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

调整事件订阅发布接口
调整事件回调函数为待执行函数,世界添加执行接口(待考虑是否需要处理结果返回)
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)
// 事件管理回调定义
ManageEventFunc func()
)
// 开启底层事件处理调试
@ -48,40 +46,39 @@ func processAllEvents(w World) {
// 发布该类型的事件
// 在world协程外执行
func (me *EventType[T]) Publish(wd World, event *T) {
wd.(*world).chanManageEvent <- func() {
wd.Execute(func() {
me.et.Publish(wd.(*world).world, *event)
}
})
}
///////////////////////////////////////////////////////////////////////////////////
// 订阅该类型的事件
// 在world启动前执行
func (me *EventType[T]) Subscribe(wd World, subscriber Subscriber[T]) {
me.subscriberMapLock.Lock()
defer me.subscriberMapLock.Unlock()
//
subscriberKey := subscriberKey[T](wd, subscriber)
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)
}
me.et.Subscribe(wd.(*world).world, me.subscriberMap[subscriberKey])
} else {
panic("重复注册事件订阅者")
me.subscriberMap[subscriberKey] = fn
wd.Execute(func() {
me.et.Subscribe(wd.(*world).world, fn)
})
}
}
// 取消订阅该类型的事件
// 在world启动前执行
func (me *EventType[T]) Unsubscribe(wd World, subscriber Subscriber[T]) {
me.subscriberMapLock.Lock()
defer me.subscriberMapLock.Unlock()
//
subscriberKey := subscriberKey[T](wd, subscriber)
if sub, ok := me.subscriberMap[subscriberKey]; ok {
me.et.Unsubscribe(wd.(*world).world, sub)
delete(me.subscriberMap, subscriberKey)
wd.Execute(func() {
me.et.Unsubscribe(wd.(*world).world, sub)
delete(me.subscriberMap, subscriberKey)
})
}
}

View File

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

View File

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