C ++ / SDL keyboard inputs

0

I have a question regarding the handling of events in SDL. I still do not know exactly how the SDL event pool works and I am having problems with the code that I will show next. Basically I'm trying to make the character move and can shoot at the same time. But if I move the character can not shoot and vice versa. I understand that you can not have two inputs at the same time or something, again I do not have it completely clear.

Here the code:

void Player::HandleEvents() {
    SDL_Event event;
    while (SDL_PollEvent(&event)) {
        switch (event.type) {
        case SDL_KEYDOWN:
            //Changes sense of vector when pressed
            if (event.key.keysym.sym == SDLK_w) {
                speedSenseY = -1; 
            } 
            if (event.key.keysym.sym == SDLK_s) {
                speedSenseY = 1; 
            } 
            if (event.key.keysym.sym == SDLK_a) {
                speedSenseX = -1; 
            } 
            if (event.key.keysym.sym == SDLK_d) {
                speedSenseX = 1;
            } 
            //Shooting
            if (event.key.keysym.sym == SDLK_UP ) {
                if (!shooting) {
                    shooting = true;
                    //speed = 0;
                    Bullet* bullet = new Bullet();
                    bullet->speedSenseY = -1;
                    bullet->bulletRect.x = playerRect.x + (frameW / 2);
                    bullet->bulletRect.y = playerRect.y + (frameH / 2);
                    spawnedBullets.push_back(bullet);
                }

            }
            if (event.key.keysym.sym == SDLK_DOWN) {
                 if (!shooting) {
                     shooting = true;
                    //speed = 0;
                     Bullet* bullet = new Bullet();
                     bullet->speedSenseY = 1;
                     bullet->bulletRect.x = playerRect.x + (frameW / 2);
                     bullet->bulletRect.y = playerRect.y + (frameH / 2);
                     spawnedBullets.push_back(bullet);
                 }

            }
            if (event.key.keysym.sym == SDLK_LEFT) {
                 if (!shooting) {
                     shooting = true;
                     //speed = 0;
                     Bullet* bullet = new Bullet();
                     bullet->speedSenseX = -1;
                     bullet->bulletRect.x = playerRect.x + (frameW / 2);
                     bullet->bulletRect.y = playerRect.y + (frameH / 2);
                     spawnedBullets.push_back(bullet);
                 }
            }
            if (event.key.keysym.sym == SDLK_RIGHT) {
                 if (!shooting) {
                     shooting = true;
                     //speed = 0;
                     Bullet* bullet = new Bullet();
                     bullet->speedSenseX = 1;
                     bullet->bulletRect.x = playerRect.x + (frameW / 2);
                     bullet->bulletRect.y = playerRect.y + (frameH / 2);
                     spawnedBullets.push_back(bullet);
                 }
            }
        break;

        case SDL_KEYUP:
            //Sets speed to 0 when not pressed
            if (event.key.keysym.sym == SDLK_w && speedSenseY  0) {
                speedSenseY = 0; 
            } 
            if (event.key.keysym.sym == SDLK_a && speedSenseX  0) {
                speedSenseX = 0; 
            }
            if (event.key.keysym.sym == SDLK_UP) {
                shooting = false;
            }
            if (event.key.keysym.sym == SDLK_DOWN) {
                shooting = false;
            }
            if (event.key.keysym.sym == SDLK_LEFT) {
                shooting = false;
            }
            if (event.key.keysym.sym == SDLK_RIGHT) {
                shooting = false;
            }
        break;
        }
    }   
}
    
asked by Artur Díez 25.06.2018 в 16:07
source

1 answer

0

The SDL event pool is nothing more than a list of the events that occurred in a particular Frame in your application, for example if in Frame X you move your mouse the SDL_MOUSEMOTION event is added to the event list and if for example in the same frame you press 2 keys, two events of the SDL_KEYDOWN type will be added with the corresponding information of the keys inside the event (event.key.keysym.sym), with that unless other events have happened during the Same frame (window, joystick, etc.) while (SDL_PollEvent(&event)) will only be executed 3 times and in each iteration event.type will be of type SDL_MOUSEMOTION, SDK_KEYDOWN and SDK_KEYDOWN (not necessarily in that order). With which we come to the conclusion that if you can have several inputs at the same time.

On the other hand, keep in mind that SDK_KEYDOWN and SDL_KEYUP are events that are triggered only once. For example if you in Frame 10 press the 'x' key the corresponding event (SDL_KEYDOWN) will be added to the event pool, however if you keep pressing the key in Frame 11 the event will no longer be added to the pool until release the key and press it again. To make your logic run always while you keep pressing X key you can do 2 things.

1.- Call function SDL_EnableKeyRepeat which will cause the SDK_KEYDOWN event to be added to the list of events whenever the key is pressed.

2.- Use the SDL_GetKeyState function which returns an array with the status of all the keys

Both cases would simplify the code since you would not have to check if you already pressed X key to stop moving or shoot with what your code would stay more or less like this:

Using SDL_GetKeyState

//Get keys state
Uint8 *keystates = SDL_GetKeyState( NULL ); 

//Reset speed
speedSenseX = speedSenseY = 0;

if (keystates[SDLK_w]) {
  speedSenseY = -1;
}
else if(keystates[SDLK_s) {
  speedSenseY = 1;
}

if (keystates[SDLK_a]) {
  speedSenseX = -1;
}
else if(keystates[SDLK_d]) {
  speedSenseX = 1;
}

shooting = keystates[SDLK_UP] || keystates[SDLK_DOWN] || keystates[SDLK_LEFT] || keystates[SDLK_RIGHT];

if (shooting) {
  Bullet* bullet = new Bullet();

  if (keystates[SDLK_UP]) {
    bullet->speedSenseY = -1;
  }
  else if(keystates[SDLK_DOWN) {
    bullet->speedSenseY = 1;
  }
  else if (keystates[SDLK_LEFT]) {
    bullet->speedSenseX = -1;
  }
  else if(keystates[SDLK_RIGHT]) {
    bullet->speedSenseX = 1;
  }

  bullet->bulletRect.x = playerRect.x + (frameW / 2);
  bullet->bulletRect.y = playerRect.y + (frameH / 2);
  spawnedBullets.push_back(bullet);
}
    
answered by 04.07.2018 / 06:10
source