本節書摘來異步社群《遊戲程式設計模式》一書中的第7章,第7.8節,作者: 【美】robert nystrom (尼斯卓姆) 譯者: 趙衛兵 , 許新星 , 姜召陽 , 陳侃 , 屈光輝 , 鄭炯彬 責編: 陳冀康,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。
我們決定給我們的主角添加持槍功能。當她持槍的時候,她仍然可以:跑、跳和躲避等。但是,她也需要能夠在這些狀态過程中開火。
如果你執着于傳統的有限狀态機,那我們可能需要把之前的狀态加倍。對于每一個已經存在的狀态,我們需要定義另一個狀态,它做的事情也差不多,不過就是多了持槍的操作。比如站立狀态和站立開火狀态,跳躍狀态和跳躍開火狀态等。
如果我們添加更多的武器種類,那麼這個狀态數量将會急劇增加。而且不僅僅是增加了大量的狀态類執行個體,它還會增加大量的備援,實際上帶不帶槍的狀态僅有是否包含開火代碼的差別而已。
這裡的問題是,我們把兩種狀态雜合在一起了。我們把兩種不同的狀态硬塞到一個狀态機裡面去了。為所有可能出現的組合模組化,我們可能需要為每一種狀态準備一組狀态。解決方法比較直覺,就是分開成兩個狀态機。
如果我們需要為主角定義n種狀态和m種它能夠攜帶的武器狀态,如果使用一個狀态機來表示,那麼我們需要n×m個狀态。而如果使用兩個狀态機,那麼狀态組合僅是n+m。
首先我們可以保留原有的狀态機的代碼和功能不管它。接下來,我們定義一個單獨的狀态機,用來處理主角攜帶的武器。現在,我們的主角會有兩個狀态索引,其中一個看起來如下所示:
為了便于示例說明,我們這裡使用了完整的狀态模式來處理女主角的裝備變化。事實上,由于裝備目前隻有兩個狀态,我們完全可以隻使用一個布爾值變量來替代。
當主角派發輸入事件給狀态類時,需要給兩種狀态都派發一下。
這樣每一個狀态機都可以響應輸入事件并以此切換狀态而不用考慮其他狀态機的實作細節。當兩個狀态沒什麼關系的時候,這種方法工作得很好。
功能更加完備的系統可能會讓一個狀态機來處理輸入,以便另外一個狀态機不會接收到輸入。這樣将能防止兩個狀态機對同一輸入進行錯誤的響應。
在實際中,你可能會發現你需要對某些狀态處理進行幹預。比如,如果主角不能夠在跳躍的過程中開火,或者她在裝備武器的時候不能俯沖。為了處理這種情況,在代碼裡面,對于每一個狀态,你可能需要做一些簡單的if判斷并做出特殊處理。雖然這可能不是最好的解決方案,但是至少它可以完成任務。