package ecs import ( "fmt" "log" "reflect" "time" "github.com/yohamta/donburi" "github.com/yohamta/donburi/features/events" ) type WorldState int type WorldId int const ( Init WorldState = iota Running Pause Error Closed ) 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 StartUp() Pause() Resume() SetSpeed(speed float64) error AddSystem(sys ...ISystem) Close() Tick() int Running() bool } type world struct { world donburi.World systems []ISystem state WorldState tick int speed float64 quit chan struct{} } func NewComponentType[T any](opts ...interface{}) *ComponentType[T] { ct := donburi.NewComponentType[T](opts...) return &ComponentType[T]{ct} } func NewWorld(tick int) World { return &world{ world: donburi.NewWorld(), systems: make([]ISystem, 0), state: Init, tick: tick, speed: 1, quit: make(chan struct{}), } } func (w *world) Running() bool { return w.state == Running } func (w *world) Tick() int { return w.tick } func (w *world) Id() WorldId { return WorldId(w.world.Id()) } func (w *world) Create(components ...donburi.IComponentType) *Entry { entity := w.world.Create(components...) return &Entry{w.world.Entry(entity)} } func (w *world) CreateMany(n int, components ...donburi.IComponentType) []*Entry { entitys := w.world.CreateMany(n, components...) ets := make([]*Entry, len(entitys)) for i, e := range entitys { ets[i] = &Entry{w.world.Entry(e)} } return ets } func (w *world) Entry(entity Entity) *Entry { return &Entry{w.world.Entry(entity.Entity)} } func (w *world) Remove(entity Entity) { w.world.Remove(entity.Entity) } func (w *world) Valid(e Entity) bool { return w.world.Valid(e.Entity) } func (w *world) Len() int { return w.world.Len() } // 添加系统 func (w *world) AddSystem(sys ...ISystem) { w.systems = append(w.systems, sys...) } // 执行所有事件处理 func (w *world) ProcessAllEvents() { events.ProcessAllEvents(w.world) } // 暂停世界 func (w *world) Pause() { if w.state == Running { w.state = Pause } } // 恢复世界运行 func (w *world) Resume() { if w.state == Pause { w.state = Running } } const ( SpeedMin = 0.1 SpeedMax = 10 ) // 设置世界运行速度 func (w *world) SetSpeed(speed float64) error { if speed < SpeedMin || speed > SpeedMax { return fmt.Errorf("速度必须在[%f, %d]之间", SpeedMin, SpeedMax) } w.speed = speed return nil } // 启动世界,世界逻辑开始执行且世界为运行状态 func (w *world) StartUp() { if w.state == Init { // 避免重复运行 w.state = Running go w.run() } } // 关闭世界 func (w *world) Close() { w.quit <- struct{}{} } func (w *world) run() { 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 } if w.state == Pause { // 暂停不更新 log.Println("仿真暂停中,id:", w.world.Id()) sleep := int64(float64(w.tick) / (w.speed)) time.Sleep(time.Duration(sleep) * time.Millisecond) continue } start := time.Now() // fmt.Println("仿真更新,id:", info.id) for _, sys := range w.systems { sys.Update(w) } // 处理所有事件 // w.ProcessAllEvents() // 执行逻辑花费时间,单位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()) } } } func NewEventType[T any](w World) *EventType[T] { // events.NewEventType() ct := NewComponentType[T]() var et T name := reflect.TypeOf(et).Name() return &EventType[T]{ name, ct, w, } }