• <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 李侃 閱讀(5972) 評論(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
            性做久久久久久久久浪潮| 久久精品国产只有精品2020| 久久电影网2021| 精品久久久久久无码专区| 亚洲国产精品无码久久久蜜芽| 免费精品国产日韩热久久| 国产高清美女一级a毛片久久w| 精品国产91久久久久久久| 国内精品久久久久影院免费| 丰满少妇人妻久久久久久| 久久精品国产精品国产精品污| 69久久夜色精品国产69| 国产精品久久久久…| 91精品国产91热久久久久福利| 久久www免费人成精品香蕉| 久久国产精品二国产精品| 久久久久这里只有精品| 少妇久久久久久被弄到高潮| 伊人久久大香线蕉av一区| 看全色黄大色大片免费久久久| 久久精品视频一| 狠狠久久综合伊人不卡| 久久久久免费视频| 狠狠色综合网站久久久久久久高清| 韩国免费A级毛片久久| 国内精品伊人久久久久妇| 久久99国产精品99久久| 人妻精品久久久久中文字幕一冢本 | 久久久中文字幕| 久久亚洲国产中v天仙www| 日韩精品无码久久久久久| 91麻精品国产91久久久久| 亚洲欧美伊人久久综合一区二区 | www久久久天天com| 奇米综合四色77777久久| 久久久久久综合网天天| 精品国产一区二区三区久久| 欧美激情一区二区久久久| 国产女人aaa级久久久级| 国产精品一久久香蕉国产线看| 精品综合久久久久久97|