Sign in to follow this  
Lasko

Trouble with SDL keyboard movement

Recommended Posts

Lasko    178
#include <SDL/SDL.h>

// things for the window

const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;
const char* WINDOW_CAPTION = "Pong Clone";


void Paddle1()
{
     SDL_Surface* bitmap=SDL_LoadBMP("Paddle.bmp");
     
     SDL_Rect source; 
     source.x = 0;
     source.y = 1;
     source.w = 25;
     source.h = 100;
     
     
     SDL_Rect dest;
     dest.x = 75;
     dest.y = 100;
     dest.w = 100;
     dest.h = 100;
     
     
     SDL_BlitSurface(bitmap, &source, SDL_GetVideoSurface(), &dest);
     SDL_Flip(SDL_GetVideoSurface());
     
     bool keysheld[323];

     SDL_Event event;
     if(SDL_PollEvent(&event))
     {
          if(event.type==SDL_KEYDOWN)
          {
               keysheld[event.key.keysym.sym] = true;
          }
          if(event.type==SDL_KEYUP)
          {
               keysheld[event.key.keysym.sym] = false;
          }
     }
     if(keysheld[SDLK_UP])
     {
           dest.y -=2;
     }
     if(keysheld[SDLK_DOWN])
     {
          dest.y+=2;
          if(dest.y+dest.h > WINDOW_HEIGHT)
          {
               dest.y=600 - dest.h;
          }
     }
}




void Paddle2()
{
     SDL_Surface* bitmap=SDL_LoadBMP("Paddle.bmp");
     
     SDL_Rect source; 
     source.x = 0;
     source.y = 1;
     source.w = 25;
     source.h = 100;
     
     
     SDL_Rect dest;
     dest.x = 700;
     dest.y = 100;
     dest.w = 100;
     dest.h = 100;
     
     
     
     SDL_BlitSurface(bitmap, &source, SDL_GetVideoSurface(), &dest);
     SDL_Flip(SDL_GetVideoSurface());
}

void Ball()
{
     SDL_Surface* bitmap=SDL_LoadBMP("ball.bmp");
     
     SDL_Rect source; 
     source.x = 0;
     source.y = 1;
     source.w = 40;
     source.h = 40;
     
     
     SDL_Rect dest;
     dest.x=WINDOW_WIDTH/2;
     dest.y=WINDOW_HEIGHT/2;
     dest.w=WINDOW_WIDTH/2;
     dest.h=WINDOW_HEIGHT/2;
     
     
     
     SDL_BlitSurface(bitmap, &source, SDL_GetVideoSurface(), &dest);
     SDL_Flip(SDL_GetVideoSurface());
}

void Game()
{
    
     Paddle1();
     Paddle2();
     Ball();
}

void Shortcut_to_start()
{     
     SDL_Init( SDL_INIT_VIDEO );
     SDL_Surface* screen=SDL_SetVideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, 0, SDL_HWSURFACE | SDL_DOUBLEBUF);
     SDL_WM_SetCaption( WINDOW_CAPTION, 0 );
    
    
    SDL_Event event;
    bool gamerunning = true;
    
    
    while(gamerunning)
    {
       Game();
       
       if(SDL_PollEvent(&event))
       {
          if(event.type == SDL_QUIT)
          {
             gamerunning = false;
          }
          if(event.type == SDL_KEYDOWN)
          {
          SDLKey keypressed = event.key.keysym.sym;
          
          
             switch(keypressed)
             {
                case SDLK_ESCAPE: gamerunning = false;
                break;
             }
          }
       }
    }
    
    
    SDL_Quit();
}
     

int main(int argc, char **argv)
{
    Shortcut_to_start();
    
    return 0;
}
The pictures are still and the only button that will work is Escape, which exits the program. Thanks if you know what I need to fix

Share this post


