精華區beta GameDesign 關於我們 聯絡資訊
為了驗證上面講的那堆有限機到底能不能達到我要的效果,我隨即開始寫 簡單的前置程式來測試。 我希望宣告一個物件,這個物件要內含上述的幾種State。 而每個State有兩個函式: Init() & runState()。 每當SEEKER從狀態A進入狀態B, 我就讓狀態A初始化。如此可以確保一些參數 回覆到一開始的狀態。 既然每個State有一個必備的Init(),我們可以宣告一個State的原形 再讓各個State繼承之。 這樣做最大的好處在於,我們可以用一個原形陣列去存取所有的State。 假如我想初始化SLEEP state, 我可以寫 sleep.init(); 想初始化FIRE state, 寫 fire.init(); 但是現在有一個問題在於PLAYER可以隨時隨地讓SEEKER進入"GOT"狀態 這意味著無論何時都有可能要初使化"某個"狀態 如果缺少了繼承的機制, 那麼寫出來的code可能會變成這樣: switch (oldState){ case SLEEP: sleep.init(); break; case FIRE: fire.init(); break; . . . } 明明可以很間單的事情卻因為對程式不夠了解的關係變成這樣, 這實在是很不漂亮的一件事情 繼承之後,我們只要宣告一個原形陣列,再把每個STATE的ptr塞進來就好 像這樣: class proto{ virtual void init(); virtual void runState(); }; class sleep: public proto{ void init(); void runState(); }; class fire: public proto{ void init(); void runState(); }; ////////////// proto *store[2]; store[0] = new fire(); store[1] = new sleep(); /////////////////////////////////////////////////////// 這個問題,等到了之後要實作武器庫的時候會再次碰到。 沒有繼承概念的程式碼,如何去應對總計17種不同的武器的選取? 實在難以想像。 總而言之,言而總之,最後關於Seeker的狀態機,寫出來的結果變成這樣: seeker.loop(){ seeker.allState[this.state].runstate(); } 簡化過的程式碼變成這樣。這個seeker.loop() 就是放在主程式的部分, 每秒執行30次的那個,每一次執行,確認目前的狀態,然後執行此狀態的運算 其中如果有符合更改狀態的條件(如上篇文章的圖表所示),則透過更改this.state 來達成跳離STATE & 初始化的動作。 至於每個State的runState function,這邊就略過了。 大體就是把上篇文章的條件機制加以程式化而已。 畢竟講解Code是件無聊的事情。我還是主要講想法以及實作方式就好。 (續) 文章轉自暨大霞蔚山城 ★ HenryBBS (henry.twbbs.org) -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 163.22.18.97