添加世界请求处理接口

修改World内部实现
This commit is contained in:
walker 2023-10-09 17:36:04 +08:00
parent e7be64a2f9
commit 47f78cb54d
3 changed files with 74 additions and 34 deletions

36
examples/main.go Normal file
View File

@ -0,0 +1,36 @@
package main
import (
"fmt"
"time"
"joylink.club/ecs"
)
func main() {
sim := ecs.NewWorld(20)
sim.StartUp()
sim.Pause()
go func() {
time.Sleep(1 * time.Second)
sim.Resume()
}()
// 超出channel缓冲区超出后会阻塞
for i := 0; i < 50; i++ {
sim.Execute(func() {
fmt.Println("测试执行")
})
}
// 请求功能测试
future := ecs.Request[int](sim, func() int {
fmt.Println("执行请求")
return 20
})
result := <-future
fmt.Println("执行结果:", result)
time.Sleep(2 * time.Second)
}

15
request.go Normal file
View File

@ -0,0 +1,15 @@
package ecs
// 请求世界执行给定函数
func Request[T any](w World, fn func() T) chan T {
future := make(chan T)
w.Execute(func() {
r := fn()
select {
// 及时外面不接收也不会卡停World运行
case future <- r:
default:
}
})
return future
}

View File

@ -1,9 +1,7 @@
package ecs package ecs
import ( import (
"context"
"fmt" "fmt"
"log"
"math" "math"
"time" "time"
@ -20,6 +18,7 @@ const (
Running Running
Pause Pause
Error Error
Close
Closed Closed
) )
@ -32,21 +31,16 @@ type (
Resume() Resume()
SetSpeed(speed float64) error SetSpeed(speed float64) error
AddSystem(sys ...ISystem) AddSystem(sys ...ISystem)
// 在世界中执行逻辑(在世界运行线程中) // 在世界中执行处理逻辑(在世界运行线程中)
Execute(fn ExecuteFunc) Execute(fn HandleFunc)
Close() Close()
// 世界时间间隔 // 世界运行间隔
Tick() int Tick() int
Running() bool Running() bool
} }
// 世界执行函数
ExecuteFunc func()
RequestFunc func() any
WorldRequest struct { // 处理函数
req RequestFunc HandleFunc func()
context context.Context
}
) )
type world struct { type world struct {
@ -55,14 +49,13 @@ type world struct {
state WorldState state WorldState
tick int tick int
ticker *time.Ticker ticker *time.Ticker
speed float64 // 世界运行倍速
// 下一帧需要执行的次数 speed float64
// 下一帧系统需要执行的次数
times float64 times float64
// 退出信号
quit chan struct{}
// 待执行函数 // 待执行函数
toBeExecuteds chan ExecuteFunc toBeExecuteds chan HandleFunc
} }
// 新建一个组件类型 // 新建一个组件类型
@ -71,7 +64,7 @@ func NewComponentType[T any](opts ...interface{}) *ComponentType[T] {
return &ComponentType[T]{ct} return &ComponentType[T]{ct}
} }
// 新建一个标签注意新建的标签如果作为全局变量使用EachFirst等方法时必须在World线程中执行即调用World.Execute执行 // 新建一个标签
func NewTag() *ComponentType[struct{}] { func NewTag() *ComponentType[struct{}] {
return NewComponentType[struct{}]() return NewComponentType[struct{}]()
} }
@ -88,6 +81,9 @@ func Entries(w World, entities []donburi.Entity) []*Entry {
// 初始化一个新World // 初始化一个新World
// tick 单位为ms且必须大于0,(小于15ms的值在Windows系统中会达不到Windows系统中系统中断好像默认是15.6ms也就是一秒最多64次) // tick 单位为ms且必须大于0,(小于15ms的值在Windows系统中会达不到Windows系统中系统中断好像默认是15.6ms也就是一秒最多64次)
func NewWorld(tick int) World { func NewWorld(tick int) World {
if tick <= 0 {
panic("tick必须大于0")
}
return &world{ return &world{
World: donburi.NewWorld(), World: donburi.NewWorld(),
systems: make([]ISystem, 0), systems: make([]ISystem, 0),
@ -96,8 +92,7 @@ func NewWorld(tick int) World {
ticker: time.NewTicker(time.Duration(tick) * time.Millisecond), ticker: time.NewTicker(time.Duration(tick) * time.Millisecond),
speed: 1, speed: 1,
times: 1, times: 1,
quit: make(chan struct{}), toBeExecuteds: make(chan HandleFunc, 32),
toBeExecuteds: make(chan ExecuteFunc, 256),
} }
} }
func (w *world) Running() bool { func (w *world) Running() bool {
@ -136,7 +131,7 @@ const (
SpeedMax = 10 SpeedMax = 10
) )
// 设置世界运行 // 设置世界运行
func (w *world) SetSpeed(speed float64) error { func (w *world) SetSpeed(speed float64) error {
if speed < SpeedMin || speed > SpeedMax { if speed < SpeedMin || speed > SpeedMax {
return fmt.Errorf("速度必须在[%f, %d]之间", SpeedMin, SpeedMax) return fmt.Errorf("速度必须在[%f, %d]之间", SpeedMin, SpeedMax)
@ -154,23 +149,23 @@ func (w *world) StartUp() {
} }
// 在世界线程执行逻辑 // 在世界线程执行逻辑
func (w *world) Execute(fn ExecuteFunc) { func (w *world) Execute(fn HandleFunc) {
w.toBeExecuteds <- fn w.toBeExecuteds <- fn
} }
// 关闭世界 // 关闭世界
func (w *world) Close() { func (w *world) Close() {
w.quit <- struct{}{} w.state = Close
} }
// 执行待处理方法 // 执行待处理方法
func (w *world) executeTodos() { func (w *world) executeTodos() {
manageEventChan := w.toBeExecuteds funcs := w.toBeExecuteds
for { for {
select { select {
case callBack := <-manageEventChan: case fn := <-funcs:
{ {
callBack() fn()
} }
default: default:
return return
@ -179,19 +174,13 @@ func (w *world) executeTodos() {
} }
func (w *world) run() { func (w *world) run() {
for { for {
select {
case <-w.quit: // 退出信号
// 仿真退出,更新状态
log.Println("仿真退出,id:", w.World.Id())
w.state = Closed
default:
}
if w.state == Error { if w.state == Error {
// 世界错误,关闭世界 // 世界错误,关闭世界
return return
} }
if w.state == Closed { if w.state == Close {
// 世界正常关闭 // 世界正常关闭
w.state = Closed
return return
} }
<-w.ticker.C <-w.ticker.C