Trouble Reading Keyboard Input!

Hello!

I’m having a lot of trouble getting my keyboard input to work the way I want it to. I’m using SDL-1.12.13 and C. Here’s my function for polling the input:

int pressed ()
{
    SDL_Event event;
    while(SDL_PollEvent(&event))
    {
        switch(event.type)
        {
            case SDL_KEYDOWN:
                switch(event.key.keysym.sym)
                {
                    case SDLK_LEFT:
                        kleft = 1;
                        break;
                    case SDLK_RIGHT:
                        kright = 1;
                        break;
                    case SDLK_UP:
                        kup = 1;
                        break;
                    case SDLK_DOWN:
                        kdown = 1;
                        break;
                    default:
                        break;
                }
                break;
            case SDL_KEYUP:
                switch(event.key.keysym.sym)
                {
                    case SDLK_LEFT:
                        kleft = 0;
                        break;
                    case SDLK_RIGHT:
                        kright = 0;
                        break;
                    case SDLK_UP:
                        kup = 0;
                        break;
                    case SDLK_DOWN:
                        kdown = 0;
                        break;
                    default:
                        break;
                }
                break;
        }
    }
}

Essentially, in my map loop, it calls this function, then increases the character’s X and Y coordinates accordingly based on which variables are equal to 1. My problem is that SDL_KEYUP seems to be triggering on its own! I have to constantly tap the direction keys to continue moving. When I comment the SDL_KEYUP section out, the character will glide across the screen, as expected.

Any ideas what I’m doing wrong? Thanks for taking a look :slight_smile:

Hi, try using http://sdl.beuc.net/sdl.wiki/SDL_EnableKeyRepeat before your map loop to enable key repeat. If it’s too fast change the delay- and interval-parameters.

Kind regards
Glocke

Thanks for the response!

I tried using SDL_EnableKeyRepeat before the map loop, but it doesn’t seem to do anything. Essentially I placed SDL_EnableKeyRepeat(10,10); right before the loop, but it makes no indication of repeating the key. Am I calling the function in the wrong place or something?

Can you post some code? A runnable example of your approach might help to find the problem :slight_smile:

Here’s the essential code to compile. You’ll need a bitmap called ‘‘character.bmp’’ in the project to compile.
Here’s one: http://bottler0cket.webs.com/character.bmp

Thanks for taking a look :slight_smile:

#include <SDL.h>

char *imagename [17];
int drawx = 0;
int drawy = 0;
int kup = 0;
int kdown = 0;
int kright = 0;
int kleft = 0;
int playerx = 128;
int playery = 128;
int playerxl = 32;
int playeryl = 32;

int draw (drawx, drawy, imagename);
int pressed ();

int main ( int argc, char** argv )
{
    atexit(SDL_Quit);
    SDL_Surface* screen = SDL_SetVideoMode(640, 480, 16,
                                            SDL_HWSURFACE|SDL_DOUBLEBUF);
    draw(playerx, playery, "character.bmp");

    SDL_EnableKeyRepeat(10,10);

    //Map Loop
    
    int done = 0;
    while (done == 0)
    {
        SDL_ShowCursor(SDL_DISABLE);
        pressed();
        if (kup == 1)
        {
            playery += -2;
        }
        if (kdown == 1)
        {
            playery += 2;
        }

        if (kright == 1)
        {
            playerx += 2;
        }
        if (kleft == 1)
        {
            playerx += - 2;
        }

        if (playery > 0)
        if (playery < 480)
        if (playerx > 0)
        if (playerx < 640)
        {
            if (playerxl != playerx)
            {
                playerxl = playerx;
                draw (playerx, playery, "character.bmp");
            }
            if (playeryl != playery)
            {
                playeryl = playery;
                draw (playerx, playery, "character.bmp");
            }
        }

        if (playerx < 1)
            playerx = 1;
        if (playerx > 600)
            playerx = 600;
        if (playery < 1)
            playery = 1;
        if (playery > 440)
            playery = 440;
    }
    return 0;
}

int draw (drawx, drawy, imagename)
{

    SDL_Surface* screen = SDL_SetVideoMode(640, 480, 16,
                                        SDL_HWSURFACE|SDL_DOUBLEBUF);

    SDL_Rect dstrect;
    dstrect.x = (drawx);
    dstrect.y = (drawy);
    SDL_Surface* bmp = SDL_LoadBMP(("%d", imagename));
    SDL_BlitSurface(bmp, 0, screen, &dstrect);
    SDL_Flip(screen);
    SDL_FreeSurface(bmp);

    return 0;
}

int pressed ()
{
    SDL_Event event;
    while(SDL_PollEvent(&event))
    {
        switch(event.type)
        {
            case SDL_KEYDOWN:
                switch(event.key.keysym.sym)
                {
                    case SDLK_LEFT:
                        kleft = 1;
                        break;
                    case SDLK_RIGHT:
                        kright = 1;
                        break;
                    case SDLK_UP:
                        kup = 1;
                        break;
                    case SDLK_DOWN:
                        kdown = 1;
                        break;
                    default:
                        break;
                }
                break;
            case SDL_KEYUP:
                switch(event.key.keysym.sym)
                {
                    case SDLK_LEFT:
                        kleft = 0;
                        break;
                    case SDLK_RIGHT:
                        kright = 0;
                        break;
                    case SDLK_UP:
                        kup = 0;
                        break;
                    case SDLK_DOWN:
                        kdown = 0;
                        break;
                    default:
                        break;
                }
                break;
        }
    }
}

Hi,

