如何在SDL2中无需常量实现可变数量按键的输入检测?
SDL2 可变按键绑定的输入检测方案
你的原代码存在两个核心问题:
- Switch 语句中不能嵌套for循环,且
case分支必须是编译期常量,无法用运行时动态变化的currentbinds[i]作为分支条件 - 混淆了事件类型(
e.type)和按键值:currentbinds存储的是按键绑定(比如SDL_SCANCODE_W这类键值),但你把它当成了事件类型(比如SDL_KEYDOWN)来匹配,逻辑完全错误
下面是两种可行的替代实现方式:
方式一:基于事件循环遍历匹配
直接在事件循环中判断按键事件,再遍历currentbinds检查匹配:
SDL_Event e; while (SDL_PollEvent(&e) != 0) { // 处理退出事件 if (e.type == SDL_QUIT) { iskillready = true; continue; } // 处理按键按下事件 if (e.type == SDL_KEYDOWN) { // 假设currentbinds存储的是SDL_Scancode类型,若存的是SDL_Keycode则用e.key.keysym.sym SDL_Scancode pressed_key = e.key.keysym.scancode; for (SDL_Scancode bind : currentbinds) { if (bind == pressed_key) { // 将按键转换为字符添加,或者直接存键值(根据你的需求调整) // 示例:如果是字母键,转换为对应的ASCII字符 keyspressed += SDL_GetKeyName(SDL_GetKeyFromScancode(bind)); break; // 匹配到就退出循环,避免重复添加 } } } }
方式二:基于键盘状态数组(适合实时检测)
如果需要实时检测按键状态(而非仅响应按下事件),可以用SDL_GetKeyboardState直接获取当前所有按下的按键,再匹配绑定:
// 获取当前键盘状态数组 const Uint8* keystates = SDL_GetKeyboardState(NULL); // 遍历绑定的按键,检查是否按下 for (SDL_Scancode bind : currentbinds) { if (keystates[bind]) { // 这里注意:如果按住按键会持续触发,若要仅记录一次按下,需要额外维护已按下的键集合 keyspressed += SDL_GetKeyName(SDL_GetKeyFromScancode(bind)); } } // 别忘了单独处理退出事件 SDL_Event e; while (SDL_PollEvent(&e) != 0) { if (e.type == SDL_QUIT) { iskillready = true; } }
注意事项
- 确认
currentbinds存储的类型:是SDL_Scancode(硬件按键码,不受输入法影响)还是SDL_Keycode(字符码,受输入法/键盘布局影响),代码中要对应调整 - 如果需要避免重复添加同一按键(比如按住时只记录一次),可以维护一个
std::unordered_set来记录已按下的键,每次匹配前先检查是否已存在
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

