遊戲編程中的小技巧:遊戲輸入的處理

一. 遊戲的輸入設備

遊戲的輸入設備,指的是日常玩家用於控制遊戲的一些外部/內部設備:PC機和家用遊戲機的鍵盤,鼠標,手柄;移動機上則以觸摸,重力感應,攝像頭的手勢識別爲主;還有最近用於AR/VR的設備,如WiiMote,Kinect,VR眼鏡一體機,索尼PlayStation vr等。這些在遊戲中已經成爲玩家獲取遊戲體驗感的重要來源。既要簡化用戶對遊戲的操作,又要能夠提升遊戲對用戶輸入反饋的處理能力,這是提升遊戲體驗感的一個重要方面。

目前對於端遊和手遊的輸入模式主要分爲兩種:數字和模擬。數字形式的輸入只有兩種狀態:按下去,沒有按。不存在介於兩者之間的情況;而模擬形式則是對用戶的輸入返回一個特定區間的值,一般是介於 -1 ~ 1 之間,對於一些比較複雜的操作,或者格鬥類遊戲的組合鍵下主要使用模擬形式。

當然,針對玩家日益提升的遊戲能力,遊戲中也需要考慮對“同時按鍵”和“序列按鍵”的支持。這種需求在格鬥類,角色扮演類,體育類遊戲中用的很多,例如拳皇和街霸中的各種連續技,組合技,NBA2k19中各種運球投籃動作等。

二. 數字輸入

除了文本類遊戲,現今大多數圖形類遊戲又不再使用標準輸入,因爲控制檯是不會長時間開啓,大多數遊戲會使用一些庫來封裝對這些設備輸入的查詢,例如Simple DirectMedia layer(SDL)的跨平臺庫。當用戶進行按鍵控制時,系統會將該按鍵對應的索引置爲true,從而反饋到遊戲中。

但僅僅這樣是不夠的,我們知道遊戲和軟件系統不一樣,用戶往往會在同一時間,甚至在短短1s內使用多個按鍵,而且遊戲一般運行在30FPS ~ 60FPS之間,用戶在這一幀按下的操作,通常在往後的幾幀中得到顯示和反饋,這就是玩家所說的“按鍵延遲”的一種情況,在網絡不好的時候尤爲突出。

目前較好的優化方法是追蹤遊戲上下幀的狀態。
在這裏插入圖片描述
這樣我們可以只針對用戶的操作提前進行處理而不是等到用戶已經操作後再進行處理,這會大大降低遊戲的流暢度。(還有一種情況,如果遊戲中需要“充能”操作,即長按某個按鍵蓄力,我們可以在“用戶剛剛輸入”時開始賦予初始值,每一幀增加定量,知道“用戶剛剛鬆開”後完成“充能”)。

三. 模擬輸入

模擬輸入會反饋一組範圍值,因爲輸入後的數值波動非常開,在整個遊戲之中系統不一定能及時處理到反饋而值就已經消失了,或者當玩家沒有使用手柄時,實際上模擬輸入的值也不會是0,這就是輸入偏差。基於這樣一般虛擬輸入不會直接應用到角色的移動中。不過凡事沒有絕對,我們可以採用一種“模擬輸入過濾”的方式來消除偏差。

在這裏插入圖片描述
在手柄搖桿中,半徑爲整個可移動範圍的半徑的10%內,所有返回的值均置爲0,即相當於靜止;當半徑處於10% ~ 100%時才視爲有效。

但是對於一些遊戲來說,對用戶操作非常敏感,那麼就無法利用到低於10%的值,那麼我們可以換一種方法,可以使用向量運算來完成無效區域的過濾。

vector2 inp = get user input
float len = inp.length()
float pct = (len - minValue) / (maxValue - minValue)

這樣就能充分利用0 ~ 100%的有效區域。

四. 基於事件機制的輸入

針對一般的遊戲場景,遊戲本身是不會主動反饋信息給用戶的。那麼對於輸入系統來說,很多的代碼都會“輪詢”輸入,比如主動檢查某某鍵是否觸發對應的操作,那麼每一幀都要去調用,去輪詢,不僅代碼量大,而且容易消耗內存,產生一定的BUG。

相比於讓代碼“輪詢”,還不如我們一開始就設置一個事件機制推送系統。在基於事件的遊戲系統下,每一部分的代碼都需要註冊其關心的事件通知,當輸入事件發生時,系統發出通知到所有已註冊的代碼,它們在收到通知後會立即執行其相應操作。當然,輪詢是不可避免的,我們只能將多個地方的輪詢彙總成一個地方進行輪詢,降低內存消耗。

五. 依賴字典映射的輸入

字典,是由一系列“Key-value”值組成的集合。在遊戲系統中使用字典會提升遍歷的速度。在這個系統中,Key就是綁定的名字(如“Horizontal”,“Jump”,“Fire”),Value則是按鈕的信息,包括對應的按鍵和按鍵對應的觸發時機。

每一幀,輸入系統都會檢查這個字典的所有鍵值,並判斷此時Key所對應的狀態,然後再進行更改。字典首先會將更改的操作提供給UI系統,UI系統會判斷哪些UI會受到這些操作的影響,然後再傳遞到遊戲中進一步的處理。(注意,比如“B”按鍵,有可能同時對應揹包系統快捷鍵以及遊戲場景的某個操作,這時必須先判斷UI層 --遊戲場景層)。

六. 移動設備的輸入

隨着遊戲向移動端的大量湧入,大多數遊戲也需要開發出移動端。相比於PC端,移動端的輸入方式有限,但是又要儘量做到PC端一樣的操作複雜度,在輸入系統上也需要花費一定的時間去設計完善。

1.觸屏和手勢

觸屏,是所有移動端遊戲的首選輸入方式。通過玩家手指與屏幕的交互,來達到像PC上玩家用鼠標控制遊戲的精準度。不過大多數的移動設備支持了多點觸摸,這是和鼠標的一個較大不同點。多點觸摸的好處是能讓玩家在移動端上對遊戲進行快捷流暢的操作,又能在這基礎上增加操作的複雜度,提升移動端遊戲的可玩性。

手勢操作,是目前移動端基於觸屏衍生的一種操作。玩家通過雙指及以上的手勢操作來達到一些快捷的功能實現,比如“兩指縮放”,“雙擊放大縮小”等。除了系統自帶的手勢識別功能,我們也可以自定義一些複雜度較低的新操作:在Android上
我們可以用“Gestures Bulider”程序,在IOS上,我們可以寫一個類繼承“UIGestureRecognizer”來實現。

在檢測用戶的手勢上,最常用的就是“羅賓算法”(Rubine 算法),它是由早期筆畫識別發展而來,對於該算法就不詳細展開講了,各位有興趣的可以手動百度一下。

2.加速器和陀螺儀

加速器,檢測移動設備在座標軸上的加速度。例如,當你豎着拿手機的時候,向上移動,就會得到y軸方向的加速度,當你平放手機,向上移動,就會得到z軸方向的加速度。

陀螺儀,則是檢測移動設備的軸向旋轉。比如我們在玩賽車類的遊戲時(狂野飆車8),玩家控制賽車的轉向,就是利用手機的陀螺儀來感知手機的軸向,從而實現對遊戲的控制,這樣相對於觸屏控制來說玩家的操作性更高更流暢。

總結不易,如有不足,懇請指導!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章