iT邦幫忙

2022 iThome 鐵人賽

DAY 12
1

接續昨天的文章,在這次的範例中,是希望更改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
流離之歌


上一篇
Day 11:State模式(一)
下一篇
Day 13:Facade模式
系列文
如何在Unity裡寫出具有一定擴充性的遊戲30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言