c++sdlkeyevent

SDL arrow key events malfunctioning


I am having a very strange problem with SDL and specifically with key presses. I have made a simply program that should display a different message on the screen depending on which arrow key is pressed, however it only displays the messages if I hit the arrow keys several times in succession. Here is my code:

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "SDL/SDL_ttf.h"
#include <iostream>
#include <string>

bool quit = false;

SDL_Event arrows;
SDL_Event xOut;

SDL_Surface *titleText;
SDL_Surface *keyText;
SDL_Surface *screen = NULL;
SDL_Surface *backgroundOPT = NULL;

const int screenW = 640;
const int screenH = 480;
const int screenBPP = 32;

SDL_Surface *loadIMG(std::string filename)
{
    SDL_Surface *img = IMG_Load(filename.c_str());

    SDL_Surface *imgOPT = SDL_DisplayFormat(img);

    SDL_FreeSurface(img);

    return imgOPT;
}

void blitIMG(int pX, int pY, SDL_Surface *window, SDL_Surface *image, int cpX, int cpY, int cpH, int cpW)
{
    SDL_Rect positionIMG;
    positionIMG.x = pX;
    positionIMG.y = pY;

    SDL_Rect clipP;
    clipP.x = cpX;
    clipP.y = cpY;
    clipP.h = cpH;
    clipP.w = cpW;

    SDL_BlitSurface(image, &clipP, window, &positionIMG);

    SDL_Flip(window);
}

SDL_Surface *loadText(int red, int blue, int green, std::string fontname, int fontSize, std::string text)
{
    int color1 = red;
    int color2 = blue;
    int color3 = green;

    SDL_Color textColor = {color1, color2, color3};

    TTF_Font *font1 = TTF_OpenFont(fontname.c_str(), fontSize);

    SDL_Surface *message1 = TTF_RenderText_Solid(font1, text.c_str(), textColor);

    return message1;
}

int main(int argc, char* args[])
{
    TTF_Init();
    SDL_Init(SDL_INIT_EVERYTHING);
    screen = SDL_SetVideoMode(screenW, screenH, screenBPP, SDL_SWSURFACE);

    while(quit == false)
    {
        SDL_PollEvent(&arrows);

        if(arrows.type == SDL_KEYDOWN)
        {
            switch(arrows.key.keysym.sym)
            {

                case SDLK_UP: keyText = loadText(255, 200, 50, "lazy.ttf", 50, "Up was pressed");
                break;
                case SDLK_DOWN: keyText = loadText(255, 200, 50, "lazy.ttf", 50, "Down was pressed");
                break;
                case SDLK_LEFT: keyText = loadText(255, 200, 50, "lazy.ttf", 50, "Left was pressed");
                break;
                case SDLK_RIGHT: keyText = loadText(255, 200, 50, "lazy.ttf", 50, "Right was pressed");
                break;
                default:;
            }
        }

        blitIMG(0, 0, screen, backgroundOPT = loadIMG("hellsing.png"), 0, 0, 1000, 1000);
        blitIMG(25, 20, screen, titleText = loadText(255, 200, 50, "lazy.ttf", 50, "Die, Freaks!"), 0, 0, 640, 480);
        blitIMG(100, 300, screen, keyText, 0, 0, 640, 480);

        SDL_PollEvent(&xOut);

        if(xOut.type == SDL_QUIT)
        {
            quit = true;
        }

    }

    SDL_FreeSurface(backgroundOPT);
    SDL_FreeSurface(titleText);
    SDL_FreeSurface(keyText);

    SDL_Quit();

    return 0;
}

Solution

  • You have a few problems:

    1. SDL_PollEvent should be in a while loop, that inside contains the event handling stuff. Something like this:

      while(SDL_PollEvent(&event)){
      
          if(event.type == SDL_KEYDOWN)
          {
              switch(event.key.keysym.sym)
              {
      
                  case SDLK_UP: keyText = loadText(255, 200, 50, "lazy.ttf", 50, "Up was pressed");
                  break;
                  case SDLK_DOWN: keyText = loadText(255, 200, 50, "lazy.ttf", 50, "Down was pressed");
                  break;
                  case SDLK_LEFT: keyText = loadText(255, 200, 50, "lazy.ttf", 50, "Left was pressed");
                  break;
                  case SDLK_RIGHT: keyText = loadText(255, 200, 50, "lazy.ttf", 50, "Right was pressed");
                  break;
                  default:;
              }
          }
      }
      
    2. You don't need 2 SDL_Events, one is enought, but I don't think it is a problem if you have two, it would be just less organized and possibly slower. You would just put:

      if(xOut.type == SDL_QUIT)
      {
          quit = true;
      }
      

      inside the previous loop i showed you.

    3. You should not have SLD_Flip(window) in your drawing function. Instead, you should have it in the end of the main loop, after you have drawn everything.