From 9198faa06140404f947bf954e36d3d94975ee46a Mon Sep 17 00:00:00 2001 From: kercylan98 Date: Tue, 1 Aug 2023 10:04:30 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20fight=20=E5=8C=85=E7=9A=84=20Round=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=93=8D=E4=BD=9C=E8=B6=85=E6=97=B6=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=EF=BC=8C=E4=BC=98=E5=8C=96=E4=BA=8B=E4=BB=B6=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/fight/round.go | 106 +++++++++++++++++++++++++++--------- game/fight/round_options.go | 19 +++++-- game/fight/round_test.go | 12 ++-- 3 files changed, 99 insertions(+), 38 deletions(-) diff --git a/game/fight/round.go b/game/fight/round.go index 6c195ee..4a17661 100644 --- a/game/fight/round.go +++ b/game/fight/round.go @@ -3,6 +3,7 @@ package fight import ( "fmt" "github.com/kercylan98/minotaur/utils/random" + "github.com/kercylan98/minotaur/utils/slice" "github.com/kercylan98/minotaur/utils/timer" "time" ) @@ -16,10 +17,12 @@ type RoundGameOverVerifyHandle[Data RoundData] func(round *Round[Data]) bool // - roundGameOverVerifyHandle 游戏结束验证函数 // - options 选项 func NewRound[Data RoundData](data Data, camps []*RoundCamp, roundGameOverVerifyHandle RoundGameOverVerifyHandle[Data], options ...RoundOption[Data]) *Round[Data] { + mark := random.HostName() round := &Round[Data]{ + mark: mark, data: data, camps: make(map[int][]int), - actionTimeoutTickerName: fmt.Sprintf("round_action_timeout_%s", random.HostName()), + actionTimeoutTickerName: fmt.Sprintf("round_action_timeout_%s", mark), roundGameOverVerifyHandle: roundGameOverVerifyHandle, } for _, camp := range camps { @@ -30,13 +33,14 @@ func NewRound[Data RoundData](data Data, camps []*RoundCamp, roundGameOverVerify option(round) } if round.ticker == nil { - round.ticker = timer.GetTicker(5) + round.ticker = timer.GetTicker(5, timer.WithMark(mark)) } return round } // Round 回合制游戏结构 type Round[Data RoundData] struct { + mark string // 标记 data Data // 游戏数据 ticker *timer.Ticker // 计时器 camps map[int][]int // 阵营 @@ -53,10 +57,11 @@ type Round[Data RoundData] struct { campCounterclockwise bool // 是否阵营逆时针 entityCounterclockwise bool // 是否对象逆时针 - swapCampEventHandles []RoundSwapCampEvent[Data] // 阵营交换事件 - swapEntityEventHandles []RoundSwapEntityEvent[Data] // 实体交换事件 - gameOverEventHandles []RoundGameOverEvent[Data] // 游戏结束事件 - changeEventHandles []RoundChangeEvent[Data] // 游戏回合变更事件 + swapCampEventHandles []RoundSwapCampEvent[Data] // 阵营交换事件 + swapEntityEventHandles []RoundSwapEntityEvent[Data] // 实体交换事件 + gameOverEventHandles []RoundGameOverEvent[Data] // 游戏结束事件 + changeEventHandles []RoundChangeEvent[Data] // 游戏回合变更事件 + actionTimeoutEventHandles []RoundActionTimeoutEvent[Data] // 行动超时事件 } // GetData 获取游戏数据 @@ -69,15 +74,25 @@ func (slf *Round[Data]) GetData() Data { func (slf *Round[Data]) Run() { slf.currentEntity = -1 slf.round = 1 - slf.loop() + slf.loop(false) } -func (slf *Round[Data]) loop() { +// Release 释放游戏 +func (slf *Round[Data]) Release() { + if slf.mark == slf.ticker.Mark() { + slf.ticker.Release() + return + } slf.ticker.StopTimer(slf.actionTimeoutTickerName) +} + +func (slf *Round[Data]) loop(timeout bool) { + slf.ticker.StopTimer(slf.actionTimeoutTickerName) + if timeout { + slf.OnActionTimeoutEvent() + } if slf.roundGameOverVerifyHandle(slf) { - for _, handle := range slf.gameOverEventHandles { - handle(slf) - } + slf.OnGameOverEvent() return } else { slf.ActionRefresh() @@ -96,22 +111,22 @@ func (slf *Round[Data]) loop() { if slf.roundCount > len(slf.camps) { slf.round++ slf.roundCount = 1 - for _, handle := range slf.changeEventHandles { - handle(slf) - } - } - for _, handle := range slf.swapCampEventHandles { - handle(slf, slf.currentCamp) + slf.OnChangeEvent() } + slf.OnSwapCampEvent() } slf.currentEntity++ - for _, handle := range slf.swapEntityEventHandles { - if slf.entityCounterclockwise { - handle(slf, slf.currentCamp, slf.camps[slf.currentCamp][len(slf.camps[slf.currentCamp])-slf.currentEntity-1]) - } else { - handle(slf, slf.currentCamp, slf.camps[slf.currentCamp][slf.currentEntity]) - } + slf.OnSwapEntityEvent() +} + +// SetCurrent 设置当前行动对象 +func (slf *Round[Data]) SetCurrent(campId int, entityId int) { + camp, exist := slf.camps[campId] + if !exist || !slice.Contains(camp, entityId) { + return } + slf.currentCamp = campId + slf.currentEntity = slice.GetIndex(camp, entityId) } // SkipCamp 跳过当前阵营剩余对象的行动 @@ -122,7 +137,7 @@ func (slf *Round[Data]) SkipCamp() { // ActionRefresh 刷新行动超时时间 func (slf *Round[Data]) ActionRefresh() { slf.currentEndTime = time.Now().Unix() - slf.ticker.After(slf.actionTimeoutTickerName, slf.actionTimeout, slf.loop) + slf.ticker.After(slf.actionTimeoutTickerName, slf.actionTimeout, slf.loop, true) } // ActionFinish 结束行动 @@ -130,10 +145,8 @@ func (slf *Round[Data]) ActionFinish() { slf.ticker.StopTimer(slf.actionTimeoutTickerName) if slf.shareAction { slf.currentEntity = -1 - } else { - slf.currentEntity++ } - slf.loop() + slf.loop(false) } // GetRound 获取当前回合数 @@ -165,3 +178,42 @@ func (slf *Round[Data]) GetCurrentRoundProgressRate() float64 { func (slf *Round[Data]) GetCurrent() (camp, entity int) { return slf.currentCamp, slf.camps[slf.currentCamp][slf.currentEntity] } + +// OnSwapCampEvent 触发阵营交换事件 +func (slf *Round[Data]) OnSwapCampEvent() { + for _, handle := range slf.swapCampEventHandles { + handle(slf, slf.currentCamp) + } +} + +// OnSwapEntityEvent 触发实体交换事件 +func (slf *Round[Data]) OnSwapEntityEvent() { + for _, handle := range slf.swapEntityEventHandles { + if slf.entityCounterclockwise { + handle(slf, slf.currentCamp, slf.camps[slf.currentCamp][len(slf.camps[slf.currentCamp])-slf.currentEntity-1]) + } else { + handle(slf, slf.currentCamp, slf.camps[slf.currentCamp][slf.currentEntity]) + } + } +} + +// OnGameOverEvent 触发游戏结束事件 +func (slf *Round[Data]) OnGameOverEvent() { + for _, handle := range slf.gameOverEventHandles { + handle(slf) + } +} + +// OnChangeEvent 触发回合变更事件 +func (slf *Round[Data]) OnChangeEvent() { + for _, handle := range slf.changeEventHandles { + handle(slf) + } +} + +// OnActionTimeoutEvent 触发行动超时事件 +func (slf *Round[Data]) OnActionTimeoutEvent() { + for _, handle := range slf.actionTimeoutEventHandles { + handle(slf, slf.currentCamp, slf.camps[slf.currentCamp][slf.currentEntity]) + } +} diff --git a/game/fight/round_options.go b/game/fight/round_options.go index 96a6570..97b9683 100644 --- a/game/fight/round_options.go +++ b/game/fight/round_options.go @@ -9,10 +9,11 @@ import ( type RoundOption[Data RoundData] func(round *Round[Data]) type ( - RoundSwapCampEvent[Data RoundData] func(round *Round[Data], campId int) - RoundSwapEntityEvent[Data RoundData] func(round *Round[Data], campId, entity int) - RoundGameOverEvent[Data RoundData] func(round *Round[Data]) - RoundChangeEvent[Data RoundData] func(round *Round[Data]) + RoundSwapCampEvent[Data RoundData] func(round *Round[Data], campId int) + RoundSwapEntityEvent[Data RoundData] func(round *Round[Data], campId, entity int) + RoundGameOverEvent[Data RoundData] func(round *Round[Data]) + RoundChangeEvent[Data RoundData] func(round *Round[Data]) + RoundActionTimeoutEvent[Data RoundData] func(round *Round[Data], campId, entity int) ) // WithRoundTicker 设置游戏的计时器 @@ -37,6 +38,7 @@ func WithRoundShareAction[Data RoundData](share bool) RoundOption[Data] { } // WithRoundSwapCampEvent 设置游戏的阵营交换事件 +// - 该事件在触发时已经完成了阵营的交换 func WithRoundSwapCampEvent[Data RoundData](swapCampEventHandle RoundSwapCampEvent[Data]) RoundOption[Data] { return func(round *Round[Data]) { round.swapCampEventHandles = append(round.swapCampEventHandles, swapCampEventHandle) @@ -44,6 +46,7 @@ func WithRoundSwapCampEvent[Data RoundData](swapCampEventHandle RoundSwapCampEve } // WithRoundSwapEntityEvent 设置游戏的实体交换事件 +// - 该事件在触发时已经完成了实体的交换 func WithRoundSwapEntityEvent[Data RoundData](swapEntityEventHandle RoundSwapEntityEvent[Data]) RoundOption[Data] { return func(round *Round[Data]) { round.swapEntityEventHandles = append(round.swapEntityEventHandles, swapEntityEventHandle) @@ -58,12 +61,20 @@ func WithRoundGameOverEvent[Data RoundData](gameOverEventHandle RoundGameOverEve } // WithRoundChangeEvent 设置游戏的回合变更事件 +// - 该事件在触发时已经完成了回合的变更 func WithRoundChangeEvent[Data RoundData](changeEventHandle RoundChangeEvent[Data]) RoundOption[Data] { return func(round *Round[Data]) { round.changeEventHandles = append(round.changeEventHandles, changeEventHandle) } } +// WithRoundActionTimeoutEvent 设置游戏的超时事件 +func WithRoundActionTimeoutEvent[Data RoundData](timeoutEventHandle RoundActionTimeoutEvent[Data]) RoundOption[Data] { + return func(round *Round[Data]) { + round.actionTimeoutEventHandles = append(round.actionTimeoutEventHandles, timeoutEventHandle) + } +} + // WithRoundCampCounterclockwise 设置游戏阵营逆序执行 func WithRoundCampCounterclockwise[Data RoundData]() RoundOption[Data] { return func(round *Round[Data]) { diff --git a/game/fight/round_test.go b/game/fight/round_test.go index bd42c6f..36a1755 100644 --- a/game/fight/round_test.go +++ b/game/fight/round_test.go @@ -1,6 +1,7 @@ package fight import ( + "fmt" "sync" "testing" "time" @@ -17,14 +18,11 @@ func TestName(t *testing.T) { }, WithRoundActionTimeout[string](time.Second), WithRoundSwapEntityEvent[string](func(round *Round[string], campId, entity int) { - t.Log(time.Now(), "swap entity", round.GetRound(), campId, entity) + fmt.Println(campId, entity) + if campId == 1 && entity == 2 { + round.SetCurrent(1, 1) + } }), - WithRoundGameOverEvent[string](func(round *Round[string]) { - t.Log(time.Now(), "game over", round.GetRound()) - wait.Done() - }), - WithRoundCampCounterclockwise[string](), - WithRoundEntityCounterclockwise[string](), ) wait.Add(1)