Link to post
Share on other sites
TDragon    679
Whenever you call SDL_PollEvent, the event gets taken off the event queue. No matter what kind of event it is. So since you call it in two different places (Paddle1() and main()), sometimes main() will pop off the event and sometimes Paddle1() will pop it off. What happens when main pops off the SDLK_UP or SDLK_DOWN keydown events, or when Paddle1() pops off the SDLK_ESCAPE event?

Share this post


Link to post
Share on other sites
Mushu    1396
You really need to unify your event handling. Right now you're getting keypress events scattered between two different polls so you're undoubtedly losing some.

To solve this, you need to make it so you only have one place where you're polling for events. You can buffer the keystates in an array like you're doing, but do it with a global so that all the functions have access to the current keystates:


// global!! :D
bool keys[SDLK_LAST];

// in main game loop
SDL_Event event;

while (SDL_PollEvent(&event)) {
if (event.type = SDL_QUIT) {
gamerunning = false; }

if (event.type == SDL_KEYDOWN) {
keys[event.key.keysym.sym] = true; }

if (event.type == SDL_KEYUP) {
keys[event.key.keysym.sym] = false; }
}

// and then you can take that out of the paddle code, which
// would then becomes just the check to see if the up/down
// keys are currently being held



Hope that helps

EDIT: Beaten :(

Share this post


Link to post
Share on other sites
Lasko    178

#include <SDL/SDL.h>

// things for the window

const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;
const char* WINDOW_CAPTION = "Pong Clone";

// dont know why i need this!
bool keys[SDLK_LAST];


void Paddle1()
{
SDL_Surface* bitmap=SDL_LoadBMP("Paddle.bmp");

SDL_Rect source;
source.x = 0;
source.y = 1;
source.w = 25;
source.h = 100;


SDL_Rect dest;
dest.x = 75;
dest.y = 100;
dest.w = 100;
dest.h = 100;


SDL_BlitSurface(bitmap, &source, SDL_GetVideoSurface(), &dest);
SDL_Flip(SDL_GetVideoSurface());

bool keysheld[323];

if(keysheld[SDLK_UP])
{
dest.y -=2;
}
if(keysheld[SDLK_DOWN])
{
dest.y+=2;
if(dest.y+dest.h > WINDOW_HEIGHT)
{
dest.y=600 - dest.h;
}
}
}




void Paddle2()
{
SDL_Surface* bitmap=SDL_LoadBMP("Paddle.bmp");

SDL_Rect source;
source.x = 0;
source.y = 1;
source.w = 25;
source.h = 100;


SDL_Rect dest;
dest.x = 700;
dest.y = 100;
dest.w = 100;
dest.h = 100;



SDL_BlitSurface(bitmap, &source, SDL_GetVideoSurface(), &dest);
SDL_Flip(SDL_GetVideoSurface());
}

void Ball()
{
SDL_Surface* bitmap=SDL_LoadBMP("ball.bmp");

SDL_Rect source;
source.x = 0;
source.y = 1;
source.w = 40;
source.h = 40;


SDL_Rect dest;
dest.x=WINDOW_WIDTH/2;
dest.y=WINDOW_HEIGHT/2;
dest.w=WINDOW_WIDTH/2;
dest.h=WINDOW_HEIGHT/2;



SDL_BlitSurface(bitmap, &source, SDL_GetVideoSurface(), &dest);
SDL_Flip(SDL_GetVideoSurface());
}

void Game()
{

Paddle1();
Paddle2();
Ball();
}

void Shortcut_to_start()
{
SDL_Init( SDL_INIT_VIDEO );
SDL_Surface* screen=SDL_SetVideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, 0, SDL_HWSURFACE | SDL_DOUBLEBUF);
SDL_WM_SetCaption( WINDOW_CAPTION, 0 );


SDL_Event event;
bool gamerunning = true;


while(gamerunning)
{
Game();

if(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
{
gamerunning = false;
}
if(event.type == SDL_KEYDOWN)
{
SDLKey keypressed = event.key.keysym.sym;


switch(keypressed)
{
case SDLK_ESCAPE: gamerunning = false;
break;
}
}
}
}


SDL_Quit();
}


