1. 程式人生 > >命令模式(1)

命令模式(1)

請求 str 只有一個 編碼 不同 名稱 處理 什麽 unity

實現玩家自定義按鍵------基於Unity3D

本文是根據Robert Nystrom所著的Game programming patterns所寫,向作者致敬!

在Robert所寫的書中,代碼全部是用C++所寫,且大部分是片段,但是可讀性非常好,稍加改動就可以應用到實際項目中去。本文使用近年來比較火熱的引擎Unity3D來實現部分編程模式,使用語言是C#。本人水平有限,有些地方理解不到位,還望大家指出。

命令模式,作者對它的解釋是:“命令就是一個對象化方法的調用。”

我對這句話的理解是,一些命令,例如jump、attack、avoid之類的命令,看起來不足以成為一個類,可能只是某個類的一個方法,但是當我們使用命令模式進行編程的時候,將這個方法的“等級”提升,將其提升到一個類的高度,例如JumpCommand、AttackCommand、AvoidCommmand這些類。這些類裏面只有一個函數,如JumpCommand類裏面會有jump這個方法,用來控制玩家的跳躍操作。

這樣做的好處是什麽?

在遊戲中,行為請求者與行為實現者通常是一種緊耦合的關系,例如玩家鍵入“K”,想讓角色可以跳起來,那麽我們通常可能判斷當”K”被按下時,進行某些操作。用偽代碼來說明一下吧。

if(isPressed(BUTTON_K))jump();

這樣就形成了一種緊耦合關系,按鍵和功能緊緊的合在一起。靈活度大大降低。 比如我們現在有一個功能,需要讓用戶自主的更改按鍵所對應的功能,例如玩家想讓”BUTTON_K”可以attack而不是jump,如果這樣硬編碼(寫死),我們就無法實現玩家自定義按鍵的功能了。對於這種用戶需求,命令模式就是很好的一個應用。

再一個,例如在遊戲中,我們讓玩家可以撤銷步驟,這在一些策略遊戲中是很常見的功能。如果像一般的編程方式那樣,執行一個操作僅僅只是調用一個函數,那麽當這個函數執行完了,關於這函數執行的一些相關信息也就消失了。那麽我們無法記錄行為,從而很難撤銷或重做。而使用命令模式,就很簡單了。

接下來我們先來實現配置玩家輸入問題。大部分代碼基於Robert的書,我在Unity3D裏實現。

一、首先定義一個玩家行為的類,用來操作玩家(所控制的角色):

技術分享圖片

具體的功能沒有實現,只是在控制打印出相應的操作。

二、接下來定義抽象基類用來代表一個可觸發的遊戲命令:

技術分享圖片

然後為每個不同的遊戲動作命令創建一個子類:
技術分享圖片
技術分享圖片
技術分享圖片

以上的類只是一小部分功能,如果還需要更多的功能,則繼續派生即可。這裏的command類都只會完成一件事件,就是操縱玩家的行為。

三、接下來我們還需要一個輸入處理類,用來對輸入進行一定的處理。

1、定義按鈕,按鈕的類型是command類型,因為一個按鈕對應一種command(當然,可以由用戶自己定義):
技術分享圖片

2、初始化這些按鈕,我把它們寫在了構造函數裏面,開始的時候,我將J、K、L分別定義為attack、jump、avoid:
技術分享圖片

3、定義handleInput函數,傳入參數是按鍵的名稱,例如“K”代表鍵盤上的K,返回和buttonK_綁定的命令:
技術分享圖片

4、定義綁定函數,這時命令模式的優勢就顯現出來啦,綁定函數有兩個輸入值,一個是按鍵名稱,一個是綁定的命令,這樣調用這個函數,就可以修改之前已經初始化的按鍵了。
技術分享圖片

四、最後我們定義玩家主邏輯:

1、首先我們定義一些變量:
技術分享圖片

2、在Start函數中進行初始化:
技術分享圖片

3、然後就是每一幀的邏輯了,就是判斷哪些按鍵被按下,然後傳遞這些被按下的值,到inputHandler裏去進行處理:
技術分享圖片

至此所有的代碼都已經完成了,已經初步的實現了我們的功能,當然代碼還以繼續完善,進入Unity3D中進行測試!

1、面板中的遊戲對象
技術分享圖片

2、player的屬性
技術分享圖片

3、J K L Shift J K L依次鍵入的效果
技術分享圖片

由此可以看出,在按下leftShift後,按鍵對應的操作發生了變化。至此,我們完成了自定義按鍵功能的需求!

命令模式(1)