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