添加世界请求处理接口

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