本節書摘來異步社群《遊戲程式設計模式》一書中的第7章,第7.3節,作者: 【美】robert nystrom (尼斯卓姆) 譯者: 趙衛兵 , 許新星 , 姜召陽 , 陳侃 , 屈光輝 , 鄭炯彬 責編: 陳冀康,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。
一個問題是,heroine類有一些布爾類型的成員變量:isjumping_和isducking_,但是這兩個變量不應該同時為true。當你有一系列的标記成員變量,而它們隻能有且僅有一個為true時,這表明我們需要把它們定義成枚舉(enum)。
在這個例子當中,我們的有限狀态機的每一個狀态可以用一個枚舉來表示,是以,讓我們定義以下枚舉:
這裡沒有大量的标志位,heroine類隻有一個state_成員。我們也需要調換分支語句的順序。在前面的代碼中,我們先判斷輸入事件,然後才是狀态。那種代碼可以讓我們集中處理每一個按鍵相關的邏輯,但是,它也讓每一種狀态的處理代碼變得很亂。我們想把它們放在一起來處理,是以,我們先判斷狀态。代碼如下:
我們可以像下面設定其他狀态:
這樣看起來雖然很普通,但是它卻是對前面的代碼的一個提升。我們仍然有一些條件分支語句,但是我們簡化了狀态的處理。所有處理單個狀态的代碼都集中在一起了。這是實作狀态機最簡單的方法,而且在某些情況下,這樣做也挺好的。
重要的是,我們的女主角再也不可能處于一個無效的狀态了。通過布爾值辨別,會存在一些沒有意義的值。但是,使用枚舉,則每一個枚舉值都是有意義的。
你的問題可能也會超過此方案能解決的範圍。比如,我們想在主角下蹲躲避的時候“蓄能”,然後等蓄滿能量之後可以釋放出一個特殊的技能。那麼,當主角處于躲避狀态的時候,我們需要添加一個變量來記錄蓄能時間。
如果你猜這是更新方法模式,那麼恭喜你,你猜中了!
我們可以在heroine類中添加一個chargetime_成員來記錄主角蓄能的時間長短。假設,我們已經有一個update()方法了,并且這個方法會在每一幀被調用。在那裡,我們可以使用如下代碼片斷能記錄蓄能的時間:
我們需要在主角躲避的時候重置這個蓄能時間,是以,我們還需要修改handleinput()方法:
總之,為了添加蓄能攻擊,我們不得不修改兩個方法,并且添加一個chargetime_成員變量給主角,盡管這個成員變量隻有在主角處于躲避狀态的時候才有效。其實我們真正想要的是把所有這些和與之相關的資料和代碼封裝起來。接下來,我們介紹gof的狀态模式來解決這個問題。