必殺技系統是格鬥遊戲中必不可少的元素,要觸發角色的必殺技,必須在一個很短的時間內,準確無誤地輸入一個按鍵序列,比如下表中街霸角色隆的部分必殺技:
必殺技 | 按鍵序列 |
---|---|
波動拳 | 下,前,拳 |
升龍拳 | 前,下,前,拳 |
在上表中還能發現一個隱藏問題,例如:波動拳的
下,前,拳
是升龍拳前,下,前,拳
的子序列,如果處理不當那麼升龍拳可能永遠不會被觸發。
直接使用幀作為計時單位,既準確又方便
當輸入(事件)佇列和出招表的每一個必殺比較時,如果佇列的長度大於必殺的指令長度,需要刪除佇列頭部的元素以使它們長度相同
這個系統只處理使用者輸入,完整實現角色的必殺技還需要結合狀態機,比如使用者輸入了下,前,拳
,本系統把使用者想觸發波動拳的訊息交傳送給狀態機,狀態機決定角色是否能發出波動拳。
上面隱藏問題的處理,實際上就是把處理升龍拳的優先順序提前,實際上就是在字典中把升龍拳放前面:
var combos : Dictionary = {
"Shoryuken" : [RIGHT,DOWN,RIGHT,A] ,
"Hadoken" : [DOWN,RIGHT,A]
}
加了註釋
# 格鬥必殺技輸入系統 V3
extends Node
enum { NONE ,UP,DOWN,LEFT,RIGHT,A,B} #和必殺技相關的事件
var action_queue : Array = []#輸入的事件佇列,NONE事件會被過濾掉
var counter := 0#計時(數)器
var is_reading := false#標記是否在輸入必殺技
const MAX_COUNT := 100#最大幀數
### 記錄大招的字典
var combos : Dictionary = {
"Shoryuken" : [RIGHT,DOWN,RIGHT,A] ,
"Hadoken" : [DOWN,RIGHT,A]
}
func _process(delta):
var current_action = read_action()
if current_action != NONE:
if not is_reading:
is_reading = true
action_queue.push_back(current_action)
for combo_name in combos:
if check_combo(action_queue,combos[combo_name]):
trigger_combo(combo_name)
print( combo_name )
reset()
break
if is_reading:
counter += 1
if counter >= MAX_COUNT:#如果超出了輸入時限。則系統歸零
reset()
#讀入輸入事件
func read_action():
var action = NONE
if Input.is_action_just_pressed("ui_up"):
action = UP
if Input.is_action_just_pressed("ui_down"):
action = DOWN
if Input.is_action_just_pressed("ui_left"):
action = LEFT
if Input.is_action_just_pressed("ui_right"):
action = RIGHT
if Input.is_action_just_pressed("ui_j"):
action = A
if Input.is_action_just_pressed("ui_k"):
action = B
return action
#檢查是否有大招成功被激發
func check_combo(s,t):
if s.size() < t.size():
return false
var c
if s.size() > t.size():
c = s.duplicate()
c.invert()
c.resize(t.size())
c.invert()
else:
c = s
for i in range(t.size()):
if c[i] != t[i]:
return false
return true
#觸發角色的大招
func trigger_combo(combo_name):
get_tree().call_group("Ryu","Combo",combo_name)
#系統歸零
func reset():
action_queue.clear()#清空輸入佇列
counter = 0#計時器清零
is_reading = false