c++ - 在 SDL 中同时处理多个按键

标签 c++ sdl sdl-2

我正在制作一个简单的自上而下的 2D 射击游戏,您可以在其中使用 WASD 移动并使用空间向您注视的方向射击。我可以移动和射击,但我不能同时进行。例如,如果我正在射击并开始移动,我的角色将停止射击,直到我松开并再次按下空格键,如果我随后开始朝另一个方向移动,我必须松开并再次按下空格键。

这是我的主要方法:

int main(int argc, char* args[])
{
    if (!init())
    {
        log("Failed to initialize!\n");
    }
    else
    {
        log("Initialized SDL and SDL subsystems. \nLoading assets:\n");

        if (!loadAssets())
        {
            printf("Failed to load assets!\n");
        }
        else
        {
            log("All assets loaded successfully.\n");

            bool running = true;
            SDL_Event e;
            std::vector<Shot> shots;

            LTimer shotTimer;
            float cooldown = 250.0f;
            float previousCooldown = 0.0f;

            Player player;

            log("Game running.\n");
            shotTimer.start();
            while (running)
            {
                while (SDL_PollEvent(&e) != 0)
                {
                    if (e.type == SDL_QUIT)
                    {
                        log("SDL_QUIT event triggered.\n");
                        running = false;
                    }
                    else if (e.type == SDL_KEYDOWN)
                    {
                        switch (e.key.keysym.sym)
                        {
                            case SDLK_ESCAPE:
                            {
                                running = false;
                                break;
                            }
                        }
                    }

                    player.handleEvent(e);

                    if (SDL_GetTicks() - previousCooldown > cooldown)
                    {
                        previousCooldown = SDL_GetTicks();

                        shots = shoot(e, player, shots);
                    }
                }

                player.move();
                for (int i = 0; i < shots.size(); i++)
                {
                    shots[i].move();
                }

                /*if (shotTimer.getTicks() >= cooldown)
                    shotTimer.restart();*/

                SDL_SetRenderDrawColor(renderer, 0xff, 0xff, 0xff, 0xff);
                SDL_RenderClear(renderer);

                background.render(0, 0);
                for (int i = 0; i < shots.size(); i++)
                {
                    shots[i].render();
                }
                player.render();

                SDL_RenderPresent(renderer);
            }
        }
    }

    close();

    return 0;
}

这是我的 shoot() 函数,这可能是造成这种情况的原因:

std::vector<Shot> shoot(SDL_Event& e, Player player, std::vector<Shot> shots)
{
    bool shoot = false;

    if (e.type = SDL_KEYDOWN  && e.key.repeat == 1)
    {
        switch (e.key.keysym.sym)
        {
            case SDLK_SPACE:
            {
                shoot = true;
                break;
            }
        }
    }
    else if (e.type = SDL_KEYUP  && e.key.repeat == 1)
    {
        switch (e.key.keysym.sym)
        {
            case SDLK_SPACE:
            {
                shoot = false;
                break;
            }
        }
    }

    if (shoot)
    {
        Shot newShot(player.getDir(), player);
        shots.push_back(newShot);
    }

    return shots;
}

这就是我移动播放器的方式

void Player::handleEvent(SDL_Event& e)
{
    if (e.type == SDL_KEYDOWN && e.key.repeat == 0)
    {
        switch (e.key.keysym.sym)
        {
            case SDLK_w: mVelY -= PLAYER_VEL; mDir = 0; break;
            case SDLK_s: mVelY += PLAYER_VEL; mDir = 1; break;
            case SDLK_d: mVelX += PLAYER_VEL; mDir = 2; break;
            case SDLK_a: mVelX -= PLAYER_VEL; mDir = 3; break;
        }
    }
    else if (e.type == SDL_KEYUP && e.key.repeat == 0)
    {
        switch (e.key.keysym.sym)
        {
            case SDLK_w: mVelY += PLAYER_VEL; break;
            case SDLK_s: mVelY -= PLAYER_VEL; break;
            case SDLK_d: mVelX -= PLAYER_VEL; break;
            case SDLK_a: mVelX += PLAYER_VEL; break;
        }
    }
}

最佳答案

将您的事件轮询与其余的游戏逻辑分开。

在单独的函数中每帧一次轮询所有事件,并将键状态的状态存储到数组中。然后,当您需要状态时,只需检查数组即可。

关于c++ - 在 SDL 中同时处理多个按键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26633669/

相关文章:

c++ - SDL 交叉 header 渲染

c++ - 如何从 VC++ 中终止进程

c++ - SDLSurface 的 OpenGL 纹理太暗

c++ - VST C++ 嵌套类 - 构造和包含

c++ - SDL_事件e;传递给函数

c++ - 当我开始一个新项目时,Visual Studio 2012 忘记了 SDL 配置?

c++ - 对多个类使用一个 SDL2 渲染器

c++ - 我如何使用中点圆算法去除在 SDL 中绘制的圆中的这些间隙?

c++ - 如何为四叉树批量插入的坐标实现 z 顺序排序 - C++

c++ - 将临时绑定(bind)到 const 引用的特定形式无效