• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            3d Game Walkman

            3d圖形渲染,網絡引擎 — tonykee's Blog
            隨筆 - 45, 文章 - 0, 評論 - 309, 引用 - 0
            數據加載中……

            淺談狀態機FSM設計方法

            看了一晚上FSM方面的資料,頗有收獲,寫寫感悟:

            狀態機,在游戲里面是非常重要的,最簡單的狀態機,莫過于

            switch()
             case 1:
                if(not 反復執行狀態1)
                   進入1狀態前要做的準備

                進入1狀態的過程

                if(not 反復執行狀態1)
                   離開狀態1的過程

              case2:
            ...

            但這種方式不能很有效預定義所有的狀態,也不能把這些狀態之間的切換過程合理的定義出來,“狀態”本身沒有一個合理的定義,幾乎是一種面向過程的方式,只過這種方式足夠簡單,也最容易讓人接受,缺點就沒有“狀態”的定義和指派功能,導致狀態的混亂,出現狀態處理重復代碼,甚至處理不一致的問題,按照OO的觀念,狀態描述本來就應該是一種實體

            比如“吃飯”這種狀態,進入要做什么,進行時要做什么,退出時要做什么,需要進行一個描述,以下是我寫的狀態機管理策略:

            //狀態的定義
            class State
            {
            public:

             State();

             State(const char * name);

             //狀態的名字
             std::string statename;
             //比較兩個狀態是否相同
             inline bool operator ==(const State& other);
            };


            //狀態機基類
            class BaseFsm
            {

            public:

             //狀態機的狀態描述
             State state;

             //進入狀態
             virtual void Enter(FsmEntity *entity);

             //執行狀態
             virtual void Execute(FsmEntity *entity);

             //離開狀態
             virtual void Exit(FsmEntity *entity);

             //比較兩個狀態機是否相同
             inline bool operator ==(const BaseFsm& other);
            };


            //狀態機實體
            class FsmEntity
            {

            protected:

              //當前所使用的狀態機
              BaseFsm *mCurrentFsm;

            public:

              //構造函數
              FsmEntity();

              //析構函數
              virtual ~FsmEntity();

              //設置開始狀態
              void InitState(BaseFsm *fsm);

              //狀態是否初始化了
              bool IsStateInited();

              //保持狀態的方法
              void KeepState();

              //返回當前的狀態機
              BaseFsm * GetCurrentFsm();

              //改變狀態
              void ChangeState(BaseFsm *newFsm);
            };


            //狀態機容器
            class FsmManager
            {

            private:

            //狀態機容器的名稱
             std::string name;

             //所有的狀態集合
             std::map<std::string, BaseFsm *> mStatusCollection;

            public:

             //命令一些實體去達到某個狀態
             void Transaction(std::vector<FsmEntity *> & entities, const char * stateName);

             //令某個實體達到某個狀態
             void Transaction(FsmEntity * entity, const char * stateName);

             //添加狀態機
             void AddFsm( BaseFsm * fsm);

             //刪除狀態機
             void RemoveFsm(const char * stateName);

             //獲取狀態機
             BaseFsm * FindFsm(const char * stateName);

                //構造
             FsmManager(const char *fsname);

             //析構
             virtual ~FsmManager();
            };




            State::State()
            {

            }

            State::State(const char * name)
            {
             statename = name;
            }


            //構造函數
            FsmEntity::FsmEntity()
            {
              mCurrentFsm = 0;
            }

            //析構函數
            FsmEntity::~FsmEntity()
            {
             
            }

            //返回當前的狀態機
            BaseFsm * FsmEntity::GetCurrentFsm()
            {
             return mCurrentFsm;
            }

            //狀態是否初始化了
            bool FsmEntity::IsStateInited()
            {
             if(mCurrentFsm)
               return true;
             else
               return false;
            }

            //設置當前狀態
            void FsmEntity::InitState(BaseFsm *fsm)
            {
             if(mCurrentFsm == 0)
             {
               mCurrentFsm = fsm;
             }
             else
             {
              LOG(0, WARN_LV, "初始狀態已經設定");
             }
            }

            //保持狀態的方法
            void FsmEntity::KeepState()
            {
             mCurrentFsm->Execute(this);
            }

            //改變狀態
            void FsmEntity::ChangeState(BaseFsm *newFsm)
            {
             if(mCurrentFsm)
                //離開原來的狀態
                mCurrentFsm->Exit(this);

             //設定現有狀態
             mCurrentFsm = newFsm;

             //進入現有狀態
             mCurrentFsm->Enter(this);

             //執行現有的狀態
                mCurrentFsm->Execute(this);

            }


            //比較兩個狀態是否相同
            bool State::operator ==(const State& other)
            {
             return statename == other.statename;
            }

             

            //進入狀態
            void BaseFsm::Enter(FsmEntity *entity)
            {
              LOG(0, DEBUG_LV, "進入%s狀態", state.statename.c_str());
            }

            //執行狀態
            void BaseFsm::Execute(FsmEntity *entity)
            {
              LOG(0, DEBUG_LV, "執行%s狀態", state.statename.c_str());
            }

            //離開狀態
            void BaseFsm::Exit(FsmEntity *entity)
            {
              LOG(0, DEBUG_LV, "離開%s狀態", state.statename.c_str());
            }


            bool BaseFsm::operator ==(const BaseFsm& other)
            {
                return state == other.state;
            }

            //命令一些實體去達到某個狀態
            void FsmManager::Transaction(std::vector<FsmEntity *> & entities, const char * stateName)
            {
             for(size_t i = 0; i < entities.size(); i ++)
             {
              FsmEntity *entity = entities[i];
              Transaction(entity, stateName);
             }
            }

            //令某個實體達到某個狀態
            void FsmManager::Transaction(FsmEntity * entity, const char * stateName)
            {
             if(entity->GetCurrentFsm() && entity->GetCurrentFsm()->state.statename == stateName)
             {
              entity->KeepState(); //保持之前的狀態
             }
             else
             {
              BaseFsm * fsm = mStatusCollection[stateName];
              if(fsm)
              {
               //執行狀態
               entity->ChangeState(fsm);
              }
              else
              {
                        LOG(0, ERROR_LV, "找不到%s狀態", stateName);
              }
             }
            }

             

            //添加狀態機
            void FsmManager::AddFsm( BaseFsm * fsm)
            {
              if(mStatusCollection.find(fsm->state.statename.c_str()) != mStatusCollection.end())
               return; //已經添加過了
              //添加
              mStatusCollection[fsm->state.statename] = fsm;
            }

            //刪除狀態機
            void FsmManager::RemoveFsm(const char * stateName)
            {
              std::map<std::string, BaseFsm *>::iterator it = 0;
              if((it = mStatusCollection.find(stateName)) != mStatusCollection.end())
              {
                 mStatusCollection.erase(it);
              }
            }

            //獲取狀態機
            BaseFsm * FsmManager::FindFsm(const char * stateName)
            {
             std::map<std::string, BaseFsm *>::iterator it = 0;
             if((it = mStatusCollection.find(stateName)) != mStatusCollection.end())
             {
               BaseFsm * fsm = it->second;
               return fsm;
             }
             return 0;
            }

             

            //構造
            FsmManager::FsmManager(const char *fsname)
            {
               name = fsname;
               LOG(0, DEBUG_LV, "構造狀態機容器 %s", fsname);
            }

            //析構
            FsmManager::~FsmManager()
            {

             //移出所有的狀態機
             for(std::map<std::string, BaseFsm *>::iterator it = mStatusCollection.begin(); it!= mStatusCollection.end(); it++)
             {
                   BaseFsm * fsm = it->second;
                if(fsm)
               delete fsm;
             }

            }






            posted on 2009-08-07 17:30 李侃 閱讀(5970) 評論(5)  編輯 收藏 引用 所屬分類: 設計思路

            評論

            # re: 淺談狀態機FSM設計方法[未登錄]  回復  更多評論   

            請問能不能介紹幾本關于這方面的書呢..謝謝!!
            2009-08-08 00:30 | vibilin

            # re: 淺談狀態機FSM設計方法[未登錄]  回復  更多評論   

            其實設計模式解決這個問題的最后也得使用配置文件才能解決問題,當時有C語言時,你要是使用配置文件,一樣是可以解決的
            2009-08-08 09:11 | Alex

            # re: 淺談狀態機FSM設計方法  回復  更多評論   

            全部是網上找的資料,GEM系列書上有介紹過,資料很零碎,具體上面的狀態機封裝形式還要結合腳本引擎,才能真正發揮它的威力,我已經這么做了,總之,就是一句話:很好很強大 o(∩_∩)o...
            2009-08-08 09:43 | 李侃

            # re: 淺談狀態機FSM設計方法  回復  更多評論   


            狀態機三個字足夠包含一切
            2009-08-08 17:11 | Vincent

            # re: 淺談狀態機FSM設計方法  回復  更多評論   

            第一個真不錯,三言兩語就解釋出來了,后面這個OO的,不知道寫起來維護會如何?幾千個狀態轉換起來。。。。
            2009-08-10 12:01 | j
            18禁黄久久久AAA片| 久久久精品久久久久特色影视| 午夜精品久久久久成人| 2020国产成人久久精品| 日韩久久久久久中文人妻 | 久久精品国产亚洲综合色| 久久综合九色综合欧美狠狠| 大美女久久久久久j久久| 久久久久国产精品嫩草影院| 成人国内精品久久久久影院| 久久这里只精品国产99热| 久久精品亚洲福利| 久久国产高潮流白浆免费观看| 久久九九亚洲精品| 久久WWW免费人成一看片| 99久久综合国产精品二区| 人妻无码久久一区二区三区免费| 国产L精品国产亚洲区久久| 久久精品国产亚洲精品2020| 亚洲国产成人精品91久久久 | 一本色道久久综合狠狠躁| 99久久婷婷国产一区二区| 伊人久久大香线焦AV综合影院| 亚洲伊人久久大香线蕉苏妲己| 亚洲精品无码专区久久久| 久久久噜噜噜久久中文字幕色伊伊| 久久九九精品99国产精品| 久久久久久曰本AV免费免费| 久久嫩草影院免费看夜色| 99久久99久久精品国产片果冻| 久久久噜噜噜久久熟女AA片| 久久AV高潮AV无码AV| 久久91精品国产91| 伊人久久一区二区三区无码| 久久久久这里只有精品| 青青草原综合久久大伊人导航| 亚洲综合精品香蕉久久网97| 久久婷婷激情综合色综合俺也去| 久久精品国产色蜜蜜麻豆| 麻豆精品久久久久久久99蜜桃| 久久这里只精品99re66|