在SDL中同时处理多个keypressess

时间:2014-10-29 14:58:20

标签: 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;
        }
    }
}

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:3)

您还可以使用SDL_GetKeyboardState对密钥的当前状态进行采样,而无需亲自处理密钥事件。