Godot Engine:格斗游戏中的必杀技(大招/绝招/特殊技/Special Move )输入系统实现

风流意气都作罢 提交于 2020-10-26 10:54:38

前言

必杀技系统是格斗游戏中必不可少的元素,要触发角色的必杀技,必须在一个很短的时间内,准确无误地输入一个按键序列,比如下表中街霸角色隆的部分必杀技:

必杀技 按键序列
波动拳 下,前,拳
升龙拳 前,下,前,拳

在上表中还能发现一个隐藏问题,例如:波动拳的下,前,拳 是升龙拳前,下,前,拳的子序列,如果处理不当那么升龙拳可能永远不会被触发。

基本原理

  • 计时器

直接使用作为计时单位,既准确又方便

  • 输入(事件)队列

当输入(事件)队列和出招表的每一个必杀比较时,如果队列的长度大于必杀的指令长度,需要删除队列头部的元素以使它们长度相同

  • 调用角色必杀技

这个系统只处理用户输入,完整实现角色的必杀技还需要结合状态机,比如用户输入了下,前,拳,本系统把用户想触发波动拳的消息交发送给状态机,状态机决定角色是否能发出波动拳。

  • 隐藏问题

上面隐藏问题的处理,实际上就是把处理升龙拳的优先级提前,实际上就是在字典中把升龙拳放前面:

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


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!