int main(int argc, char **argv)
{
Shortcut_to_start();

return 0;
}



All right, I still dont really understand, also i had taken out the poll from my game loop and it still dosn't work (im confused)

Share this post


Link to post
Share on other sites
Mushu    1396
Okay, what we're doing is using a single event poll to make sure that we don't accidentially lose any events (keypresses) because we already got them and didn't do anything with them (what your original code did). To do this, we're going to make sure that, no matter what the event is, we get the information we need and save it for later.

In this case, we're going to do that by buffering the state of every key in a global variable so that every function can "see" it.

First: change the polling in the game loop to this:

if(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
{
gamerunning = false;
}

if(event.type == SDL_KEYDOWN)
{
keys[event.key.keysym.sym] = true;
}

if(event.type == SDL_KEYDOWN)
keys[event.key.keysym.sym] = false;
}
}

if (keys[SDLK_ESCAPE] == true) {
gamerunning = false; }
}



The reason why its not working is because you are still polling for events in two places. First take out the declaration of the array of keystates in Paddle1, since we moved that out to global so it was actually saved between each pass. (it was being deleted each time after Paddle1 returned)

void Paddle1()
{
SDL_Surface* bitmap=SDL_LoadBMP("Paddle.bmp");

SDL_Rect source;
source.x = 0;
source.y = 1;
source.w = 25;
source.h = 100;


SDL_Rect dest;
dest.x = 75;
dest.y = 100;
dest.w = 100;
dest.h = 100;


SDL_BlitSurface(bitmap, &source, SDL_GetVideoSurface(), &dest);
SDL_Flip(SDL_GetVideoSurface());

//bool keysheld[323]; // ***TAKE THIS LINE OUT***



And because we're doing all our event stuff in one place, we don't want to have another loop to steal events. So we're going to have to take that out:

/*SDL_Event event;
if(SDL_PollEvent(&event))
{
if(event.type==SDL_KEYDOWN)
{
keysheld[event.key.keysym.sym] = true;
}
if(event.type==SDL_KEYUP)
{
keysheld[event.key.keysym.sym] = false;
}
}*/


if(keys[SDLK_UP])
{
dest.y -=2;
}
if(keys[SDLK_DOWN])
{
dest.y+=2;
if(dest.y+dest.h > WINDOW_HEIGHT)
{
dest.y=600 - dest.h;
}
}
}



If you want a more detailed explanation of exactly why polling in two places doesn't work, I'll be happy to give one.

Share this post


Link to post
Share on other sites
Lasko    178

#include <SDL/SDL.h>

// things for the window

const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;
const char* WINDOW_CAPTION = "Pong Clone";

// dont know why i need this!
bool keys[SDLK_LAST];
bool keysheld[323];


void Paddle1()
{
SDL_Surface* bitmap=SDL_LoadBMP("Paddle.bmp");

SDL_Rect source;
source.x = 0;
source.y = 1;
source.w = 25;
source.h = 100;


SDL_Rect dest;
dest.x = 75;
dest.y = 100;
dest.w = 100;
dest.h = 100;


SDL_BlitSurface(bitmap, &source, SDL_GetVideoSurface(), &dest);
SDL_Flip(SDL_GetVideoSurface());

if(keys[SDLK_UP])
{
dest.y -=2;
}
if(keys[SDLK_DOWN])
{
dest.y+=2;
if(dest.y+dest.h > WINDOW_HEIGHT)
{
dest.y=600 - dest.h;
}
}
}





void Paddle2()
{
SDL_Surface* bitmap=SDL_LoadBMP("Paddle.bmp");

SDL_Rect source;
source.x = 0;
source.y = 1;
source.w = 25;
source.h = 100;


SDL_Rect dest;
dest.x = 700;
dest.y = 100;
dest.w = 100;
dest.h = 100;



SDL_BlitSurface(bitmap, &source, SDL_GetVideoSurface(), &dest);
SDL_Flip(SDL_GetVideoSurface());
}

