接續昨天的文章,在這次的範例中,是希望更改CALGUIController
裡顯示回合階段的判斷條件,在重構前我是這樣去做回合階段的顯示
CALGUIController.cs
private void ShowCurrentStageName()
{
if (CellGrid.CellGridState is CellGridStateCALAIAttackTurn)
m_StageTooltipGUI.SetCurrentStageNameIsEnemyAttackStage();
if (CellGrid.CellGridState is CellGridStateAIPrepareTurn)
m_StageTooltipGUI.SetCurrentStageNameIsEnemyPrepareStage();
if(CellGrid.CurrentPlayerNumber == 0)
m_StageTooltipGUI.SetCurrentStageNameIsPlayerStage();
}
不過為了防止重複呼叫,所以會有個判斷是用確定是否已經呼叫過
CALGUIController.cs
if(UIInputObserver.IsUnitTurnChange)
{
ShowCurrentStageName();
if (CellGrid.CellGridState is CellGridStateCALAIAttackTurn)
{
SetPlayerInfoIsActive(default, false);
m_StageTooltipGUI.SetFleeButtonIsActive(false);
m_IsUnitClicked = false;
}
UIInputObserver.IsUnitTurnChange = false;
}
至於這些CellGridState
的改變時機則是當此回合階段結束時,會切換可行動單位,此時會去做new 一個相對應的類別
CALAIPlayer.cs
private IEnumerator PlayPrepareCoroutine(CellGrid cellGrid)
{
...
cellGrid.CellGridState = new CellGridStateCALAIAttackTurn(cellGrid, this);
...
}
private IEnumerator PlayAttackCoroutine(CellGrid cellGrid)
{
...
cellGrid.CellGridState = new CellGridStateAIPrepareTurn(cellGrid, this);
...
}
CALHumanPlayer.cs
public override void Play(CellGrid cellGrid)
{
...
cellGrid.CellGridState = new CellGridStateCALPlayerTurn(cellGrid);
}
在這次的重構中,我會想把這三個狀態用繼承ITurnState
的方式去重構,程式碼如下
TurnState.cs
using Assets.Scripts.GUI.GUITool;
namespace LinXuan.TBSF.TurnTtates
{
//其實這邊應該要把interface跟三個class分別放在一個cs檔裡,這邊因為不想占太多篇幅就直接這樣放了
public interface ITurnState
{
public void OnStateEnter();
public void OnStateExit();
}
public class PlayerTurnState : ITurnState
{
public void OnStateEnter()
{
UIInputObserver.IsUnitTurnChange = true;
}
public void OnStateExit()
{
}
}
public class EnemyPrepareTurnState : ITurnState
{
public void OnStateEnter()
{
UIInputObserver.IsUnitTurnChange = true;
}
public void OnStateExit()
{
}
}
public class EnemyAttackTurnState : ITurnState
{
public void OnStateEnter()
{
UIInputObserver.IsUnitTurnChange = true;
}
public void OnStateExit()
{
}
}
}
其他重構後的程式碼
CALAIPlayer.cs
private IEnumerator PlayPrepareCoroutine(CellGrid cellGrid)
{
...
cellGrid.TurnState = new EnemyAttackTurnState();
cellGrid.CellGridState = new CALCellGridStateBlockInput(cellGrid);
...
}
private IEnumerator PlayAttackCoroutine(CellGrid cellGrid)
{
...
cellGrid.TurnState = new EnemyPrepareTurnState();
cellGrid.CellGridState = new CALCellGridStateBlockInput(cellGrid);
...
}
CALHumanPlayer.cs
public override void Play(CellGrid cellGrid)
{
...
cellGrid.CellGridState = new CALCellGridStateBlockInput(cellGrid);
cellGrid.TurnState = new PlayerTurnState();
}
CALGUIController.cs
private void Update()
{
...
if(UIInputObserver.IsUnitTurnChange)
{
ShowCurrentStage();
if(CellGrid.TurnState is EnemyAttackTurnState)
{
SetPlayerInfoIsActive(default, false);
m_StageTooltipGUI.SetFleeButtonIsActive(false);
m_IsUnitClicked = false;
}
UIInputObserver.IsUnitTurnChange = false;
}
...
}
private void ShowCurrentStage()
{
if (CellGrid.TurnState is EnemyAttackTurnState)
m_StageTooltipGUI.SetCurrentStageNameIsEnemyAttackStage();
if (CellGrid.TurnState is EnemyPrepareTurnState)
m_StageTooltipGUI.SetCurrentStageNameIsEnemyPrepareStage();
if (CellGrid.TurnState is PlayerTurnState)
m_StageTooltipGUI.SetCurrentStageNameIsPlayerStage();
}
不過其實也可以直接讓這些TurnState去控制回合階段的顯示這種寫法,這邊就不寫了,有興趣的可以自己寫寫看。
設計模式與遊戲開發的完美結合(暢銷回饋版)
Turn Based Strategy Framework
流離之歌