Godot钢琴游戏Shift+按键无法触发黑键问题求助
解决Godot虚拟钢琴Shift+白键触发黑键的问题
你的核心问题在于白键和黑键的触发逻辑完全分离:白键判断里加了!Input.is_key_pressed(KEY_SHIFT)导致Shift按住时白键失效,但黑键又没关联到Shift+白键的组合上;之前手动拼接黑键名出现重复#,是因为字符串拼接容易出错,直接用映射字典更稳妥。
具体修改方案
- 建立白键到黑键的映射表:直接定义每个白键对应的黑键,彻底避免拼接错误
- 合并触发逻辑:检测白键按下时,根据Shift状态决定触发白键还是对应黑键
- 优化按键状态管理:确保白/黑键的按压状态都能正确重置
修改后的完整代码
extends Node # 左右手按键映射 var left_hand = ['Z', 'S', 'X', 'D', 'C', 'V', 'G', 'B', 'H', 'N', 'J', 'M'] var right_hand = ['R', '5', 'T', '6', 'Y', 'U', '8', 'I', '9', 'O', '0', 'P'] # 白键列表 var white_notes = ['C2', 'D2', 'E2', 'F2', 'G2', 'A2', 'B2', 'C3', 'D3', 'E3', 'F3', 'G3', 'A3', 'B3', 'C4', 'D4', 'E4', 'F4', 'G4', 'A4', 'B4', 'C5', 'D5', 'E5', 'F5', 'G5', 'A5', 'B5', 'C6', 'D6', 'E6', 'F6', 'G6', 'A6', 'B6', 'C7'] # 白键对应黑键的映射表(无对应黑键的白键无需添加) var white_to_black = { 'C2': 'C#2', 'D2': 'D#2', 'F2': 'F#2', 'G2': 'G#2', 'A2': 'A#2', 'C3': 'C#3', 'D3': 'D#3', 'F3': 'F#3', 'G3': 'G#3', 'A3': 'A#3', 'C4': 'C#4', 'D4': 'D#4', 'F4': 'F#4', 'G4': 'G#4', 'A4': 'A#4', 'C5': 'C#5', 'D5': 'D#5', 'F5': 'F#5', 'G5': 'G#5', 'A5': 'A#5', 'C6': 'C#6', 'D6': 'D#6', 'F6': 'F#6', 'G6': 'G#6', 'A6': 'A#6', 'C7': 'C#7' } # 所有音符(白+黑) var all_notes = white_notes + list(white_to_black.values()) # 按键状态追踪字典 var key_pressed = {} func _ready(): # 初始化所有音符的按压状态 for note in all_notes: key_pressed[note] = false set_process_input(true) func _process(delta): for white_note in white_notes: var action = "play_note_" + white_note var is_key_down = Input.is_action_pressed(action) var shift_held = Input.is_key_pressed(KEY_SHIFT) # 确定目标音符:Shift按住且有对应黑键则触发黑键,否则触发白键 var target_note = white_note if shift_held and white_to_black.has(white_note): target_note = white_to_black[white_note] # 触发音符并更新状态(避免重复触发) if is_key_down and !key_pressed[target_note]: play_note(target_note) key_pressed[target_note] = true elif !is_key_down and key_pressed[target_note]: key_pressed[target_note] = false func play_note(note): var audio_stream = load("res://notes/" + note + ".wav") if audio_stream: var audio_player = AudioStreamPlayer.new() audio_player.stream = audio_stream add_child(audio_player) audio_player.play() # 播放完毕后自动销毁节点,避免内存堆积 audio_player.connect("finished", audio_player, "queue_free")
关键修改说明
- 映射表
white_to_black:直接关联白键与黑键,彻底解决手动拼接导致的重复#问题,逻辑更直观 - 合并触发逻辑:不再分开遍历白键和黑键,而是通过Shift状态动态切换目标音符,实现Shift+白键触发黑键的需求
- 自动销毁音频节点:添加
queue_free逻辑,避免大量播放后节点占用内存 - 状态管理优化:统一用
target_note追踪按压状态,确保白键和黑键的状态更新准确
内容的提问来源于stack exchange,提问作者JuanPlayz
相关产品推荐
相关产品推荐

