前言:
本模块是在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)
标签:case,cocos,StateType,AI,fsm,节点,状态机,public From: https://www.cnblogs.com/qindaoao/p/18160649