删除goroutineid及相关逻辑
修改世界运行逻辑循环从使用睡眠改为使用Ticker(睡眠会有因go调度产生的额外几毫秒时间问题)
This commit is contained in:
parent
c3b9d965c6
commit
cbb36d8c08
18
events.go
18
events.go
@ -47,34 +47,22 @@ func processAllEvents(w World) {
|
|||||||
|
|
||||||
// 订阅该类型的事件
|
// 订阅该类型的事件
|
||||||
func (me *EventType[T]) Subscribe(wd World, subscriber Subscriber[T]) {
|
func (me *EventType[T]) Subscribe(wd World, subscriber Subscriber[T]) {
|
||||||
if wd.GoroutineId() == currentGoId() {
|
wd.(*world).chanManageEvent <- func() {
|
||||||
me.subscribe(wd, subscriber)
|
me.subscribe(wd, subscriber)
|
||||||
} else {
|
|
||||||
wd.(*world).chanManageEvent <- func() {
|
|
||||||
me.subscribe(wd, subscriber)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 取消订阅该类型的事件
|
// 取消订阅该类型的事件
|
||||||
func (me *EventType[T]) Unsubscribe(wd World, subscriber Subscriber[T]) {
|
func (me *EventType[T]) Unsubscribe(wd World, subscriber Subscriber[T]) {
|
||||||
if wd.GoroutineId() == currentGoId() {
|
wd.(*world).chanManageEvent <- func() {
|
||||||
me.unsubscribe(wd, subscriber)
|
me.unsubscribe(wd, subscriber)
|
||||||
} else {
|
|
||||||
wd.(*world).chanManageEvent <- func() {
|
|
||||||
me.unsubscribe(wd, subscriber)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发布该类型的事件
|
// 发布该类型的事件
|
||||||
func (me *EventType[T]) Publish(wd World, event *T) {
|
func (me *EventType[T]) Publish(wd World, event *T) {
|
||||||
if wd.GoroutineId() == currentGoId() {
|
wd.(*world).chanManageEvent <- func() {
|
||||||
me.publish(wd, event)
|
me.publish(wd, event)
|
||||||
} else {
|
|
||||||
wd.(*world).chanManageEvent <- func() {
|
|
||||||
me.publish(wd, event)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"joylink.club/ecs"
|
"joylink.club/ecs"
|
||||||
@ -14,36 +15,57 @@ type FireSwitchDcEvent struct {
|
|||||||
var fireSwitchDcEventType = ecs.NewEventType[FireSwitchDcEvent]()
|
var fireSwitchDcEventType = ecs.NewEventType[FireSwitchDcEvent]()
|
||||||
|
|
||||||
type SwitchSystem struct {
|
type SwitchSystem struct {
|
||||||
|
count int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (me *SwitchSystem) WhenFireSwitchDcEvent(w ecs.World, event FireSwitchDcEvent) {
|
func (me *SwitchSystem) WhenFireSwitchDcEvent(w ecs.World, event FireSwitchDcEvent) {
|
||||||
fmt.Println("====>>>world-", w.GoroutineId(), " SwitchSystem 处理事件 :", event)
|
fmt.Println("====>>>world-", w.Id(), " SwitchSystem 处理事件 :", event)
|
||||||
}
|
}
|
||||||
func (me *SwitchSystem) Update(w ecs.World) {
|
func (me *SwitchSystem) Update(w ecs.World) {
|
||||||
fmt.Println("====>>>world-", w.GoroutineId(), " SwitchSystem update ")
|
me.count += 1
|
||||||
|
fmt.Println("time: ", time.Now().Format(time.StampMilli), "====>>>world-", w.Id(), " SwitchSystem update , count: ", me.count)
|
||||||
}
|
}
|
||||||
|
|
||||||
var switchSystem = &SwitchSystem{}
|
// var switchSystem = &SwitchSystem{}
|
||||||
|
|
||||||
|
func NewSwitchSystem() *SwitchSystem {
|
||||||
|
return &SwitchSystem{
|
||||||
|
0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
wd1 = ecs.NewWorld(1000)
|
wd1 = ecs.NewWorld(1)
|
||||||
wd2 = ecs.NewWorld(1000)
|
wd2 = ecs.NewWorld(20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// ////////////////////////////////////////
|
// ////////////////////////////////////////
|
||||||
func main() {
|
func main() {
|
||||||
go world1()
|
// go world1()
|
||||||
go world2()
|
// go world2()
|
||||||
time.Sleep(4 * time.Second)
|
// time.Sleep(4 * time.Second)
|
||||||
fireSwitchDcEventType.Publish(wd1, &FireSwitchDcEvent{Dc: true})
|
// fireSwitchDcEventType.Publish(wd1, &FireSwitchDcEvent{Dc: true})
|
||||||
fireSwitchDcEventType.Publish(wd2, &FireSwitchDcEvent{Dc: false})
|
// fireSwitchDcEventType.Publish(wd2, &FireSwitchDcEvent{Dc: false})
|
||||||
time.Sleep(30 * time.Second)
|
|
||||||
|
fmt.Println("当前运行系统为:", runtime.GOOS)
|
||||||
|
|
||||||
|
wd1.AddSystem(NewSwitchSystem())
|
||||||
|
wd1.StartUp()
|
||||||
|
|
||||||
|
//
|
||||||
|
wd2.AddSystem(NewSwitchSystem())
|
||||||
|
wd2.StartUp()
|
||||||
|
fmt.Println("开始", time.Now())
|
||||||
|
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
fmt.Println("结束", time.Now())
|
||||||
|
|
||||||
}
|
}
|
||||||
func world1() {
|
func world1() {
|
||||||
world := wd1
|
world := wd1
|
||||||
world.StartUp()
|
world.StartUp()
|
||||||
//
|
//
|
||||||
|
switchSystem := NewSwitchSystem()
|
||||||
world.AddSystem(switchSystem)
|
world.AddSystem(switchSystem)
|
||||||
//
|
//
|
||||||
fireSwitchDcEventType.Subscribe(world, switchSystem.WhenFireSwitchDcEvent)
|
fireSwitchDcEventType.Subscribe(world, switchSystem.WhenFireSwitchDcEvent)
|
||||||
@ -58,6 +80,7 @@ func world2() {
|
|||||||
world := wd2
|
world := wd2
|
||||||
world.StartUp()
|
world.StartUp()
|
||||||
//
|
//
|
||||||
|
switchSystem := NewSwitchSystem()
|
||||||
world.AddSystem(switchSystem)
|
world.AddSystem(switchSystem)
|
||||||
fireSwitchDcEventType.Subscribe(world, switchSystem.WhenFireSwitchDcEvent)
|
fireSwitchDcEventType.Subscribe(world, switchSystem.WhenFireSwitchDcEvent)
|
||||||
//
|
//
|
||||||
|
5
go.mod
5
go.mod
@ -2,4 +2,7 @@ module joylink.club/ecs
|
|||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require github.com/yohamta/donburi v1.3.8
|
require (
|
||||||
|
github.com/yohamta/donburi v1.3.8
|
||||||
|
golang.org/x/time v0.3.0
|
||||||
|
)
|
||||||
|
2
go.sum
2
go.sum
@ -3,4 +3,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||||||
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
||||||
github.com/yohamta/donburi v1.3.8 h1:ca4NuhzJ8Jeb6GAEf6ecksa+l8JWaAnr0WLqG20TimU=
|
github.com/yohamta/donburi v1.3.8 h1:ca4NuhzJ8Jeb6GAEf6ecksa+l8JWaAnr0WLqG20TimU=
|
||||||
github.com/yohamta/donburi v1.3.8/go.mod h1:5QkyraUjkzbMVTD2b8jaPFy1Uwjm/zdFN1c1lZGaezg=
|
github.com/yohamta/donburi v1.3.8/go.mod h1:5QkyraUjkzbMVTD2b8jaPFy1Uwjm/zdFN1c1lZGaezg=
|
||||||
|
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||||
|
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
|
86
world.go
86
world.go
@ -1,11 +1,8 @@
|
|||||||
package ecs
|
package ecs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/yohamta/donburi"
|
"github.com/yohamta/donburi"
|
||||||
@ -47,18 +44,19 @@ type World interface {
|
|||||||
SetSpeed(speed float64) error
|
SetSpeed(speed float64) error
|
||||||
AddSystem(sys ...ISystem)
|
AddSystem(sys ...ISystem)
|
||||||
Close()
|
Close()
|
||||||
|
// 世界时间间隔
|
||||||
Tick() int
|
Tick() int
|
||||||
Running() bool
|
Running() bool
|
||||||
GoroutineId() uint64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type world struct {
|
type world struct {
|
||||||
gId uint64
|
world donburi.World
|
||||||
world donburi.World
|
systems []ISystem
|
||||||
systems []ISystem
|
state WorldState
|
||||||
state WorldState
|
tick int
|
||||||
tick int
|
lastTick time.Time
|
||||||
speed float64
|
ticker *time.Ticker
|
||||||
|
speed float64
|
||||||
|
|
||||||
quit chan struct{}
|
quit chan struct{}
|
||||||
chanManageEvent chan ManageEventFunc
|
chanManageEvent chan ManageEventFunc
|
||||||
@ -69,20 +67,21 @@ func NewComponentType[T any](opts ...interface{}) *ComponentType[T] {
|
|||||||
return &ComponentType[T]{ct}
|
return &ComponentType[T]{ct}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化一个新World
|
||||||
|
// tick 单位为ms,且必须大于0
|
||||||
func NewWorld(tick int) World {
|
func NewWorld(tick int) World {
|
||||||
return &world{
|
return &world{
|
||||||
world: donburi.NewWorld(),
|
world: donburi.NewWorld(),
|
||||||
systems: make([]ISystem, 0),
|
systems: make([]ISystem, 0),
|
||||||
state: Init,
|
state: Init,
|
||||||
tick: tick,
|
tick: tick,
|
||||||
|
lastTick: time.Now(),
|
||||||
|
ticker: time.NewTicker(time.Duration(tick) * time.Millisecond),
|
||||||
speed: 1,
|
speed: 1,
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
chanManageEvent: make(chan ManageEventFunc, 1024),
|
chanManageEvent: make(chan ManageEventFunc, 1024),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (w *world) GoroutineId() uint64 {
|
|
||||||
return w.gId
|
|
||||||
}
|
|
||||||
func (w *world) Running() bool {
|
func (w *world) Running() bool {
|
||||||
return w.state == Running
|
return w.state == Running
|
||||||
}
|
}
|
||||||
@ -158,9 +157,20 @@ func (w *world) SetSpeed(speed float64) error {
|
|||||||
return fmt.Errorf("速度必须在[%f, %d]之间", SpeedMin, SpeedMax)
|
return fmt.Errorf("速度必须在[%f, %d]之间", SpeedMin, SpeedMax)
|
||||||
}
|
}
|
||||||
w.speed = speed
|
w.speed = speed
|
||||||
|
fmt.Println("更新速度,实际tick=", w.ActualTick())
|
||||||
|
w.ticker.Reset(time.Duration(w.ActualTick()) * time.Millisecond)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 世界实际运行频率
|
||||||
|
func (w *world) ActualTick() int64 {
|
||||||
|
tick := int64(float64(w.tick) / (w.speed))
|
||||||
|
if tick <= 0 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return tick
|
||||||
|
}
|
||||||
|
|
||||||
// 启动世界,世界逻辑开始执行且世界为运行状态
|
// 启动世界,世界逻辑开始执行且世界为运行状态
|
||||||
func (w *world) StartUp() {
|
func (w *world) StartUp() {
|
||||||
if w.state == Init { // 避免重复运行
|
if w.state == Init { // 避免重复运行
|
||||||
@ -196,30 +206,42 @@ func (w *world) processManageEventFuncs() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
func (w *world) run() {
|
func (w *world) run() {
|
||||||
w.gId = currentGoId()
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-w.quit: // 退出信号
|
case <-w.quit: // 退出信号
|
||||||
|
// 仿真退出,更新状态
|
||||||
log.Println("仿真退出,id:", w.world.Id())
|
log.Println("仿真退出,id:", w.world.Id())
|
||||||
w.state = Closed
|
w.state = Closed
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
if w.state == Error {
|
if w.state == Error {
|
||||||
log.Println("世界错误,关闭世界,id:", w.world.Id())
|
// 世界错误,关闭世界
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if w.state == Closed {
|
if w.state == Closed {
|
||||||
log.Println("世界正常关闭,id:", w.world.Id())
|
// 世界正常关闭
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
<-w.ticker.C
|
||||||
if w.state == Pause { // 暂停不更新
|
if w.state == Pause { // 暂停不更新
|
||||||
log.Println("仿真暂停中,id:", w.world.Id())
|
// time.Sleep(1 * time.Millisecond)
|
||||||
sleep := int64(float64(w.tick) / (w.speed))
|
|
||||||
time.Sleep(time.Duration(sleep) * time.Millisecond)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
start := time.Now()
|
// dt := time.Since(w.lastTick).Milliseconds()
|
||||||
// fmt.Println("仿真更新,id:", info.id)
|
// if dt >= w.ActualTick() {
|
||||||
|
// // fmt.Println("仿真更新,id:", info.id)
|
||||||
|
// w.lastTick = time.Now()
|
||||||
|
|
||||||
|
// for _, sys := range w.systems {
|
||||||
|
// sys.Update(w)
|
||||||
|
// }
|
||||||
|
// // 处理事件管理相关
|
||||||
|
// w.processManageEventFuncs()
|
||||||
|
// // 处理所有事件
|
||||||
|
// processAllEvents(w)
|
||||||
|
// }
|
||||||
|
// time.Sleep(15 * time.Millisecond)
|
||||||
|
|
||||||
for _, sys := range w.systems {
|
for _, sys := range w.systems {
|
||||||
sys.Update(w)
|
sys.Update(w)
|
||||||
}
|
}
|
||||||
@ -227,27 +249,5 @@ func (w *world) run() {
|
|||||||
w.processManageEventFuncs()
|
w.processManageEventFuncs()
|
||||||
// 处理所有事件
|
// 处理所有事件
|
||||||
processAllEvents(w)
|
processAllEvents(w)
|
||||||
// 执行逻辑花费时间,单位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())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取当前协程id
|
|
||||||
func currentGoId() (gid uint64) {
|
|
||||||
b := make([]byte, 16)
|
|
||||||
b = b[:runtime.Stack(b, false)]
|
|
||||||
b = bytes.TrimPrefix(b, []byte("goroutine "))
|
|
||||||
b = b[:bytes.IndexByte(b, ' ')]
|
|
||||||
n, err := strconv.ParseUint(string(b), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user