here is your fixed code (comments below):

#include <SDL/SDL.h> 

char *imagename [17]; 
int drawx = 0; 
int drawy = 0; 
int kup = 0; 
int kdown = 0; 
int kright = 0; 
int kleft = 0; 
int playerx = 128; 
int playery = 128; 
int playerxl = 32; 
int playeryl = 32; 

int pressed (); 

int main ( int argc, char** argv ) 
{ 
    // @note: remember to initialize SDL
    //        (I wonder why it already works without O_o)
    SDL_Init(SDL_INIT_VIDEO);

    atexit(SDL_Quit); 
    SDL_Surface* screen = SDL_SetVideoMode(640, 480, 16, 
                                           SDL_HWSURFACE|SDL_DOUBLEBUF); 
    // @note: load the player sprite ONCE ;)
    SDL_Surface* player = SDL_LoadBMP("character.bmp"); 

    SDL_EnableKeyRepeat(10,10); 

    // @note: you just need that once :)
    SDL_ShowCursor(SDL_DISABLE); 
    
    int done = 0; 
    while (done == 0) 
    { 
        // @note: remember to clear the screen on each loop
        SDL_FillRect(screen, NULL, 0x000000); 
        // @note: to shutdown when window was close-clicked
        if (pressed() == -1) {
            done = 1;
            break;
        } 
        if (kup == 1) 
        { 
            playery += -2; 
        } 
        if (kdown == 1) 
        { 
            playery += 2; 
        } 

        if (kright == 1) 
        { 
            playerx += 2; 
        } 
        if (kleft == 1) 
        { 
            playerx += - 2; 
        }

        /*
        if (playery > 0) 
        if (playery < 480) 
        if (playerx > 0) 
        if (playerx < 640) 
        { 
            if (playerxl != playerx) 
            { 
                playerxl = playerx; 
                draw (playerx, playery, "character.bmp"); 
            } 
            if (playeryl != playery) 
            { 
                playeryl = playery; 
                draw (playerx, playery, "character.bmp"); 
            } 
        }*/
        // @note: you should draw on each loop, even the player did not move
        SDL_Rect dstrect; 
        dstrect.x = playerx; 
        dstrect.y = playery; 
        SDL_BlitSurface(player, NULL, screen, &dstrect);
        
        SDL_Flip(screen); 

        if (playerx < 1) 
            playerx = 1; 
        if (playerx > 600) 
            playerx = 600; 
        if (playery < 1) 
            playery = 1; 
        if (playery > 440) 
            playery = 440; 
    } 
    
    // @note: you player can be free'd at the end
    SDL_FreeSurface(player); 
    // @note: don't forget to shutdown SDL (not needed here but good style)
    SDL_Quit();
    
    return 0; 
} 


int pressed () 
{ 
    SDL_Event event; 
    while(SDL_PollEvent(&event)) 
    { 
        switch(event.type) 
        { 
            // @note: to shutdown when window was close-clicked
            case SDL_QUIT:
                return -1;
            case SDL_KEYDOWN: 
                switch(event.key.keysym.sym) 
                { 
                    case SDLK_LEFT: 
                        kleft = 1; 
                        break; 
                    case SDLK_RIGHT: 
                        kright = 1; 
                        break; 
                    case SDLK_UP: 
                        kup = 1; 
                        break; 
                    case SDLK_DOWN: 
                        kdown = 1; 
                        break; 
                    default: 
                        break; 
                } 
                break; 
            case SDL_KEYUP: 
                switch(event.key.keysym.sym) 
                { 
                    case SDLK_LEFT: 
                        kleft = 0; 
                        break; 
                    case SDLK_RIGHT: 
                        kright = 0; 
                        break; 
                    case SDLK_UP: 
                        kup = 0; 
                        break; 
                    case SDLK_DOWN: 
                        kdown = 0; 
                        break; 
                    default: 
                        break; 
                } 
                break; 
        } 
    } 
}

Here are some comments on the code and your problem (they are also in the code at the line with “// @note: […]”:

  • You should initialize SDL before using SDL-functions. But I wonder why it already works without O_o

  • In larger programs, loading the image over and over will slowdown performance. A better solution is to load the image in the first place.

  • You don’t need to disable the cursor on each loop.

  • The basic game-loop is: Clear Screen; Handle Logic; Render Stuff; Flip Screen; Limit FPS

  • I added handling SDL_Quit to stop the mainloop on a window close.

  • As I said: draw on each loop, even the player did not move. Else (if you move another window over your window and move the other one off again) there will be black boxes on your game window until the window is redrawn.

  • At the end you can free your player’s image’s surface :slight_smile:

  • And you should shutdown SDL. It is not needed here, because the program will terminate and free all stuff; but it’s good style to do SDL_Quit().

I don’t know what your problem was exactly but not it seems to work. The problem might came from the
if (playery > 0)
if (playery < 480)
if (playerx > 0)
if (playerx < 640)
{
if (playerxl != playerx)
{
playerxl = playerx;
draw (playerx, playery, “character.bmp”);
}
if (playeryl != playery)
{
playeryl = playery;
draw (playerx, playery, “character.bmp”);
}

part. Actual you do not need the last player position in this case.

Well… the list (see above) looks quite long and strict… but it’s cool. These are mostly some performance- or style-tips. I hope the code is already easy-to read for you :slight_smile:

Kind regards
Glocke

Thank you so much :slight_smile: I have been stuck on this for a while!

Thanks a lot for all the advice too. I’m still in the process of learning a lot, so this really speeds things up and avoids some major problems later on!