首页 > 技术文章 > Ts有限状态机

nuolo 2020-06-05 17:20 原文

ts版本的有限状态机

最近做小游戏要做切换人物状态,花点时间写了一个有限状态机,使用语言为Ts,也可改成自己的语言
按照目前的逻辑,这个可以继续横向扩展,某些做流程管理
先上预览图

Fsm:状态机类
FsmBase:状态机基类
FsmManager:状态机管理类
FsmState:状态类
FsmIdle FsmRun角色Ctrl测试用状态机类
代码:FsmBase
//状态机基类 export default abstract class FsmBase { constructor(fsmid:number) {this.FsmId=fsmid } //状态机编号 public FsmId:number; //状态机拥有者 public Owner:any; //当前状态类型 public CurrStateType:number; //关闭状态机 public abstract ShutDown(); }
代码:FsmState
`
import Fsm from "./Fsm";
//状态类
export default abstract class FsmState
{
constructor() { }
//状态对应的状态机
public CurrFsm:Fsm
//进入状态
public abstract Enter()
//执行状态
public abstract Update()
//厉害状态
public abstract Leave()
//状态机销毁时调用
public abstract Destroy()

}
`
代码:Fsm

`
import FsmBase from "./FsmBase";
import FsmState from "./FsmState";

//状态机
export default class Fsmextends FsmBase {

private m_CurrState:FsmState<T>;

private m_StateDic:{[key:number]:FsmState<T>}={}

//初始化状态机
constructor(fsmid:number ,owner:T,states:FsmState[] )
{
super(fsmid);
this. m_StateDic={};

   this.Owner=owner;

   for (let i in states) {
    let state=states[i];
    state.CurrFsm=this;
    this.m_StateDic[i]=state;
   }

   this.CurrStateType=0;
   this.m_CurrState=this.m_StateDic[this.CurrStateType];
   this.m_CurrState.Enter();
}

//获取当前状态
public GetState(stateType:number):FsmState{
let state=null;
if (this.m_StateDic[stateType]) {
state=this.m_StateDic[stateType];
}
return state;
}
//执行当前状态
public Update(){
if (this.m_CurrState) {
this.m_CurrState.Update();
}
}
//切换当前状态
public ChangeState(newState:number){
if (this.CurrStateType==newState) {
return;
}
if (this.m_CurrState!=null) {
this.m_CurrState.Leave();
}
this.CurrStateType=newState;
this.m_CurrState=this.m_StateDic[this.CurrStateType];

    //进入新状态
    this.m_CurrState.Enter();
}

//切换状态机
public ShutDown() {
if (this.m_CurrState!=null) {
this.m_CurrState.Leave();
}
for (let index in this.m_StateDic) {
this.m_StateDic[index].Destroy();
}
delete this.m_StateDic;
}

}
代码:FsmManager
import FsmBase from "./FsmBase";
import Fsm from "./Fsm";
import FsmState from "./FsmState";

//状态机管理类
export default class FsmManager {

constructor() { this.M_FsmDic= {}}
static _instance:any;
static getInstance() {
    return this._instance || (this._instance = new FsmManager() )
}

private M_FsmDic:{[key:number]:FsmBase};
private m_TemFsmId:number=0;

//创建状态机
public Create<T>(owner:T,states:FsmState<T>[]):Fsm<T> {
    this. m_TemFsmId+=1;
    let fsm=new Fsm<T>(this.m_TemFsmId,owner,states)
    this.M_FsmDic[this.m_TemFsmId]=fsm;
    return fsm;
}
//销毁状态机
public DestroyFsm(fsmId:number){
   let fsm=null;
    if (this.M_FsmDic[fsmId]) {
        fsm=this.M_FsmDic[fsmId];
        fsm.ShutDown();
        delete this.M_FsmDic[fsmId]
    }
}

}
测试用代码:FsmIdle FsmRun RoleCtrl
import FsmState from "../Core/FSM/FsmState";
import RoleCtrl from "./RoleCtrl";

export default class FsmIdle extends FsmState {

constructor() { super(); }


public Enter() {
    console.log("FsmIdle__Enter");
}
public Update() {
    console.log("FsmIdle__Update");
}
public Leave() {
    console.log("FsmIdle__Leave");
}
public Destroy() {
    console.log("FsmIdle__Destroy");
}

}

import FsmState from "../Core/FSM/FsmState";
import RoleCtrl from "./RoleCtrl";

export default class FsmRun extends FsmState {

constructor() { super(); }

  
public Enter() {
    console.log("FsmRun__Enter");
}
public Update() {
    console.log("FsmRun__Update");
}
public Leave() {
    console.log("FsmRun__Leave");
}
public Destroy() {
    console.log("FsmRun__Destroy");
}

}
`

`
import Fsm from "../Core/FSM/Fsm";
import FsmState from "../Core/FSM/FsmState";
import FsmIdle from "./FsmIdle";
import FsmRun from "./FsmRun";
import FsmManager from "../Core/FSM/FsmManager";

enum RoleFsmState{Idle=0,Run=1}

export default class RoleCtrl extends Laya.Script {

/** @prop {name:myimage, tips:"图片", type:Node}*/
public myimage:Laya.Image;

Index:number=0;
CurrFsm:Fsm<RoleCtrl>;

constructor() { super();
    let states:{[key:number]:FsmState<RoleCtrl>}={
        0:new FsmIdle(),
        1:new FsmRun()
    };
    this.CurrFsm=  FsmManager.getInstance().Create(this,states);
}
onClick(){
    this.change();
}

change(): any {
   this.CurrFsm.ChangeState((++this.Index)%2);
}
onUpdate(){
    this.CurrFsm.Update();
}

}
`
目前测试运行良好,如果有发现问题的话,会及时进行修改

推荐阅读