void Ball()
{
SDL_Surface* bitmap=SDL_LoadBMP("ball.bmp");

SDL_Rect source;
source.x = 0;
source.y = 1;
source.w = 40;
source.h = 40;


SDL_Rect dest;
dest.x=WINDOW_WIDTH/2;
dest.y=WINDOW_HEIGHT/2;
dest.w=WINDOW_WIDTH/2;
dest.h=WINDOW_HEIGHT/2;



SDL_BlitSurface(bitmap, &source, SDL_GetVideoSurface(), &dest);
SDL_Flip(SDL_GetVideoSurface());
}

void Game()
{

Paddle1();
Paddle2();
Ball();
}

void Shortcut_to_start()
{
SDL_Init( SDL_INIT_VIDEO );
SDL_Surface* screen=SDL_SetVideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, 0, SDL_HWSURFACE | SDL_DOUBLEBUF);
SDL_WM_SetCaption( WINDOW_CAPTION, 0 );


SDL_Event event;
bool gamerunning = true;


while(gamerunning)
{
Game();

if(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
{
gamerunning = false;
}

if(event.type == SDL_KEYDOWN)
{
keys[event.key.keysym.sym] = true;
}

if(event.type == SDL_KEYDOWN)
keys[event.key.keysym.sym] = false;
}
}

if (keys[SDLK_ESCAPE] == true) {
gamerunning = false; }


SDL_Quit();
}


int main(int argc, char **argv)
{
Shortcut_to_start();

return 0;
}



Ok i follwed the directions and tried to understand, here is what i came up with and it still dosnt move.

Share this post


Link to post
Share on other sites
dudedbz1    100
Uhh, I have no idea what they mean. But there is an easier way. Have this:

Uint8 *Keys;
Keys = SDL_GetKeyState(NULL);

if (Keys[SDLK_UP]) // or whatever
// whatever

Just like in my example, check for key presses with Keys[...].

About the keypresses all over the place, yes it true. Have something like this game pump:

// sample game pump

while(MyGameIsRunningBool == true)
{
MyUpdateGameFunction(); // Includes all keypresses and events
MyDrawEverythingFunction(); // Draws all the graphics
}

This was just an example. The idea is not to check for keypresses all over the place.

-DBZ-

Share this post


Link to post
Share on other sites
Mushu    1396
If you do use that method, just be aware that you have to call SDL_PumpEvents(); each pass to update the key states. SDL_PumpEvents is called for you when you use SDL_PollEvent or SDL_WaitEvent, which is why you don't need it when using those functions.

Share this post


Link to post
Share on other sites
Lasko    178

#include "SDL/SDL.h"

const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;
const char* WINDOW_TITLE = "SDL Start";

SDL_Event event;
bool gamerunning = true;

void Paddle1()
{
//DRAW
SDL_Surface*bitmap=SDL_LoadBMP("paddle.bmp");

SDL_Rect source;
source.x = 0;
source.y = 1;
source.w = 25;
source.h = 100;

SDL_Rect dest;
dest.x = 75;
dest.y = 50;
dest.w = 75;
dest.h = 50;

SDL_BlitSurface(bitmap, &source, SDL_GetVideoSurface(), &dest);

SDL_Flip(SDL_GetVideoSurface());

//MOVE


}



void Game()
{
Paddle1();
}



void Init()
{
SDL_Init( SDL_INIT_VIDEO );

SDL_Surface* screen = SDL_SetVideoMode( WINDOW_WIDTH, WINDOW_HEIGHT, 0,
SDL_HWSURFACE | SDL_DOUBLEBUF );
SDL_WM_SetCaption( WINDOW_TITLE, 0 );

SDL_Event event;

while (gamerunning)
{
if (SDL_PollEvent(&event))
{
Game();
if (event.type == SDL_QUIT)
{
gamerunning = false;
}
if (event.type == SDL_KEYDOWN)
{
SDLKey keyPressed = event.key.keysym.sym;

switch (keyPressed)
{
case SDLK_ESCAPE:
gamerunning = false;
break;
}
}
}
}

SDL_Quit();
}



