调整仿真运行逻辑
完善仿真状态切换逻辑 添加仿真状态变更事件可由外部监听
This commit is contained in:
parent
e779734672
commit
74c0211614
@ -38,13 +38,11 @@ func NewEventType[T any]() *EventType[T] {
|
||||
}
|
||||
|
||||
// 迭代处理所有事件
|
||||
// 在world协程中执行
|
||||
func processAllEvents(w World) {
|
||||
events.ProcessAllEvents(w)
|
||||
}
|
||||
|
||||
// 发布该类型的事件
|
||||
// 在world协程外执行
|
||||
func (me *EventType[T]) Publish(wd World, event *T) {
|
||||
wd.Execute(func() {
|
||||
me.et.Publish(wd, *event)
|
||||
|
37
examples/close/main.go
Normal file
37
examples/close/main.go
Normal file
@ -0,0 +1,37 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"joylink.club/ecs"
|
||||
)
|
||||
|
||||
type WorldTimeSys struct {
|
||||
}
|
||||
|
||||
func (s *WorldTimeSys) Update(w ecs.World) {
|
||||
slog.Info("世界更新")
|
||||
// panic("更新异常")
|
||||
}
|
||||
|
||||
func main() {
|
||||
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug})))
|
||||
w := ecs.NewWorld(15)
|
||||
// ecs.EventsDebugEnable()
|
||||
ecs.WorldStateChangeEvent.Subscribe(w, func(_ ecs.World, e ecs.WorldStateChange) {
|
||||
slog.Info("世界状态变更", "statechange", e)
|
||||
if e.NewState == ecs.WorldClosed {
|
||||
panic("状态变更监听处理异常")
|
||||
}
|
||||
})
|
||||
slog.Info("世界启动")
|
||||
w.AddSystem(&WorldTimeSys{})
|
||||
w.StartUp()
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
w.Close()
|
||||
|
||||
time.Sleep(4 * time.Second)
|
||||
}
|
146
world.go
146
world.go
@ -15,35 +15,49 @@ type WorldState int
|
||||
type WorldId = donburi.WorldId
|
||||
|
||||
const (
|
||||
Init WorldState = iota
|
||||
Running
|
||||
Pause
|
||||
Error
|
||||
Close
|
||||
Closed
|
||||
WorldInit WorldState = iota
|
||||
WorldRunning
|
||||
WorldPause
|
||||
WorldError
|
||||
WorldClose
|
||||
WorldClosed
|
||||
)
|
||||
|
||||
type (
|
||||
World interface {
|
||||
donburi.World
|
||||
|
||||
// 世界运行间隔时间
|
||||
Tick() int
|
||||
// 启动世界
|
||||
StartUp()
|
||||
// 暂停世界
|
||||
Pause()
|
||||
// 恢复世界
|
||||
Resume()
|
||||
// 关闭世界
|
||||
Close()
|
||||
// 设置时间运行倍速
|
||||
SetSpeed(speed float64) error
|
||||
// 添加系统
|
||||
AddSystem(sys ...ISystem)
|
||||
// 在世界中执行处理逻辑(在世界运行线程中)
|
||||
Execute(fn HandleFunc)
|
||||
Close()
|
||||
// 世界运行间隔
|
||||
Tick() int
|
||||
Running() bool
|
||||
}
|
||||
|
||||
// 处理函数
|
||||
HandleFunc func()
|
||||
|
||||
// 世界状态变更消息
|
||||
WorldStateChange struct {
|
||||
OldState WorldState
|
||||
NewState WorldState
|
||||
}
|
||||
)
|
||||
|
||||
// 世界状态变更事件
|
||||
var WorldStateChangeEvent = NewEventType[WorldStateChange]()
|
||||
|
||||
type world struct {
|
||||
donburi.World
|
||||
systems []ISystem
|
||||
@ -88,7 +102,7 @@ func NewWorld(tick int) World {
|
||||
return &world{
|
||||
World: donburi.NewWorld(),
|
||||
systems: make([]ISystem, 0),
|
||||
state: Init,
|
||||
state: WorldInit,
|
||||
tick: tick,
|
||||
ticker: time.NewTicker(time.Duration(tick) * time.Millisecond),
|
||||
speed: 1,
|
||||
@ -97,7 +111,7 @@ func NewWorld(tick int) World {
|
||||
}
|
||||
}
|
||||
func (w *world) Running() bool {
|
||||
return w.state == Running
|
||||
return w.state == WorldRunning
|
||||
}
|
||||
func (w *world) Tick() int {
|
||||
return w.tick
|
||||
@ -115,27 +129,48 @@ func (w *world) ProcessAllEvents() {
|
||||
|
||||
// 暂停世界
|
||||
func (w *world) Pause() {
|
||||
if w.state == Running {
|
||||
w.state = Pause
|
||||
if w.state == WorldRunning {
|
||||
w.updateState(WorldPause)
|
||||
}
|
||||
}
|
||||
|
||||
// 恢复世界运行
|
||||
func (w *world) Resume() {
|
||||
if w.state == Pause {
|
||||
w.state = Running
|
||||
if w.state == WorldPause {
|
||||
w.updateState(WorldRunning)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *world) updateState(state WorldState) {
|
||||
if w.state != state {
|
||||
old := w.state
|
||||
slog.Debug("世界状态变更", "oldstate", old, "state", state)
|
||||
w.state = state
|
||||
WorldStateChangeEvent.Publish(w, &WorldStateChange{
|
||||
OldState: old,
|
||||
NewState: state,
|
||||
})
|
||||
WorldStateChangeEvent.et.ProcessEvents(w)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
SpeedMin = 0.1
|
||||
SpeedMax = 10
|
||||
speedMin = 0.1
|
||||
speedMax = 10
|
||||
)
|
||||
|
||||
func WorldSpeedMax() float64 {
|
||||
return speedMax
|
||||
}
|
||||
|
||||
func WorldSpeedMin() float64 {
|
||||
return speedMin
|
||||
}
|
||||
|
||||
// 设置世界运行倍速
|
||||
func (w *world) SetSpeed(speed float64) error {
|
||||
if speed < SpeedMin || speed > SpeedMax {
|
||||
return fmt.Errorf("速度必须在[%f, %d]之间", SpeedMin, SpeedMax)
|
||||
if speed < speedMin || speed > speedMax {
|
||||
return fmt.Errorf("世界倍速必须在[%f, %d]之间", speedMin, speedMax)
|
||||
}
|
||||
w.speed = speed
|
||||
return nil
|
||||
@ -143,8 +178,8 @@ func (w *world) SetSpeed(speed float64) error {
|
||||
|
||||
// 启动世界,世界逻辑开始执行且世界为运行状态
|
||||
func (w *world) StartUp() {
|
||||
if w.state == Init { // 避免重复运行
|
||||
w.state = Running
|
||||
if w.state == WorldInit { // 避免重复运行
|
||||
w.updateState(WorldRunning)
|
||||
go w.run()
|
||||
}
|
||||
}
|
||||
@ -156,7 +191,12 @@ func (w *world) Execute(fn HandleFunc) {
|
||||
|
||||
// 关闭世界
|
||||
func (w *world) Close() {
|
||||
w.state = Close
|
||||
if w.state == WorldRunning || w.state == WorldPause {
|
||||
w.updateState(WorldClose)
|
||||
} else if w.state == WorldError {
|
||||
w.updateState(WorldClosed)
|
||||
w.handleRequestAndEvent()
|
||||
}
|
||||
}
|
||||
|
||||
// 执行待处理方法
|
||||
@ -173,38 +213,32 @@ func (w *world) executeTodos() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 世界循环
|
||||
func (w *world) run() {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
slog.Error("世界运行异常:", "stacks", err)
|
||||
w.state = Error
|
||||
w.exception(err)
|
||||
}
|
||||
}()
|
||||
for {
|
||||
if w.state == Error {
|
||||
// 世界错误,关闭世界
|
||||
return
|
||||
}
|
||||
if w.state == Close {
|
||||
for range w.ticker.C {
|
||||
if w.state == WorldClose {
|
||||
// 世界正常关闭
|
||||
w.state = Closed
|
||||
w.close()
|
||||
return
|
||||
}
|
||||
<-w.ticker.C
|
||||
// start := time.Now()
|
||||
if w.state == Pause { // 暂停不更新
|
||||
if w.state != WorldRunning { // 世界非运行状态
|
||||
w.handleRequestAndEvent()
|
||||
continue
|
||||
}
|
||||
if w.times > 1 {
|
||||
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.executeTodos()
|
||||
// 处理所有事件
|
||||
processAllEvents(w)
|
||||
w.handleRequestAndEvent()
|
||||
}
|
||||
w.times = w.times - float64(times) + w.speed
|
||||
} else {
|
||||
@ -214,3 +248,37 @@ func (w *world) run() {
|
||||
// slog.Info("仿真系统执行耗时:" + dt.Milliseconds() + "ms")
|
||||
}
|
||||
}
|
||||
|
||||
// 处理请求和事件执行
|
||||
func (w *world) handleRequestAndEvent() {
|
||||
// 执行待执行逻辑
|
||||
w.executeTodos()
|
||||
// 处理所有事件
|
||||
processAllEvents(w)
|
||||
}
|
||||
|
||||
// 世界运行异常处理
|
||||
func (w *world) exception(err any) {
|
||||
slog.Error("世界出现异常", "error", err)
|
||||
w.updateState(WorldError)
|
||||
// // 关闭定时器
|
||||
// w.ticker.Stop()
|
||||
w.handleRequestAndEvent()
|
||||
}
|
||||
|
||||
// 世界正常关闭逻辑
|
||||
func (w *world) close() {
|
||||
// 世界正常关闭
|
||||
w.updateState(WorldClosed)
|
||||
// 关闭定时器
|
||||
w.ticker.Stop()
|
||||
go func() {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
slog.Error("世界关闭监听处理可能异常", "error", err)
|
||||
}
|
||||
}()
|
||||
w.handleRequestAndEvent()
|
||||
}()
|
||||
slog.Debug("世界关闭finish")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user