diff --git a/game/fight/round.go b/game/fight/round.go deleted file mode 100644 index 3096dd9..0000000 --- a/game/fight/round.go +++ /dev/null @@ -1,263 +0,0 @@ -package fight - -import ( - "fmt" - "github.com/kercylan98/minotaur/utils/random" - "github.com/kercylan98/minotaur/utils/slice" - "github.com/kercylan98/minotaur/utils/timer" - "time" -) - -// RoundGameOverVerifyHandle 回合制游戏结束验证函数 -type RoundGameOverVerifyHandle[Data RoundData] func(round *Round[Data]) bool - -// NewRound 创建一个新的回合制游戏 -// - data 游戏数据 -// - camps 阵营 -// - roundGameOverVerifyHandle 游戏结束验证函数 -// - options 选项 -// -// Deprecated: 从 Minotaur 0.2.7 开始,由于设计原因已弃用,请尝试考虑使用 fight.TurnBased 进行代替 -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", mark), - roundGameOverVerifyHandle: roundGameOverVerifyHandle, - } - for _, camp := range camps { - round.camps[camp.campId] = camp.entities - round.campOrder = append(round.campOrder, camp.campId) - } - round.campOrderSource = slice.Copy(round.campOrder) - for _, option := range options { - option(round) - } - if round.ticker == nil { - 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 // 阵营 - campOrder []int // 阵营顺序 - campOrderSource []int // 阵营顺序源 - actionTimeout time.Duration // 行动超时时间 - actionTimeoutTickerName string // 行动超时计时器名称 - actionTimeoutTime int64 // 行动超时时间 - round int // 回合数 - roundCount int // 回合计数 - currentCamp int // 当前行动阵营 - currentEntity int // 当前行动的阵营实体索引 - shareAction bool // 是否共享行动(同阵营共享行动时间) - roundGameOverVerifyHandle RoundGameOverVerifyHandle[Data] // 游戏结束验证函数 - campCounterclockwise bool // 是否阵营逆时针 - entityCounterclockwise bool // 是否对象逆时针 - - swapCampEventHandles []RoundSwapCampEvent[Data] // 阵营交换事件 - swapEntityEventHandles []RoundSwapEntityEvent[Data] // 实体交换事件 - gameOverEventHandles []RoundGameOverEvent[Data] // 游戏结束事件 - changeEventHandles []RoundChangeEvent[Data] // 游戏回合变更事件 - actionTimeoutEventHandles []RoundActionTimeoutEvent[Data] // 行动超时事件 - actionRefreshEventHandles []RoundActionRefreshEvent[Data] // 行动刷新事件 - - //actionMutex sync.Mutex -} - -// GetData 获取游戏数据 -func (slf *Round[Data]) GetData() Data { - return slf.data -} - -// Start 开始回合 -// - 将通过传入的 Camp 进行初始化,Camp 为一个二维数组,每个数组内的元素都是一个行动标识 -func (slf *Round[Data]) Start() { - slf.currentEntity = -1 - slf.round = 1 - //slf.actionMutex.Lock() - //defer slf.actionMutex.Unlock() - slf.loop(false) -} - -// Stop 停止回合 -// - 停止回合时仅会停止行动超时计时器,其他所有数据均会保留 -// - 若要重置回合,需要调用 Reset 方法 -func (slf *Round[Data]) Stop() { - slf.ticker.StopTimer(slf.actionTimeoutTickerName) -} - -// Reset 重置回合 -func (slf *Round[Data]) Reset() { - slf.ticker.StopTimer(slf.actionTimeoutTickerName) - slf.currentCamp = 0 - slf.currentEntity = 0 - slf.round = 0 - slf.roundCount = 0 - slf.campOrder = slice.Copy(slf.campOrderSource) -} - -// 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) { - slf.OnGameOverEvent() - return - } else { - slf.ActionRefresh() - } - if slf.currentEntity == -1 || slf.currentEntity >= len(slf.camps[slf.currentCamp])-1 { - if !slf.campCounterclockwise { - slf.currentCamp = slf.campOrder[0] - slf.campOrder = append(slf.campOrder[1:], slf.currentCamp) - } else { - slf.currentCamp = slf.campOrder[len(slf.campOrder)-1] - slf.campOrder = append([]int{slf.currentCamp}, slf.campOrder[:len(slf.campOrder)-1]...) - } - - slf.currentEntity = -1 - slf.roundCount++ - if slf.roundCount > len(slf.camps) { - slf.round++ - slf.roundCount = 1 - slf.OnChangeEvent() - } - slf.OnSwapCampEvent() - } - 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 跳过当前阵营剩余对象的行动 -func (slf *Round[Data]) SkipCamp() { - slf.currentEntity = -1 -} - -// ActionRefresh 刷新行动超时时间 -func (slf *Round[Data]) ActionRefresh() { - slf.actionTimeoutTime = time.Now().Add(slf.actionTimeout).Unix() - slf.ticker.After(slf.actionTimeoutTickerName, slf.actionTimeout, func(timeout bool) { - //slf.actionMutex.Lock() - //defer slf.actionMutex.Unlock() - slf.loop(timeout) - }, true) -} - -// ActionFinish 结束行动 -func (slf *Round[Data]) ActionFinish() { - slf.ticker.StopTimer(slf.actionTimeoutTickerName) - if slf.shareAction { - slf.currentEntity = -1 - } - //slf.actionMutex.Lock() - //defer slf.actionMutex.Unlock() - slf.loop(false) -} - -// GetRound 获取当前回合数 -func (slf *Round[Data]) GetRound() int { - return slf.round -} - -// GetActionTimeoutTime 获取行动超时时间 -func (slf *Round[Data]) GetActionTimeoutTime() int64 { - return slf.actionTimeoutTime -} - -// AllowAction 是否允许行动 -func (slf *Round[Data]) AllowAction(camp, entity int) bool { - return (slf.currentCamp == camp && slf.currentEntity == entity) || slf.shareAction && camp == slf.currentCamp -} - -// CampAllowAction 阵容是否允许行动 -func (slf *Round[Data]) CampAllowAction(camp int) bool { - return slf.currentCamp == camp -} - -// GetCurrentCamp 获取当前行动的阵营 -func (slf *Round[Data]) GetCurrentCamp() int { - return slf.currentCamp -} - -// GetCurrentRoundProgressRate 获取当前回合进度 -func (slf *Round[Data]) GetCurrentRoundProgressRate() float64 { - return float64(slf.roundCount / len(slf.camps)) -} - -// GetCurrent 获取当前行动的阵营和对象 -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]) - } -} - -// OnActionRefreshEvent 触发行动刷新事件 -func (slf *Round[Data]) OnActionRefreshEvent() { - for _, handle := range slf.actionRefreshEventHandles { - handle(slf, slf.currentCamp, slf.camps[slf.currentCamp][slf.currentEntity]) - } -} diff --git a/game/fight/round_camp.go b/game/fight/round_camp.go deleted file mode 100644 index 348c4fd..0000000 --- a/game/fight/round_camp.go +++ /dev/null @@ -1,15 +0,0 @@ -package fight - -// NewRoundCamp 创建一个新的回合制游戏阵营 -func NewRoundCamp(campId, entity int, entities ...int) *RoundCamp { - return &RoundCamp{ - campId: campId, - entities: append([]int{entity}, entities...), - } -} - -// RoundCamp 回合制游戏阵营 -type RoundCamp struct { - campId int - entities []int -} diff --git a/game/fight/round_data.go b/game/fight/round_data.go deleted file mode 100644 index 01dba29..0000000 --- a/game/fight/round_data.go +++ /dev/null @@ -1,6 +0,0 @@ -package fight - -// RoundData 回合制游戏数据 -type RoundData interface { - // 占位 -} diff --git a/game/fight/round_options.go b/game/fight/round_options.go deleted file mode 100644 index 03d010d..0000000 --- a/game/fight/round_options.go +++ /dev/null @@ -1,98 +0,0 @@ -package fight - -import ( - "github.com/kercylan98/minotaur/utils/timer" - "time" -) - -// RoundOption 回合制游戏选项 -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]) - RoundActionTimeoutEvent[Data RoundData] func(round *Round[Data], campId, entity int) - RoundActionRefreshEvent[Data RoundData] func(round *Round[Data], campId, entity int) -) - -// WithRoundTicker 设置游戏的计时器 -func WithRoundTicker[Data RoundData](ticker *timer.Ticker) RoundOption[Data] { - return func(round *Round[Data]) { - round.ticker = ticker - } -} - -// WithRoundActionTimeout 设置游戏的行动超时时间 -func WithRoundActionTimeout[Data RoundData](timeout time.Duration) RoundOption[Data] { - return func(round *Round[Data]) { - round.actionTimeout = timeout - } -} - -// WithRoundShareAction 设置游戏的行动是否共享 -func WithRoundShareAction[Data RoundData](share bool) RoundOption[Data] { - return func(round *Round[Data]) { - round.shareAction = share - } -} - -// WithRoundSwapCampEvent 设置游戏的阵营交换事件 -// - 该事件在触发时已经完成了阵营的交换 -func WithRoundSwapCampEvent[Data RoundData](swapCampEventHandle RoundSwapCampEvent[Data]) RoundOption[Data] { - return func(round *Round[Data]) { - round.swapCampEventHandles = append(round.swapCampEventHandles, swapCampEventHandle) - } -} - -// WithRoundSwapEntityEvent 设置游戏的实体交换事件 -// - 该事件在触发时已经完成了实体的交换 -func WithRoundSwapEntityEvent[Data RoundData](swapEntityEventHandle RoundSwapEntityEvent[Data]) RoundOption[Data] { - return func(round *Round[Data]) { - round.swapEntityEventHandles = append(round.swapEntityEventHandles, swapEntityEventHandle) - } -} - -// WithRoundGameOverEvent 设置游戏的结束事件 -func WithRoundGameOverEvent[Data RoundData](gameOverEventHandle RoundGameOverEvent[Data]) RoundOption[Data] { - return func(round *Round[Data]) { - round.gameOverEventHandles = append(round.gameOverEventHandles, gameOverEventHandle) - } -} - -// 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]) { - round.campCounterclockwise = true - } -} - -// WithRoundEntityCounterclockwise 设置游戏实体逆序执行 -func WithRoundEntityCounterclockwise[Data RoundData]() RoundOption[Data] { - return func(round *Round[Data]) { - round.entityCounterclockwise = true - } -} - -// WithRoundActionRefreshEvent 设置游戏的行动刷新事件 -func WithRoundActionRefreshEvent[Data RoundData](refreshEventHandle RoundActionRefreshEvent[Data]) RoundOption[Data] { - return func(round *Round[Data]) { - round.actionRefreshEventHandles = append(round.actionRefreshEventHandles, refreshEventHandle) - } -} diff --git a/game/fight/round_test.go b/game/fight/round_test.go deleted file mode 100644 index eff7d7e..0000000 --- a/game/fight/round_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package fight - -import ( - "fmt" - "sync" - "testing" - "time" -) - -func TestName(t *testing.T) { - var wait sync.WaitGroup - var camps []*RoundCamp - camps = append(camps, NewRoundCamp(1, 1, 2, 3)) - camps = append(camps, NewRoundCamp(2, 4, 5, 6)) - camps = append(camps, NewRoundCamp(3, 7, 8, 9)) - r := NewRound("", camps, func(round *Round[string]) bool { - return round.GetRound() == 2 - }, - WithRoundActionTimeout[string](time.Second), - WithRoundSwapEntityEvent[string](func(round *Round[string], campId, entity int) { - fmt.Println(campId, entity) - if campId == 1 && entity == 2 { - round.SetCurrent(1, 1) - } - }), - ) - - wait.Add(1) - r.Start() - wait.Wait() -}