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;
}
You have a few problems:
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:;
}
}
}
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.
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.