0
\$\begingroup\$

I'm making a game in SDL2 that so far is basically just a top down shooter, where the player aims at the mouse. When I run the game, you can move properly and shoot properly, and shoot and move the mouse at the same time properly, but you cannot shoot while moving. For example, if I'm using the gatling gun which is fully automatic (as long as I hold the mouse down it keeps on shooting), and I start shooting, then press the w key to move, it stops shooting right away, and doesn't start again until I click again. Here is my code:

void Main::handleInput2(void)
{
double xcomponent,ycomponent,xVel,yVel,angle;
SDL_GetMouseState(&mouseX,&mouseY);
xcomponent = mouseX - (player.getBarrelX() + xOffset);
ycomponent = mouseY - (player.getBarrelY() + yOffset);
angle = atan2(ycomponent,xcomponent);
xVel = cos(angle);
yVel = sin(angle);

if(screen->getEvent()->type == SDL_KEYDOWN)
{
    if(screen->getEvent()->key.keysym.sym == SDLK_a)
    {
        player.setVelX(-1 * player.getSpeed());
    }
    if(screen->getEvent()->key.keysym.sym == SDLK_d)
    {
        player.setVelX(player.getSpeed());
    }
    if(screen->getEvent()->key.keysym.sym == SDLK_w)
    {
        player.setVelY(-1 * player.getSpeed());
    }
    if(screen->getEvent()->key.keysym.sym == SDLK_s)
    {
        player.setVelY(player.getSpeed());
    }
}
if(screen->getEvent()->type == SDL_KEYUP){
    //if(screen->getEvent()->key.keysym.sym = SDLK_8) player.setVelocity(-2,-2); TEST PASSED
    if(screen->getEvent()->key.keysym.sym == SDLK_a)
    {
        player.setVelX(0);
    }
    if(screen->getEvent()->key.keysym.sym == SDLK_d)
    {
        player.setVelX(0);
    }
    if(screen->getEvent()->key.keysym.sym == SDLK_w)
    {
        player.setVelY(0);
    }
    if(screen->getEvent()->key.keysym.sym == SDLK_s)
    {
        player.setVelY(0);
    }
    if(screen->getEvent()->key.keysym.sym == SDLK_1) //Paintball Gun
    {
        player.setWeapon(0);
    }
    if(screen->getEvent()->key.keysym.sym == SDLK_0) //Glock
    {
        player.setWeapon(1);
    }
    if(screen->getEvent()->key.keysym.sym == SDLK_2) //Skorpion
    {
        player.setWeapon(2);
    }
    if(screen->getEvent()->key.keysym.sym == SDLK_3) //Ballistic Knife
    {
        player.setWeapon(5);
    }
    if(screen->getEvent()->key.keysym.sym == SDLK_4) //Spas 12
    {
        player.setWeapon(4);
    }
    if(screen->getEvent()->key.keysym.sym == SDLK_5)
    {
        player.setWeapon(3);
    }
}
if(screen->getEvent()->type == SDL_MOUSEBUTTONDOWN || screen->getEvent()->type == SDL_MOUSEMOTION&SDL_MOUSEBUTTONDOWN)
{
    if(screen->getEvent()->button.button == 1)
    {
        player.Shoot(1,xVel,yVel,screen);
    }
    if(screen->getEvent()->button.button == 3)
    {
        player.Shoot(3,xVel,yVel,screen);
    }
}
}

This was originally all in switch statements, but I thought it might work in if statements. I also tried handling SDL_KEYDOWN and SDL_MOUSEDOWN the same way as I did with SDL_MOUSEDOWN and SDL_MOUSEMOTION. I tried stuff like

if(screen->getEvent()->type == SDL_KEYDOWN|SDL_MOUSEDOWN)
{
    ...
}

if(screen->getEvent()->type == SDL_MOUSEDOWN|SDL_KEYDOWN)
{
    ...
}

if(screen->getEvent()->type == SDL_MOUSEDOWN&SDL_KEYDOWN)
{
    ...
}

if(screen->getEvent()->type == SDL_KEYDOWN&SDL_MOUSEDOWN)
{
    ...
}

But none of those helped, each one in fact made it worse. Seeing as that SDL is meant for making games, I would imagine there must be a way around this. Does anyone know how?

\$\endgroup\$
3
\$\begingroup\$

SDL events are events. They are fired in response to the user doing something, not fired continuously. The mouse down event is only called when the button is first pressed. The key down events are only called when a key is pressed down. They keydown events may get repeatedly called if you have key repeat enabled (which exists to easily simulate the behavior you get in most text-oriented input interfaces). This will never happen with the mouse down event, however.

In particular, this kind of thing can never ever happen:

screen->getEvent()->type == SDL_MOUSEDOWN&SDL_KEYDOWN

Each event is only one kind of event. Either it's a key down event or it's a mouse down event. It cannot be both. If the player does both in the same frame then you will get two separate events.

You need to query the state of the input devices rather than rely on events or use the events to manage your own state data. A key being pushed down has nothing to do with whether the mouse was pressed, released, or held, and vice versa. Likewise there is no event for "still being held down."

You can set some flag to true when you get a key/mouse down event and then set it to false when you get the appropriate key/mouse up event. Use the event handling only for managing these flags. Then in a separate piece of code set movement and firing based on the state of those flags. Or you can use the state in SDL using things like SDL_GetKeyboardState or SDL_GetMouseState.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.