feat: fight 包的 Round 新增操作超时事件,优化事件逻辑

This commit is contained in:
kercylan98 2023-08-01 10:04:30 +08:00
parent 237cbd79cb
commit 9198faa061
3 changed files with 99 additions and 38 deletions

View File

@ -3,6 +3,7 @@ package fight
import ( import (
"fmt" "fmt"
"github.com/kercylan98/minotaur/utils/random" "github.com/kercylan98/minotaur/utils/random"
"github.com/kercylan98/minotaur/utils/slice"
"github.com/kercylan98/minotaur/utils/timer" "github.com/kercylan98/minotaur/utils/timer"
"time" "time"
) )
@ -16,10 +17,12 @@ type RoundGameOverVerifyHandle[Data RoundData] func(round *Round[Data]) bool
// - roundGameOverVerifyHandle 游戏结束验证函数 // - roundGameOverVerifyHandle 游戏结束验证函数
// - options 选项 // - options 选项
func NewRound[Data RoundData](data Data, camps []*RoundCamp, roundGameOverVerifyHandle RoundGameOverVerifyHandle[Data], options ...RoundOption[Data]) *Round[Data] { func NewRound[Data RoundData](data Data, camps []*RoundCamp, roundGameOverVerifyHandle RoundGameOverVerifyHandle[Data], options ...RoundOption[Data]) *Round[Data] {
mark := random.HostName()
round := &Round[Data]{ round := &Round[Data]{
mark: mark,
data: data, data: data,
camps: make(map[int][]int), camps: make(map[int][]int),
actionTimeoutTickerName: fmt.Sprintf("round_action_timeout_%s", random.HostName()), actionTimeoutTickerName: fmt.Sprintf("round_action_timeout_%s", mark),
roundGameOverVerifyHandle: roundGameOverVerifyHandle, roundGameOverVerifyHandle: roundGameOverVerifyHandle,
} }
for _, camp := range camps { for _, camp := range camps {
@ -30,13 +33,14 @@ func NewRound[Data RoundData](data Data, camps []*RoundCamp, roundGameOverVerify
option(round) option(round)
} }
if round.ticker == nil { if round.ticker == nil {
round.ticker = timer.GetTicker(5) round.ticker = timer.GetTicker(5, timer.WithMark(mark))
} }
return round return round
} }
// Round 回合制游戏结构 // Round 回合制游戏结构
type Round[Data RoundData] struct { type Round[Data RoundData] struct {
mark string // 标记
data Data // 游戏数据 data Data // 游戏数据
ticker *timer.Ticker // 计时器 ticker *timer.Ticker // 计时器
camps map[int][]int // 阵营 camps map[int][]int // 阵营
@ -57,6 +61,7 @@ type Round[Data RoundData] struct {
swapEntityEventHandles []RoundSwapEntityEvent[Data] // 实体交换事件 swapEntityEventHandles []RoundSwapEntityEvent[Data] // 实体交换事件
gameOverEventHandles []RoundGameOverEvent[Data] // 游戏结束事件 gameOverEventHandles []RoundGameOverEvent[Data] // 游戏结束事件
changeEventHandles []RoundChangeEvent[Data] // 游戏回合变更事件 changeEventHandles []RoundChangeEvent[Data] // 游戏回合变更事件
actionTimeoutEventHandles []RoundActionTimeoutEvent[Data] // 行动超时事件
} }
// GetData 获取游戏数据 // GetData 获取游戏数据
@ -69,15 +74,25 @@ func (slf *Round[Data]) GetData() Data {
func (slf *Round[Data]) Run() { func (slf *Round[Data]) Run() {
slf.currentEntity = -1 slf.currentEntity = -1
slf.round = 1 slf.round = 1
slf.loop() slf.loop(false)
} }
func (slf *Round[Data]) loop() { // Release 释放游戏
slf.ticker.StopTimer(slf.actionTimeoutTickerName) func (slf *Round[Data]) Release() {
if slf.roundGameOverVerifyHandle(slf) { if slf.mark == slf.ticker.Mark() {
for _, handle := range slf.gameOverEventHandles { slf.ticker.Release()
handle(slf) 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) {
slf.OnGameOverEvent()
return return
} else { } else {
slf.ActionRefresh() slf.ActionRefresh()
@ -96,22 +111,22 @@ func (slf *Round[Data]) loop() {
if slf.roundCount > len(slf.camps) { if slf.roundCount > len(slf.camps) {
slf.round++ slf.round++
slf.roundCount = 1 slf.roundCount = 1
for _, handle := range slf.changeEventHandles { slf.OnChangeEvent()
handle(slf)
}
}
for _, handle := range slf.swapCampEventHandles {
handle(slf, slf.currentCamp)
} }
slf.OnSwapCampEvent()
} }
slf.currentEntity++ slf.currentEntity++
for _, handle := range slf.swapEntityEventHandles { slf.OnSwapEntityEvent()
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])
} }
// 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 跳过当前阵营剩余对象的行动 // SkipCamp 跳过当前阵营剩余对象的行动
@ -122,7 +137,7 @@ func (slf *Round[Data]) SkipCamp() {
// ActionRefresh 刷新行动超时时间 // ActionRefresh 刷新行动超时时间
func (slf *Round[Data]) ActionRefresh() { func (slf *Round[Data]) ActionRefresh() {
slf.currentEndTime = time.Now().Unix() 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 结束行动 // ActionFinish 结束行动
@ -130,10 +145,8 @@ func (slf *Round[Data]) ActionFinish() {
slf.ticker.StopTimer(slf.actionTimeoutTickerName) slf.ticker.StopTimer(slf.actionTimeoutTickerName)
if slf.shareAction { if slf.shareAction {
slf.currentEntity = -1 slf.currentEntity = -1
} else {
slf.currentEntity++
} }
slf.loop() slf.loop(false)
} }
// GetRound 获取当前回合数 // GetRound 获取当前回合数
@ -165,3 +178,42 @@ func (slf *Round[Data]) GetCurrentRoundProgressRate() float64 {
func (slf *Round[Data]) GetCurrent() (camp, entity int) { func (slf *Round[Data]) GetCurrent() (camp, entity int) {
return slf.currentCamp, slf.camps[slf.currentCamp][slf.currentEntity] 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])
}
}

View File

@ -13,6 +13,7 @@ type (
RoundSwapEntityEvent[Data RoundData] func(round *Round[Data], campId, entity int) RoundSwapEntityEvent[Data RoundData] func(round *Round[Data], campId, entity int)
RoundGameOverEvent[Data RoundData] func(round *Round[Data]) RoundGameOverEvent[Data RoundData] func(round *Round[Data])
RoundChangeEvent[Data RoundData] func(round *Round[Data]) RoundChangeEvent[Data RoundData] func(round *Round[Data])
RoundActionTimeoutEvent[Data RoundData] func(round *Round[Data], campId, entity int)
) )
// WithRoundTicker 设置游戏的计时器 // WithRoundTicker 设置游戏的计时器
@ -37,6 +38,7 @@ func WithRoundShareAction[Data RoundData](share bool) RoundOption[Data] {
} }
// WithRoundSwapCampEvent 设置游戏的阵营交换事件 // WithRoundSwapCampEvent 设置游戏的阵营交换事件
// - 该事件在触发时已经完成了阵营的交换
func WithRoundSwapCampEvent[Data RoundData](swapCampEventHandle RoundSwapCampEvent[Data]) RoundOption[Data] { func WithRoundSwapCampEvent[Data RoundData](swapCampEventHandle RoundSwapCampEvent[Data]) RoundOption[Data] {
return func(round *Round[Data]) { return func(round *Round[Data]) {
round.swapCampEventHandles = append(round.swapCampEventHandles, swapCampEventHandle) round.swapCampEventHandles = append(round.swapCampEventHandles, swapCampEventHandle)
@ -44,6 +46,7 @@ func WithRoundSwapCampEvent[Data RoundData](swapCampEventHandle RoundSwapCampEve
} }
// WithRoundSwapEntityEvent 设置游戏的实体交换事件 // WithRoundSwapEntityEvent 设置游戏的实体交换事件
// - 该事件在触发时已经完成了实体的交换
func WithRoundSwapEntityEvent[Data RoundData](swapEntityEventHandle RoundSwapEntityEvent[Data]) RoundOption[Data] { func WithRoundSwapEntityEvent[Data RoundData](swapEntityEventHandle RoundSwapEntityEvent[Data]) RoundOption[Data] {
return func(round *Round[Data]) { return func(round *Round[Data]) {
round.swapEntityEventHandles = append(round.swapEntityEventHandles, swapEntityEventHandle) round.swapEntityEventHandles = append(round.swapEntityEventHandles, swapEntityEventHandle)
@ -58,12 +61,20 @@ func WithRoundGameOverEvent[Data RoundData](gameOverEventHandle RoundGameOverEve
} }
// WithRoundChangeEvent 设置游戏的回合变更事件 // WithRoundChangeEvent 设置游戏的回合变更事件
// - 该事件在触发时已经完成了回合的变更
func WithRoundChangeEvent[Data RoundData](changeEventHandle RoundChangeEvent[Data]) RoundOption[Data] { func WithRoundChangeEvent[Data RoundData](changeEventHandle RoundChangeEvent[Data]) RoundOption[Data] {
return func(round *Round[Data]) { return func(round *Round[Data]) {
round.changeEventHandles = append(round.changeEventHandles, changeEventHandle) 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 设置游戏阵营逆序执行 // WithRoundCampCounterclockwise 设置游戏阵营逆序执行
func WithRoundCampCounterclockwise[Data RoundData]() RoundOption[Data] { func WithRoundCampCounterclockwise[Data RoundData]() RoundOption[Data] {
return func(round *Round[Data]) { return func(round *Round[Data]) {

View File

@ -1,6 +1,7 @@
package fight package fight
import ( import (
"fmt"
"sync" "sync"
"testing" "testing"
"time" "time"
@ -17,14 +18,11 @@ func TestName(t *testing.T) {
}, },
WithRoundActionTimeout[string](time.Second), WithRoundActionTimeout[string](time.Second),
WithRoundSwapEntityEvent[string](func(round *Round[string], campId, entity int) { 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) wait.Add(1)