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

如何在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;
    }
}

关键改动说明

  1. 把SDL_PollEvent改成while循环,确保处理完所有待处理事件,避免事件堆积
  2. 将移动逻辑完全移出事件处理块,放在函数末尾,这样每一帧都会执行移动检测,不再依赖事件触发
  3. 事件循环只处理窗口退出等必须通过事件处理的逻辑,输入状态通过SDL_GetKeyboardState()实时获取

这样修改后,按住按键时,每一帧都会检测到按键处于按下状态,玩家会持续流畅移动,不会出现停顿。

内容的提问来源于stack exchange,提问作者Slykapar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 00:55:19