调整世界运行倍速实现方式

调整事件订阅发布接口
调整事件回调函数为待执行函数,世界添加执行接口(待考虑是否需要处理结果返回)
This commit is contained in:
walker 2023-09-21 09:41:49 +08:00
parent 5744018095
commit 03669cd1b3
4 changed files with 108 additions and 127 deletions

View File

@ -21,8 +21,6 @@ type (
} }
// 事件订阅者定义 // 事件订阅者定义
Subscriber[T any] func(w World, event T) Subscriber[T any] func(w World, event T)
// 事件管理回调定义
ManageEventFunc func()
) )
// 开启底层事件处理调试 // 开启底层事件处理调试
@ -48,40 +46,39 @@ func processAllEvents(w World) {
// 发布该类型的事件 // 发布该类型的事件
// 在world协程外执行 // 在world协程外执行
func (me *EventType[T]) Publish(wd World, event *T) { func (me *EventType[T]) Publish(wd World, event *T) {
wd.(*world).chanManageEvent <- func() { wd.Execute(func() {
me.et.Publish(wd.(*world).world, *event) me.et.Publish(wd.(*world).world, *event)
} })
} }
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
// 订阅该类型的事件 // 订阅该类型的事件
// 在world启动前执行
func (me *EventType[T]) Subscribe(wd World, subscriber Subscriber[T]) { func (me *EventType[T]) Subscribe(wd World, subscriber Subscriber[T]) {
me.subscriberMapLock.Lock() me.subscriberMapLock.Lock()
defer me.subscriberMapLock.Unlock() defer me.subscriberMapLock.Unlock()
//
subscriberKey := subscriberKey[T](wd, subscriber) subscriberKey := subscriberKey[T](wd, subscriber)
if _, exist := me.subscriberMap[subscriberKey]; !exist { if _, exist := me.subscriberMap[subscriberKey]; !exist {
me.subscriberMap[subscriberKey] = func(w donburi.World, event T) { fn := func(w donburi.World, event T) {
subscriber(wd, event) subscriber(wd, event)
} }
me.et.Subscribe(wd.(*world).world, me.subscriberMap[subscriberKey]) me.subscriberMap[subscriberKey] = fn
} else { wd.Execute(func() {
panic("重复注册事件订阅者") me.et.Subscribe(wd.(*world).world, fn)
})
} }
} }
// 取消订阅该类型的事件 // 取消订阅该类型的事件
// 在world启动前执行
func (me *EventType[T]) Unsubscribe(wd World, subscriber Subscriber[T]) { func (me *EventType[T]) Unsubscribe(wd World, subscriber Subscriber[T]) {
me.subscriberMapLock.Lock() me.subscriberMapLock.Lock()
defer me.subscriberMapLock.Unlock() defer me.subscriberMapLock.Unlock()
//
subscriberKey := subscriberKey[T](wd, subscriber) subscriberKey := subscriberKey[T](wd, subscriber)
if sub, ok := me.subscriberMap[subscriberKey]; ok { if sub, ok := me.subscriberMap[subscriberKey]; ok {
me.et.Unsubscribe(wd.(*world).world, sub) wd.Execute(func() {
delete(me.subscriberMap, subscriberKey) me.et.Unsubscribe(wd.(*world).world, sub)
delete(me.subscriberMap, subscriberKey)
})
} }
} }

View File

@ -2,7 +2,6 @@ package main
import ( import (
"fmt" "fmt"
"runtime"
"time" "time"
"joylink.club/ecs" "joylink.club/ecs"
@ -35,31 +34,17 @@ func NewSwitchSystem() *SwitchSystem {
} }
var ( var (
wd1 = ecs.NewWorld(1) wd1 = ecs.NewWorld(500)
wd2 = ecs.NewWorld(20) wd2 = ecs.NewWorld(500)
) )
// //////////////////////////////////////// // ////////////////////////////////////////
func main() { func main() {
// go world1() go world1()
// go world2() go world2()
// time.Sleep(4 * time.Second) time.Sleep(4 * time.Second)
// fireSwitchDcEventType.Publish(wd1, &FireSwitchDcEvent{Dc: true}) fireSwitchDcEventType.Publish(wd1, &FireSwitchDcEvent{Dc: true})
// fireSwitchDcEventType.Publish(wd2, &FireSwitchDcEvent{Dc: false}) 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() { func world1() {
world := wd1 world := wd1

View File

@ -1,17 +1,18 @@
package main package main
import ( import (
"time" "fmt"
"math"
"joylink.club/ecs" "strconv"
system "joylink.club/ecs/examples/rtss/sys"
) )
func main() { func main() {
w := ecs.NewWorld(1) // w := ecs.NewWorld(20)
turnoutSys := system.NewTurnoutSys() // turnoutSys := system.NewTurnoutSys()
w.AddSystem(turnoutSys) // w.AddSystem(turnoutSys)
w.StartUp() // w.StartUp()
// w.SetSpeed(10)
// for i := 0; i < 5; i++ { // for i := 0; i < 5; i++ {
// w := ecs.NewWorld(1) // w := ecs.NewWorld(1)
@ -40,5 +41,12 @@ func main() {
// // } // // }
// // }() // // }()
// } // }
time.Sleep(5 * time.Second) // time.Sleep(5 * time.Second)
f := 2.1
i := math.Floor(f)
d := f - i
fmt.Println(f, i, d)
f1, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", d), 64)
fmt.Println(f1)
} }

155
world.go
View File

@ -3,6 +3,7 @@ package ecs
import ( import (
"fmt" "fmt"
"log" "log"
"math"
"time" "time"
"github.com/yohamta/donburi" "github.com/yohamta/donburi"
@ -21,45 +22,54 @@ const (
Closed Closed
) )
type World interface { type (
World interface {
// Id returns the unique identifier for the world. // Id returns the unique identifier for the world.
Id() WorldId Id() WorldId
// Create creates a new entity with the specified components. // Create creates a new entity with the specified components.
Create(components ...donburi.IComponentType) *Entry Create(components ...donburi.IComponentType) *Entry
// CreateMany creates a new entity with the specified components. // CreateMany creates a new entity with the specified components.
CreateMany(n int, components ...donburi.IComponentType) []*Entry CreateMany(n int, components ...donburi.IComponentType) []*Entry
// Entry returns an entry for the specified entity. // Entry returns an entry for the specified entity.
Entry(entity Entity) *Entry Entry(entity Entity) *Entry
// Remove removes the specified entity. // Remove removes the specified entity.
Remove(entity Entity) Remove(entity Entity)
// Valid returns true if the specified entity is valid. // Valid returns true if the specified entity is valid.
Valid(e Entity) bool Valid(e Entity) bool
// Len returns the number of entities in the world. // Len returns the number of entities in the world.
Len() int Len() int
StartUp() StartUp()
Pause() Pause()
Resume() Resume()
SetSpeed(speed float64) error SetSpeed(speed float64) error
AddSystem(sys ...ISystem) AddSystem(sys ...ISystem)
Close() // 在世界线程执行
// 世界时间间隔 Execute(fn ExecuteFunc)
Tick() int Close()
Running() bool // 世界时间间隔
} Tick() int
Running() bool
}
// 世界执行函数
ExecuteFunc func()
)
type world struct { type world struct {
world donburi.World world donburi.World
systems []ISystem systems []ISystem
state WorldState state WorldState
tick int tick int
lastTick time.Time ticker *time.Ticker
ticker *time.Ticker speed float64
speed float64 // 下一帧需要执行的次数
times float64
quit chan struct{} // 退出信号
chanManageEvent chan ManageEventFunc quit chan struct{}
// 待执行函数
toBeExecuteds chan ExecuteFunc
} }
func NewComponentType[T any](opts ...interface{}) *ComponentType[T] { func NewComponentType[T any](opts ...interface{}) *ComponentType[T] {
@ -71,15 +81,15 @@ func NewComponentType[T any](opts ...interface{}) *ComponentType[T] {
// tick 单位为ms且必须大于0 // tick 单位为ms且必须大于0
func NewWorld(tick int) World { func NewWorld(tick int) World {
return &world{ return &world{
world: donburi.NewWorld(), world: donburi.NewWorld(),
systems: make([]ISystem, 0), systems: make([]ISystem, 0),
state: Init, state: Init,
tick: tick, tick: tick,
lastTick: time.Now(), ticker: time.NewTicker(time.Duration(tick) * time.Millisecond),
ticker: time.NewTicker(time.Duration(tick) * time.Millisecond), speed: 1,
speed: 1, times: 1,
quit: make(chan struct{}), quit: make(chan struct{}),
chanManageEvent: make(chan ManageEventFunc, 1024), toBeExecuteds: make(chan ExecuteFunc, 1024),
} }
} }
func (w *world) Running() bool { func (w *world) Running() bool {
@ -157,20 +167,9 @@ func (w *world) SetSpeed(speed float64) error {
return fmt.Errorf("速度必须在[%f, %d]之间", SpeedMin, SpeedMax) return fmt.Errorf("速度必须在[%f, %d]之间", SpeedMin, SpeedMax)
} }
w.speed = speed w.speed = speed
fmt.Println("更新速度实际tick=", w.ActualTick())
w.ticker.Reset(time.Duration(w.ActualTick()) * time.Millisecond)
return nil 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() { func (w *world) StartUp() {
if w.state == Init { // 避免重复运行 if w.state == Init { // 避免重复运行
@ -179,19 +178,19 @@ func (w *world) StartUp() {
} }
} }
// 在世界线程执行逻辑
func (w *world) Execute(fn ExecuteFunc) {
w.toBeExecuteds <- fn
}
// 关闭世界 // 关闭世界
func (w *world) Close() { func (w *world) Close() {
w.quit <- struct{}{} w.quit <- struct{}{}
} }
// 获取world与事件系统间的管道的只读引用
func (w *world) eventChanReader() <-chan ManageEventFunc {
return w.chanManageEvent
}
// 事件管理相关处理 // 事件管理相关处理
func (w *world) processManageEventFuncs() { func (w *world) processManageEventFuncs() {
manageEventChan := w.eventChanReader() manageEventChan := w.toBeExecuteds
for { for {
select { select {
case callBack := <-manageEventChan: case callBack := <-manageEventChan:
@ -224,30 +223,22 @@ func (w *world) run() {
} }
<-w.ticker.C <-w.ticker.C
if w.state == Pause { // 暂停不更新 if w.state == Pause { // 暂停不更新
// time.Sleep(1 * time.Millisecond)
continue continue
} }
// dt := time.Since(w.lastTick).Milliseconds() if w.times > 1 {
// if dt >= w.ActualTick() { times := int(math.Floor(w.times))
// // fmt.Println("仿真更新,id:", info.id) for i := 0; i < times; i++ {
// w.lastTick = time.Now() for _, sys := range w.systems {
sys.Update(w)
// for _, sys := range w.systems { }
// sys.Update(w) // 处理事件管理相关
// } w.processManageEventFuncs()
// // 处理事件管理相关 // 处理所有事件
// w.processManageEventFuncs() processAllEvents(w)
// // 处理所有事件 }
// processAllEvents(w) w.times = w.times - float64(times) + w.speed
// } } else {
// time.Sleep(15 * time.Millisecond) w.times += w.speed
for _, sys := range w.systems {
sys.Update(w)
} }
// 处理事件管理相关
w.processManageEventFuncs()
// 处理所有事件
processAllEvents(w)
} }
} }