您当前的位置: 首页 >  游戏

开发游戏的老王

暂无认证

  • 2浏览

    0关注

    803博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

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

开发游戏的老王 发布时间:2020-10-24 18:11:23 ,浏览量:2

文章目录
      • 前言
      • 基本原理
        • 计时器
        • 输入(事件)队列
        • 调用角色必杀技
        • 子序列问题
      • 完整的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("UP"):
		action = UP
	if Input.is_action_just_pressed("DOWN"):
		action = DOWN
	if Input.is_action_just_pressed("LEFT"):
		action = LEFT
	if Input.is_action_just_pressed("RIGHT"):
		action = RIGHT
	if Input.is_action_just_pressed("A"):
		action = A
	if Input.is_action_just_pressed("B"):
		action = B
	return action


#检查是否有大招成功被激发
func check_combo(s,t):
	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","do_combo",combo_name)
	

#系统归零
func reset():
	action_queue.clear()#清空输入队列
	counter = 0#计时器清零
	is_reading = false


关注
打赏
1656935939
查看更多评论
立即登录/注册

微信扫码登录

0.0406s