Godot组合键的实现
Posted 张学徒
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Godot组合键的实现相关的知识,希望对你有一定的参考价值。
Godot 3.4
组合键,连招时对按键的判定,实现代码。底部有使用的示例文件
关键代码:
#==================================================
# Componse Input - 组合输入
#==================================================
# * 延迟判断按键是否被按下,防止操作过于快速导致组合键失效
# * 例,按下:小键盘方向键左+空格,则触发操作:
# add_mapper(
# "刺"
# , ["ui_accept", "ui_left", "ui_right"] # 包含的组合键
# , ["ui_accept"] # 在按下的一刻才被检测到的键
# , ["ui_left", "ui_right"] # 其中的一个键被检测到则都被检测到
# )
#==================================================
# @datetime: 2021-12-21 22:50:05
#==================================================
extends Node
# 每个按键组合会在其中一个按键被触发时进行计时器倒计时
# 进行组合件判定,如果到达时间,则会进行释放掉所有已按
# 下的记录,会在此进行发出释放掉的按键,以便可以连接这
# 个信号去执行其他可能的操作
## @keys 释放掉的key
## @release_all 是否全部释放掉了
## @map_name 释放掉的是哪个组合键
signal released(keys, release_all, map_name)
## 按键映射
var input_mapper : Dictionary =
#==================================================
# 自定义方法
#==================================================
#(override)
func _physics_process(delta):
for m in input_mapper.values():
m.physics_process()
## 添加 key 映射
## @key 判断的 key
## @input_maps 触发的键盘映射
## @just 仅仅在按下那一刻才检测到
## @or_input 其中的一个按下即为各个都按下
func add_mapper(
key: String,
input_maps: PoolStringArray,
just: PoolStringArray = [],
or_input: PoolStringArray = []
):
input_mapper[key] = ComponseKey.new(
self, key, input_maps, just, or_input
)
## 获取已按下的键
## @key
func get_inputed_key(key: String) -> Array:
return input_mapper[key].get_inputed()
## 清除按键记录
## @key
func clear(key: String):
input_mapper[key].clear()
## 清空所有按键记录
func clear_all():
for key in input_mapper:
input_mapper[key].clear()
## 回调方法
##(每个组合键会在释放掉记录的按键时,调用这个方法)
## @data
func callback(data):
emit_signal("released",
data.released_keys,
data.released_all,
data.map_name
)
#==================================================
# 组合键
#==================================================
class ComponseKey:
# 在这个时间内按下的组合键则进行释放,可自行调整修改这个时间
# 不过如果值太小,会判定困难,因为用户可能两个键按键间隔没有那么快
const DURATION = 0.1
var _host : Node
var _map_name : String = ""
var _release_timer := Timer.new()
var _delta = 1.0 / ProjectSettings.get("physics/common/physics_fps")
# 仅仅在按下的时候才被检测
var _just :=
# 或输入(其中一个按下了,则全部都算作按下了)
var _or_input :=
# 已按下的按键
var _inputted :=
# 已按下按键的数量
var _inputted_count : int = 0
func _init(
host: Node # 这个对象的宿主,用于添加计时器到这个节点上
, map_name : String
, input_maps: PoolStringArray # 判定的按键
, just: PoolStringArray = [] # 是否只是在按下那一刻才测到
, or_input: PoolStringArray = [] # 其中一个按下,即为都按下
) -> void:
_host = host
_map_name = map_name
# 添加重置计时器
_release_timer.wait_time = DURATION
_release_timer.one_shot = true
_release_timer.autostart = false
if _release_timer.connect("timeout", self, "release") != OK:
printerr(self, "连接信号时出现错误")
_host.add_child(_release_timer)
# 初始化数据
for key in input_maps:
self._inputted[key] = false
for key in just:
self._just[key] = key
for key in or_input:
self._or_input[key] = key
## 检测
func physics_process() -> void:
for key in _inputted.keys():
# 按下时捕获输入
if _just.has(key):
if Input.is_action_just_pressed(key):
set_inputted_key(key)
# 每帧都捕获输入
else:
if Input.is_action_pressed(key):
set_inputted_key(key)
## 设置已输入的按键
func set_inputted_key(key: String):
if key in _or_input:
for i in _or_input:
if !_inputted[i]:
_inputted[i] = true
_inputted_count += 1
else:
if !_inputted[key]:
_inputted[key] = true
_inputted_count += 1
# 开始倒计时
if _release_timer.is_stopped():
_release_timer.start()
# 如果已按下全部按键,则进行释放
elif is_all_inputted():
_release_timer.stop()
release()
## 是否全部按下
func is_all_inputted() -> bool:
return _inputted_count == _inputted.size()
## 释放掉所有按键记录,重置状态
func release() -> void:
var list = get_inputed()
clear()
# 回调宿主的 callback 方法
_host.callback(
released_keys = list,
released_all = (list.size() == _inputted.size()),
map_name = _map_name,
)
## 获取已按下的键
func get_inputed() -> Array:
var list := []
for key in _inputted.keys():
if _inputted[key]:
list.push_back(key)
return list
## 清除内容
func clear():
_release_timer.stop()
_inputted_count = 0
# 重置按下状态
for key in _inputted.keys():
_inputted[key] = false
示例文件:ComponseInput.rar
运行后,按下小键盘的方向键 + 空格键,查看编辑器底部中的输出内容
以上是关于Godot组合键的实现的主要内容,如果未能解决你的问题,请参考以下文章
delphi 中 实现 ctrl + A~Z 和 Alt + A~Z 组合键的拦截