diff --git a/events.go b/events.go index a7c16f9..f0a0196 100644 --- a/events.go +++ b/events.go @@ -47,34 +47,22 @@ func processAllEvents(w World) { // 订阅该类型的事件 func (me *EventType[T]) Subscribe(wd World, subscriber Subscriber[T]) { - if wd.GoroutineId() == currentGoId() { + wd.(*world).chanManageEvent <- func() { me.subscribe(wd, subscriber) - } else { - wd.(*world).chanManageEvent <- func() { - me.subscribe(wd, subscriber) - } } } // 取消订阅该类型的事件 func (me *EventType[T]) Unsubscribe(wd World, subscriber Subscriber[T]) { - if wd.GoroutineId() == currentGoId() { + wd.(*world).chanManageEvent <- func() { me.unsubscribe(wd, subscriber) - } else { - wd.(*world).chanManageEvent <- func() { - me.unsubscribe(wd, subscriber) - } } } // 发布该类型的事件 func (me *EventType[T]) Publish(wd World, event *T) { - if wd.GoroutineId() == currentGoId() { + wd.(*world).chanManageEvent <- func() { me.publish(wd, event) - } else { - wd.(*world).chanManageEvent <- func() { - me.publish(wd, event) - } } } diff --git a/examples/rtss-event/main.go b/examples/rtss-event/main.go index 356098d..2ea821d 100644 --- a/examples/rtss-event/main.go +++ b/examples/rtss-event/main.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "runtime" "time" "joylink.club/ecs" @@ -14,36 +15,57 @@ type FireSwitchDcEvent struct { var fireSwitchDcEventType = ecs.NewEventType[FireSwitchDcEvent]() type SwitchSystem struct { + count int } func (me *SwitchSystem) WhenFireSwitchDcEvent(w ecs.World, event FireSwitchDcEvent) { - fmt.Println("====>>>world-", w.GoroutineId(), " SwitchSystem 处理事件 :", event) + fmt.Println("====>>>world-", w.Id(), " SwitchSystem 处理事件 :", event) } func (me *SwitchSystem) Update(w ecs.World) { - fmt.Println("====>>>world-", w.GoroutineId(), " SwitchSystem update ") + me.count += 1 + fmt.Println("time: ", time.Now().Format(time.StampMilli), "====>>>world-", w.Id(), " SwitchSystem update , count: ", me.count) } -var switchSystem = &SwitchSystem{} +// var switchSystem = &SwitchSystem{} + +func NewSwitchSystem() *SwitchSystem { + return &SwitchSystem{ + 0, + } +} var ( - wd1 = ecs.NewWorld(1000) - wd2 = ecs.NewWorld(1000) + wd1 = ecs.NewWorld(1) + wd2 = ecs.NewWorld(20) ) // //////////////////////////////////////// func main() { - go world1() - go world2() - time.Sleep(4 * time.Second) - fireSwitchDcEventType.Publish(wd1, &FireSwitchDcEvent{Dc: true}) - fireSwitchDcEventType.Publish(wd2, &FireSwitchDcEvent{Dc: false}) - time.Sleep(30 * time.Second) + // go world1() + // go world2() + // time.Sleep(4 * time.Second) + // fireSwitchDcEventType.Publish(wd1, &FireSwitchDcEvent{Dc: true}) + // fireSwitchDcEventType.Publish(wd2, &FireSwitchDcEvent{Dc: false}) + + fmt.Println("当前运行系统为:", runtime.GOOS) + + wd1.AddSystem(NewSwitchSystem()) + wd1.StartUp() + + // + wd2.AddSystem(NewSwitchSystem()) + wd2.StartUp() + fmt.Println("开始", time.Now()) + + time.Sleep(5 * time.Second) + fmt.Println("结束", time.Now()) } func world1() { world := wd1 world.StartUp() // + switchSystem := NewSwitchSystem() world.AddSystem(switchSystem) // fireSwitchDcEventType.Subscribe(world, switchSystem.WhenFireSwitchDcEvent) @@ -58,6 +80,7 @@ func world2() { world := wd2 world.StartUp() // + switchSystem := NewSwitchSystem() world.AddSystem(switchSystem) fireSwitchDcEventType.Subscribe(world, switchSystem.WhenFireSwitchDcEvent) // diff --git a/go.mod b/go.mod index b58e068..d306653 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,7 @@ module joylink.club/ecs go 1.20 -require github.com/yohamta/donburi v1.3.8 +require ( + github.com/yohamta/donburi v1.3.8 + golang.org/x/time v0.3.0 +) diff --git a/go.sum b/go.sum index 9ac4ec0..dd4f7c6 100644 --- a/go.sum +++ b/go.sum @@ -3,4 +3,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/yohamta/donburi v1.3.8 h1:ca4NuhzJ8Jeb6GAEf6ecksa+l8JWaAnr0WLqG20TimU= github.com/yohamta/donburi v1.3.8/go.mod h1:5QkyraUjkzbMVTD2b8jaPFy1Uwjm/zdFN1c1lZGaezg= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= diff --git a/world.go b/world.go index 51ba15a..89a5382 100644 --- a/world.go +++ b/world.go @@ -1,11 +1,8 @@ package ecs import ( - "bytes" "fmt" "log" - "runtime" - "strconv" "time" "github.com/yohamta/donburi" @@ -47,18 +44,19 @@ type World interface { SetSpeed(speed float64) error AddSystem(sys ...ISystem) Close() + // 世界时间间隔 Tick() int Running() bool - GoroutineId() uint64 } type world struct { - gId uint64 - world donburi.World - systems []ISystem - state WorldState - tick int - speed float64 + world donburi.World + systems []ISystem + state WorldState + tick int + lastTick time.Time + ticker *time.Ticker + speed float64 quit chan struct{} chanManageEvent chan ManageEventFunc @@ -69,20 +67,21 @@ func NewComponentType[T any](opts ...interface{}) *ComponentType[T] { return &ComponentType[T]{ct} } +// 初始化一个新World +// tick 单位为ms,且必须大于0 func NewWorld(tick int) World { return &world{ world: donburi.NewWorld(), systems: make([]ISystem, 0), state: Init, tick: tick, + lastTick: time.Now(), + ticker: time.NewTicker(time.Duration(tick) * time.Millisecond), speed: 1, quit: make(chan struct{}), chanManageEvent: make(chan ManageEventFunc, 1024), } } -func (w *world) GoroutineId() uint64 { - return w.gId -} func (w *world) Running() bool { return w.state == Running } @@ -158,9 +157,20 @@ func (w *world) SetSpeed(speed float64) error { return fmt.Errorf("速度必须在[%f, %d]之间", SpeedMin, SpeedMax) } w.speed = speed + fmt.Println("更新速度,实际tick=", w.ActualTick()) + w.ticker.Reset(time.Duration(w.ActualTick()) * time.Millisecond) return nil } +// 世界实际运行频率 +func (w *world) ActualTick() int64 { + tick := int64(float64(w.tick) / (w.speed)) + if tick <= 0 { + return 1 + } + return tick +} + // 启动世界,世界逻辑开始执行且世界为运行状态 func (w *world) StartUp() { if w.state == Init { // 避免重复运行 @@ -196,30 +206,42 @@ func (w *world) processManageEventFuncs() { } func (w *world) run() { - w.gId = currentGoId() for { select { case <-w.quit: // 退出信号 + // 仿真退出,更新状态 log.Println("仿真退出,id:", w.world.Id()) w.state = Closed default: } if w.state == Error { - log.Println("世界错误,关闭世界,id:", w.world.Id()) + // 世界错误,关闭世界 return } if w.state == Closed { - log.Println("世界正常关闭,id:", w.world.Id()) + // 世界正常关闭 return } + <-w.ticker.C if w.state == Pause { // 暂停不更新 - log.Println("仿真暂停中,id:", w.world.Id()) - sleep := int64(float64(w.tick) / (w.speed)) - time.Sleep(time.Duration(sleep) * time.Millisecond) + // time.Sleep(1 * time.Millisecond) continue } - start := time.Now() - // fmt.Println("仿真更新,id:", info.id) + // dt := time.Since(w.lastTick).Milliseconds() + // if dt >= w.ActualTick() { + // // fmt.Println("仿真更新,id:", info.id) + // w.lastTick = time.Now() + + // for _, sys := range w.systems { + // sys.Update(w) + // } + // // 处理事件管理相关 + // w.processManageEventFuncs() + // // 处理所有事件 + // processAllEvents(w) + // } + // time.Sleep(15 * time.Millisecond) + for _, sys := range w.systems { sys.Update(w) } @@ -227,27 +249,5 @@ func (w *world) run() { w.processManageEventFuncs() // 处理所有事件 processAllEvents(w) - // 执行逻辑花费时间,单位ms - ot := time.Duration(time.Now().Nanosecond() - start.Nanosecond()).Milliseconds() - // 根据间隔和速度计算休眠时间 - sleep := int64(float64(w.tick)/(w.speed)) - ot - if sleep > 0 { - time.Sleep(time.Duration(sleep) * time.Millisecond) - } else { - log.Println("仿真无休眠,id:", w.world.Id()) - } } } - -// 获取当前协程id -func currentGoId() (gid uint64) { - b := make([]byte, 16) - b = b[:runtime.Stack(b, false)] - b = bytes.TrimPrefix(b, []byte("goroutine ")) - b = b[:bytes.IndexByte(b, ' ')] - n, err := strconv.ParseUint(string(b), 10, 64) - if err != nil { - panic(err) - } - return n -}