當前位置: 華文問答 > 遊戲

格鬥遊戲的招式指令實際程式碼是如何判斷的?

2016-09-09遊戲

又是這種問題,我還是不請自來了,不知道這樣的問題為什麽沒人邀請我,邀請我的都是些很奇怪的問題(笑)。我就簡單說說2002年那會接到的格鬥遊戲外包(侍魂某作的移植工作,現在的孩子可能不太知道侍魂是什麽遊戲,你可以百度一下,當年也是世界級大作)是怎麽做吧。

1,有效輸入與無效輸入

首先,你必須明白遊戲中有有效輸入和無效輸入2個概念,大多時候輸入是有效的,但是當你的角色處於一些動作幀的時候,幀的內容(按現在的理解就是「填表內容」)會告訴程式2個資訊:一是這幀時使用者輸入是否有效,二是這幀時使用者輸入緩存(按照現在的概念來看,應該叫做

「輸入緩存」)是否清空。這裏有一個關鍵在於:在邏輯的世界中(並非你肉眼看到的,首先你要能做動作遊戲,你的資質必須支持你看的見共存的兩個世界——現實世界和邏輯世界,他們是耦合的,但並不是完全互相對映的)無效輸入和清理緩存的幀,當你看到圖形的時候未必能夠直接聯想的到關系,這需要很有經驗的策劃和美術的配合(這是現代分工法,當年做動作遊戲的這一批人,要麽就是美術型策劃,要麽都是能寫邏輯程式碼的)才能制作好。

2,「輸入緩存」的產生和遍歷

在且僅在使用者輸入有效的時候,我們會向緩存中寫入我們的操作記錄,這個結構是非常簡單的,如果用虛擬碼寫出來,他就是:

KeyRecord = {"key":按鈕,"time":按下時間}

其中按鈕是這條記錄代表他按了什麽按鈕,對於這個是有一個特殊處理的:

1)方向按鈕,擡起的時候產生KeyRecord,記錄時間卻是按下時間,再按住方向按鈕沒有擡起的時候,也會周期性的增加KeyRecord,time都是根據周期開始時候獲得的。

2)動作按鈕(對應遊戲機上ABCXYZ等),擡起的時候產生KeyRecord,記錄時間也是擡起時間。

最後我們會在記憶體中有一串玩家輸入的2維陣列(為什麽是二維?因為遊戲機有2-4個手柄,我們需要第一維記錄是哪個手柄發起的),去記錄這個KeyRecord。當然沒一個角色的每一個招式的出招表,也是用這個結構的一個陣列array of KeyRecord。

在每次記錄的時候,我們還需要做兩件事情:

1,)根據遊戲設定的「操作指令輸入時間」,通常是100幀(如果一個人用「秒」來說這類遊戲的單位,就證明了他壓根沒有開發過這類遊戲,都是在想當然的,因為在那個環境裏,你能得到的時間只有幀,所以你會發現現在一些模擬環境下,你啟用模擬器加速,你的操作可能會要求更高才能發出招),我們要吧陣列中「超時」的KeyRecord全部刪除,通常這裏很容易最佳化,就是迴圈到第一個不需要刪除的就好了(這是小聰明,現在我仍然覺得有點危險)。

2)遍歷角色每一個招式,首先判斷最後一個按鍵是否符合現在建立的這個KeyRecord(也就是最新輸入,這也是小聰明最佳化,但是依然說不出有什麽不好的),首先如果還有1條以上符合這個條件,那麽在針對這些符合條件的去查詢他們的出招過程是否符合了出招。

3,當符合了出招表的輸入產生了,我們要幹什麽?

只是符合了出招條件,並不等於我們必須放出招式,這裏是一個很重要的Key,我們還有很多邏輯判斷要做:

1)怎樣找出我最想放的是哪招?

當你在遍歷「輸入緩存」的時候,你很有可能找到兩條甚至更多條都符合你想出招的操作,這是很常見的,比如(我這裏就不用KeyRecord了,因為寫時間,地球人是寫不出來的,我就寫一下這個「緩存」裏面有過哪些按鈕):↓↘→↙↓→↘→此時我按下的是A, 這裏還必須先讓你知道一件事情,就是這裏的方向,是面對你角色Flip過得,比如你的角色面向左邊的時候按左,記錄在緩存裏面的是按右 。你會發現這樣的記錄並不奇怪,如果按照出招表(玩家通常都是在遊戲攻略得知的出招表),他可能什麽都發不出來,而是砍了輕刀(在那一作侍魂A是輕刀B是中刀C是重刀D是踢腿Select是挑釁),但事實上使用者這時候的意思很可能有3個(如果使用者操作的是霸王丸):

