如何在SDL中实现持续用户输入?C语言游戏输入延迟问题
解决SDL中按住按键移动的停顿问题
问题出在你的移动逻辑被嵌套在SDL_PollEvent的判断分支里——只有当有事件产生时才会执行移动。而系统默认的按键重复机制存在延迟,按住按键时,只有第一个SDL_KEYDOWN事件会立即触发,后续的重复事件要等系统延迟后才会持续发送,这就导致了先移动一步、停顿后才流畅移动的现象。
修正方案
把移动逻辑从SDL_PollEvent的条件块中移出,让它在每一帧都执行。SDL_GetKeyboardState()获取的是当前键盘的实时状态,不需要依赖事件触发,只要按键按住,每一帧检测到状态为按下,就执行移动。
修正后的代码
首先保留你原本的结构体定义:
typedef struct { SDL_Rect rect; bool alive, large; float speed; } Player; typedef struct { bool running; int width, height; SDL_Event event; Uint8* keystates; Player* player; } Game;
修改后的update函数:
void update(Game* game) { // 实时获取键盘状态 game->keystates = SDL_GetKeyboardState(NULL); // 设置玩家速度 game->player->speed = STD_PLAYERSPEED * (game->player->large ? 2 : 1); // 处理所有事件(仅处理退出等非输入事件) while (SDL_PollEvent(&game->event) > 0) { switch(game->event.type) { case SDL_QUIT: game->running = false; break; // 这里可以添加其他需要处理的事件,比如按键松开的逻辑(如果需要) } } // 移动逻辑:每一帧都执行,只要按键按住就移动 if(game->keystates[SDL_SCANCODE_W]) { game->player->rect.y -= game->player->speed; } if(game->keystates[SDL_SCANCODE_S]) { game->player->rect.y += game->player->speed; } if(game->keystates[SDL_SCANCODE_A]) { game->player->rect.x -= game->player->speed; } if(game->keystates[SDL_SCANCODE_D]) { game->player->rect.x += game->player->speed; } }
关键改动说明
- 把
SDL_PollEvent改成while循环,确保处理完所有待处理事件,避免事件堆积 - 将移动逻辑完全移出事件处理块,放在函数末尾,这样每一帧都会执行移动检测,不再依赖事件触发
- 事件循环只处理窗口退出等必须通过事件处理的逻辑,输入状态通过
SDL_GetKeyboardState()实时获取
这样修改后,按住按键时,每一帧都会检测到按键处于按下状态,玩家会持续流畅移动,不会出现停顿。
内容的提问来源于stack exchange,提问作者Slykapar
相关产品推荐
相关产品推荐

