parent
e7be64a2f9
commit
47f78cb54d
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
57
world.go
57
world.go
|
@ -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}
|
||||
}
|
||||
|
||||
// 新建一个标签(注意:新建的标签如果作为全局变量,使用Each,First等方法时必须在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
|
||||
|
|
Loading…
Reference in New Issue