人物FSM
人物有限状态机 之前看这个状态机没看懂,今天又翻出来,看的略懂 FSM在游戏中应用的地方还是挺多的 怪物AI,玩家行为管理 条件(包含若干事件) 条件(包含若干事件) 状态1<-------------------->状态2<------------------->状态3 状态之间跃迁通过条件,条件包含若干事件 1.初始化条件 // 从读表器中查找编号为i的记录 const PlayerFSMConditionInfo* pInfo = (const PlayerFSMConditionInfo*)kConditionLoader.Find(i); if (pInfo) { // 新建条件 FSMCondition* pCondition = new FSMCondition(eFsmEvent_Amount); // 为条件添加事件 for (int j = 0; j < eFsmEvent_Amount; j++) { // 因为0也代表了一个事件,所以,这里用-1来判定对应字段是否有有效数据 if (pInfo->nEvtArray[j] != -1) { // 加入该事件包含的条件 pCondition->AttachEvent(pInfo->nEvtArray[j]); } } // 将条件存入条件集合中 m_vecConditions[i] = pCondition; } else { m_vecConditions[i] = NULL; } // 不同于条件的加载过程,这里需要首先将所有状态构造出来 // 以备稍后对所有状态进行跃迁条件的设置 for (int i = 0; i < eFsmState_Amount; i++) { //创建所有的状态 m_vecStates[i] = new FSMState(i); } 3.注册每个状态的目标状态和相应的条件 // 表格中的记录总数由读表器给出 nCount = kStateLoader.GetRecordCount(); for (unsigned int i = 0; i < nCount; i++) { // 取得第i条记录 const PlayerFSMStateInfo* pInfo = (const PlayerFSMStateInfo*)kStateLoader.Find(i); // 使用表格数据,注册状态跃迁信息 // 即:nSrcStateID状态通过条件nConditionID,可跃迁至nDstStateID RegistTransition(pInfo->nSrcStateID, pInfo->nDstStateID, pInfo->nConditionID); } 4.发送事件,跃迁动作 FSMCondition kCondition(eFsmEvent_Amount); { OutputLog(">>>>>>>> 用户按下鼠标\n"); kCondition.Reset(); kCondition.AttachEvent(eFsmEvent_Click); m_kFSM.Transition(&kCondition); ShowFSMState(); } void FSM::Transition(FSMCondition* pCondition) { //根据条件将当前状态尝试进行状态跃迁 FSMState* pState = m_pCurrentState->Transition(pCondition); if (pState != m_pCurrentState) { // 保存之前的状态 m_pLastState = m_pCurrentState; // 设置当前状态为新的状态 m_pCurrentState = pState; // 通知观察者 Notify(); } } FSMState* FSMState::Transition(FSMCondition* pCondition) { for (unsigned int i = 0; i < m_vecTargetCondition.size(); i++) { //查找是否是目标条件的子集 if (m_vecTargetCondition[i]->IsSubSetOfCondition(pCondition)) { //返回对应的目标状态 return m_vecTargetState[i]; } } return this; } 基本过程这样的 通过配置将条件及其所包含的事件,状态跃迁的条件配置好,程序加载读取配置文件 当动作(事件)发生时,通过该事件构造一个条件,将这个条件和当前状态的目标条件进行匹配,如果匹配上了,就返回对应的目标状态,如果发现状态不同就通知观察者就相应变化,在根据状态决定其行为