int main(int argc, char **argv)
{
Init();

return 0;
}



All right, thank you and sorry you guys, but there is too much information thrown at me, so pardon me as I paste a whole new code with less waste as the first, now my question is, What do I need add, Where and Why :-D

Share this post


Link to post
Share on other sites
dudedbz1    100
First, you need a gamerunning variable declared, not just used. That said, game() should be outside of the polling events. Then it lookds pretty nice. Though I suggest you have an update() function like this:

while(gamerunning)
{
update();
}

Which would get all the input, instead of throwing it in the loop like that.
Other than that, good start. Good luck.

Share this post


Link to post
Share on other sites
The Rug    628
Hmmm, I have to make this quick but I think the posters above missed the bit about not moving (forgive me if I'm wrong!) or I've read wrong!

The paddle isn't moving because you're re-initialising the variables every time the function is called:


void Paddle1()
{
// These variables won't retain their values between function calls!
// You certainly don't need to load the bitmap every funcion call, so have
// the variable "bitmap" in global scope, and call SDL_LoadBMP before you
// enter the game loop
SDL_Surface*bitmap=SDL_LoadBMP("paddle.bmp");

// This could remain here, because this doesn't change between calls
SDL_Rect source;
source.x = 0;
source.y = 1;
source.w = 25;
source.h = 100;

// This should be in global scope- re-initialising it every time means
// it will be drawn in the same place every time!
SDL_Rect dest;
dest.x = 75;
dest.y = 50;
dest.w = 75;
dest.h = 50;

// This blit call is OK ...
SDL_BlitSurface(bitmap, &source, SDL_GetVideoSurface(), &dest);

// This should be called only once per frame- after the 2 paddles and the
// ball have been updated and drawn
SDL_Flip(SDL_GetVideoSurface());

//MOVE
}




This is roughly what I'd do: (no compiler to check it though, so I've probably messed up somewhere [grin])


#include "SDL/SDL.h"

const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;
const char* WINDOW_TITLE = "SDL Start";

SDL_Event event;
bool gamerunning = true;

// The first paddle's position
SDL_Rect paddle1Dest;
paddle1Dest.x = 75;
paddle1Dest.y = 50;
paddle1Dest.w = 75;
paddle1Dest.h = 50;

// The first paddle's image
SDL_Surface* paddle1Bitmap;


void Paddle1()
{
//DRAW
SDL_Rect source;
source.x = 0;
source.y = 1;
source.w = 25;
source.h = 100;

SDL_BlitSurface(bitmap, &source, SDL_GetVideoSurface(), &paddle1Dest);

//MOVE


}



void Game()
{ // Draw everything here
Paddle1();

// THEN flip the video surface
SDL_Flip(SDL_GetVideoSurface());
}



void Init()
{
SDL_Init( SDL_INIT_VIDEO );

SDL_Surface* screen = SDL_SetVideoMode( WINDOW_WIDTH, WINDOW_HEIGHT, 0,
SDL_HWSURFACE | SDL_DOUBLEBUF );
SDL_WM_SetCaption( WINDOW_TITLE, 0 );

SDL_Event event;

// Load the paddle's image into paddle1Bitmap
paddle1Bitmap=SDL_LoadBMP("paddle.bmp");

while (gamerunning)
{
if (SDL_PollEvent(&event))
{
Game();
if (event.type == SDL_QUIT)
{
gamerunning = false;
}
if (event.type == SDL_KEYDOWN)
{
SDLKey keyPressed = event.key.keysym.sym;

switch (keyPressed)
{
case SDLK_ESCAPE:
gamerunning = false;
break;
}
}
}
}

SDL_Quit();
}



int main(int argc, char **argv)
{
Init();

return 0;
}




OK hopefully that helps, I'm in a rush to catch a train though, so I'll check back later.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this