You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Godot钢琴游戏Shift+按键无法触发黑键问题求助

解决Godot虚拟钢琴Shift+白键触发黑键的问题

你的核心问题在于白键和黑键的触发逻辑完全分离:白键判断里加了!Input.is_key_pressed(KEY_SHIFT)导致Shift按住时白键失效,但黑键又没关联到Shift+白键的组合上;之前手动拼接黑键名出现重复#,是因为字符串拼接容易出错,直接用映射字典更稳妥。

具体修改方案

  1. 建立白键到黑键的映射表:直接定义每个白键对应的黑键,彻底避免拼接错误
  2. 合并触发逻辑:检测白键按下时,根据Shift状态决定触发白键还是对应黑键
  3. 优化按键状态管理:确保白/黑键的按压状态都能正确重置

修改后的完整代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 04:57:09