前言:
本模組是在cocos專案中運用戰鬥框架,根據學習別人的文章來結合專案進行編寫的,若有不對不合理的地方有勞大家指正,萬分感謝!!!若有能有用的上的,萬分榮幸!
簡介:
AI模組一般是對怪物的AI實現,或者託管等自動戰鬥的情況。具體方式可能根據專案的具體需求來選擇,常用的有:有限狀態機,行為樹。
有限狀態機(fsm)
介紹:
狀態機,或稱有限狀態機FSM(Finite State Machine),是一種重要的程式設計思想。
狀態機有3要素:狀態、事件與響應;
- 狀態:系統處在什麼狀態?
- 事件:發生了什麼事?
- 響應:此狀態下發生了這樣的事,系統要如何處理?
狀態機有三大特徵:
- 狀態總數(state)是有限的。
- 任一時刻,只處在一種狀態之中。
- 某種條件下,會從一種狀態轉變(transition)到另一種狀態。
下面用在Cocos專案中的例子來做個簡單的應用:
各個狀態均包含以下操作:
export interface IState{
OnEnter();//進入狀態機回撥
OnExit();//退出狀態機回撥
OnUpdate(deltaTime);//持續執行狀態
//OnCheck();
//OnFixdeUpdate();
}
定義對應狀態:
export enum StateType{
//狀態機中可能的狀態
/**未啟用 */
InActive,
/**等待遊戲開始 */
WaitingStart,
/**待機 */
Idle,
/**待機 */
Idle_TowerDefense,
/**移動 */
Move,
/**攻擊 */
Attack,
/**正在大殺特殺 */
Killing,
/**死亡中 */
Die,
/**怪物扮演中的玩家 */
MonsterCosplay,
/**顯示結算介面 */
END,
}
定義狀態機:
@ccclass('FSM')
export class FSM{
public curState:IState;
public states = new Map<StateType,IState>;
public blackboard:BlackBoard;
public constructor(blackboard:BlackBoard){
this.states = new Map<StateType,IState>();
this.blackboard = blackboard;
}
/**增加對應狀態 */
public AddState(stateType:StateType,state:IState){
if(this.states.has(stateType)){
return;
}
this.states.set(stateType,state);
}
/**切換到對應狀態 */
public SwitchState(stateType:StateType){
if(!this.states.has(stateType)){
return;
}
if(this.curState != null){
this.curState.OnExit();
}
this.curState = this.states.get(stateType);
this.curState.OnEnter();
}
/**獲取到對應狀態 */
public GetIState(stateType:StateType){
return this.states.get(stateType);
}
/**這裡實現狀態機對應執行邏輯 */
public OnUpdate(deltaTime){
this.curState?.OnUpdate(deltaTime);
}
// public OnCheck(){
// this.curState.OnCheck();
// }
// public OnFixedUpdate(){
// this.curState.OnFixedUpdate();
// }
}
定義AI角色狀態,並初始化狀態機(根據自己的邏輯來切換對應狀態):
//初始化狀態機
@ccclass('Test')
export class Test extends AttrBase {
public fsm: FSM;
public blackboard: TestBlackboard = new TestBlackboard();//此處儲存共享資料,或者向外展示的資料,可配置的資料
InitFsm() {
this.fsm = new FSM(this.blackboard);
/**攻擊狀態 */
this.fsm.AddState(StateType.Attack, new AttackState(this.fsm));
/**增加待機狀態 */
this.fsm.AddState(StateType.Idle, new IdleState(this.fsm));
/**增加死亡狀態 */
this.fsm.AddState(StateType.Die, new DieState(this.fsm));
/**增加等待開始狀態 */
this.fsm.AddState(StateType.WaitingStart, new WaittingState(this.fsm));
/**增加結束狀態 */
this.fsm.AddState(StateType.END, new ENDState(this.fsm));
}
Init(){
super.Init();
this.InitFsm();
this.fsm.SwitchState(StateType.WaitingStart);//切換狀態為遊戲開始狀態
}
}
//定義各個狀態
class WaittingState implements IState {
private fsm: FSM;
public blackboard: TestBlackboard;
public constructor(fsm: FSM) {
this.fsm = fsm;
this.blackboard = fsm.blackboard as TestBlackboard;
}
//新開局初始化
OnEnter() {
}
OnExit() {
}
OnUpdate(deltaTime: number) {
if(GamePlaying){//遊戲開始
this.fsm.SwitchState(StateType.Idle);//切換狀態IDLE
}
}
}
行為樹(這裡沒有太深入的研究,應用的也不太多,大概瞭解了下理論)
簡介:
行為樹(Behavior Tree)是一種用於描述複雜行為邏輯的圖形化結構,常用於遊戲開發、機器人控制、人工智慧等領域。它由節點組成,節點之間透過連線線連線,形成樹狀結構。行為樹主要由以下幾種型別的節點組成:
- 行為節點(Action Nodes):執行具體的動作或任務,例如移動、攻擊、待機等。
- 條件節點(Conditional Nodes):判斷條件是否滿足,通常用於控制流程的分支。
- 複合節點(Composite Nodes):用於組合和控制其他節點的執行順序和邏輯關係,主要分為序列節點和選擇節點兩種型別:
- 序列節點(Sequence Nodes):按順序執行其子節點,只有當所有子節點都成功執行時,序列節點才會返回成功;一旦有一個子節點失敗,則序列節點會立即返回失敗,不再執行後續節點。
- 選擇節點(Selector Nodes):按順序嘗試執行其子節點,一旦某個子節點成功執行,選擇節點即返回成功;只有當所有子節點都失敗時,選擇節點才會返回失敗。
- 裝飾節點(Decorator Nodes):用於修改其子節點的行為或結果,常見的裝飾節點包括反轉節點、條件節點、超時節點等。
簡單的程式碼運用
private actionType: number = 0;
public get ActionType(): number { return this.actionType; }
/**玩家的行為:0為待機,1為移動,2為跳,3為跑,4為散步,9為瀕死,10為死亡 */
public set ActionType(value: number) {
switch (value) {
case 0:
case 9:
this.ChangeAni("idle", true);
break;
case 2:
break;
case 1:
case 3:
case 4:
this.ChangeAni("run", true);
break;
case 5:
case 6:
case 7:
case 8:
break;
case 10:
this.ChangeAni("die",false);
break;
default:
Logger.Error("Character ActionType Error: " + value);
break;
}
this.actionType = value;
}
ChangeAni(aniName: string, isLoop: boolean, func?){
//定義自己的對應邏輯
}
參考文章:
如何深入理解“有限狀態機”的設計思想? - 知乎 (zhihu.com)
JavaScript與有限狀態機 - 阮一峰的網路日誌 (ruanyifeng.com)
ChatGpt的回答