可能性1:他就是想來個輕刀。

可能性2:旋風斬:我自己給的稱呼,反正就是飛一個龍卷風出去,「遊戲配置表」中是↓→A,遊戲攻略中給出的↓↘→A or B or C,因為寫攻略的人並不知道這其實有3個技能。

可能性3:升龍斬:也是我自己起的名,就是刀轉兩下再來個遨遊跟的那個,→↓↘A,當然槽點還是跟旋風斬一樣。

然而,得出這些以後,我們還會經過幾個步驟,來得出最後我最想放的是哪招,為什麽要有這樣一個過程?因為玩家可能覺得自己的操作是非常符合出招表的,但是出招表給出的並不是官方的數據配置表,而且配合輸入裝置的一些限制,總是會有一些「噪音」被加入到你的操作過程中,如果我們嚴格的按照沒有「噪音」的來做,你會發現一個遊戲根本搓不出招,手感極爛(這個你可以在真說侍魂武士道列傳,這個侍魂的RPG版本中體驗到有多讓你抓狂):

Step1:目前是否接受按鍵,不接受啥都不做(接收條件上面說了)。

Step2:列出一個列表,把這些招式放入表裏,並且定個「親密度」,並且根據親密度把表從上到下排列。親密度是根據最接近尾部的那次操作來算的,我們還是看範例中的「緩存」,然後編個號:1↓,2↘,3→,4↙,5↓,6→,7↘,8→,9A(這是最新加入的,也是本次按鍵)。那麽旋風斬「最近一次」符合輸入是569,升龍斬最近一次符合是3579,取(緩存長度-最大2個按鈕次數之差/需要按鍵次數-abs(最後2次按鍵次數差-平均按鍵次數差))得到親密度(很可能小於0,不過這只是比大小的,所以並沒什麽問題),則可以看出:

旋風斬:需要按鍵次數=3,最大2個按鈕次數之差(這個名詞真不好定,都很拗口)=3(來自9-6)-1(來自6-5)=2,最後2次按鍵次數差=9-6=3,平均按鍵次數差=(3+1)/2=2,結果就是9-1-abs(2-3)=7(長度是9)

升龍斬:需要按鍵次數=4,最大2個按鈕次數之差=0(都是2),最後2次按鍵次數差=2,平均按鍵次數差=2,那麽結果就是9-0-0=9。

因此我們這時候得到了親密度列表順序是:升龍斬→旋風斬。然後我們再把單個按鍵企圖做的動作(當前按鍵是A,所以是輕刀)push到這個列表的最後。

2)得出了這個列表幹什麽呢?

並不是得出列表我立即就放了第一個動作了,那是不可能的事情。我們按照列表的順序遍歷,判斷當前的情況是否可以轉入這個動作,如果可以,那麽就進入這個動作並且return,否則就繼續遍歷下一個,直到列表沒貨。判斷這個動作是否有效的依據是:

a)當前是否有武器,這是侍魂的一個特殊處理點,不適用於所有遊戲,但這也是一層最佳化,其實原本完全可以根據當前角色的動作來確定是否能夠Cancel的,但是這樣就算設計師配置表都會很復雜,所以幹脆增加了「持有武器」這個boolean,要知道在侍魂裏面,旋風斬和升龍斬都是必須有武器才能放的,所以當你「持有武器」==false的時候,就可以直接下一個loop了。

b)當前的動作是否可以被現在判斷的這個動作Cancel,之前有一篇我也發在GameRes的貼文

[經驗心得]動作遊戲中連招的實作

說到了關於Cancel的概念。如果不能Cancel,那麽當前判斷的這個動作不能釋放。

3)找到或者找不到合適的動作,我都要幹什麽?

透過上面一步,我們也許能找到一個合適的動作,作為現在要做的動作,那麽就讓角色立即做那個動作,並且清空這個「緩存」。如果沒有找到,則不執行任何改變。

以上這些是我的一些計畫的實戰經驗,希望對大家有所幫助。