文章目錄
- 前言
- 基本原理
- 計時器
- 輸入(事件)佇列
- 呼叫角色必殺技
- 隱藏問題
- 完整的GDScript版必殺技輸入系統
前言
必殺技系統是格斗游戲中必不可少的元素,要觸發角色的必殺技,必須在一個很短的時間內,準確無誤地輸入一個按鍵序列,比如下表中街霸角色隆的部分必殺技:
| 必殺技 | 按鍵序列 |
|---|---|
| 波動拳 | 下,前,拳 |
| 升龍拳 | 前,下,前,拳 |
在上表中還能發現一個隱藏問題,例如:波動拳的
下,前,拳是升龍拳前,下,前,拳的子序列,如果處理不當那么升龍拳可能永遠不會被觸發,
基本原理
-
計時器
直接使用幀作為計時單位,既準確又方便
-
輸入(事件)佇列
當輸入(事件)佇列和出招表的每一個必殺比較時,如果佇列的長度大于必殺的指令長度,需要洗掉佇列頭部的元素以使它們長度相同
-
呼叫角色必殺技
這個系統只處理用戶輸入,完整實作角色的必殺技還需要結合狀態機,比如用戶輸入了下,前,拳,本系統把用戶想觸發波動拳的訊息交發送給狀態機,狀態機決定角色是否能發出波動拳,
-
隱藏問題
上面隱藏問題的處理,實際上就是把處理升龍拳的優先級提前,實際上就是在字典中把升龍拳放前面:
var combos : Dictionary = {
"Shoryuken" : [RIGHT,DOWN,RIGHT,A] ,
"Hadoken" : [DOWN,RIGHT,A]
}
完整的GDScript版必殺技輸入系統
加了注釋
# 格斗必殺技輸入系統 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
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/190405.html
標籤:AI
上一篇:Java程式員:終于,在一個艱難而又輕松的作業日之后,我被辭退了......
下一篇:一篇文章帶你解決 Unable to infer base url. This is common when using dynamic servlet registra
