Sign in to follow this  

Movement in SDL

This topic is 3631 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello! Do anybody know how to do a simple movement in SDL? This is my code so far.
#include "SDL/SDL.h"
#include <string>

SDL_Surface *character = NULL;
SDL_Surface *background = NULL;
SDL_Surface *screen = NULL;

SDL_Surface *load_image(std::string filename)
{
SDL_Surface* loaded_image = NULL;
SDL_Surface* optimized_image = NULL;

loaded_image = SDL_LoadBMP(filename.c_str());

if (loaded_image != NULL)
{
optimized_image = SDL_DisplayFormat(loaded_image);

SDL_FreeSurface(loaded_image);
}

return optimized_image;
}

void apply_image(int x, int y, SDL_Surface* source, SDL_Surface* destination)
{
SDL_Rect offset;

offset.x = x;
offset.y = y;

SDL_BlitSurface(source, NULL, destination, &offset);
}

int main(int argc, char* args[])
{
if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
return 1;
}

screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);

if (screen == NULL)
{
return 1;
}

SDL_WM_SetCaption("Lucas Adventures", NULL);

character = load_image("character.bmp");
background = load_image("background.bmp");

apply_image(0, 0, background, screen);
apply_image(34, 315, character, screen);

int charx;

SDL_Rect charr;
charr.x = charx;

int end = false;

SDL_Event keyevent;
while (end == false) 
{
while (SDL_PollEvent(&keyevent))
{
switch(keyevent.type){
case SDL_KEYDOWN:
switch(keyevent.key.keysym.sym){
case SDLK_LEFT:
charx -= 1;
break;
case SDLK_RIGHT:
charx += 1;
break;
case SDLK_ESCAPE:
end = true;
default:
break;
}
}
}
}

if (SDL_Flip(screen) == -1)
{
return 1;
}


SDL_FreeSurface(character);
SDL_FreeSurface(background);

SDL_Quit();
}


The problem is that the character don't move! :( I don't know how to store the characters x value and my try wasn't to good so I would be glad if you came up with some good ideas and examples :) And it's one more thing that don't work, it's when I've compile the game I can't see the images and I need to minimize the window and then open it again to make the images visible :( Thanks! MrUkki [Edited by - mrukki on January 6, 2008 9:48:37 AM]

Share this post


Link to post
Share on other sites
Fortunately, the problem here is quite simple to solve. You are drawing your background and character to screen only once. After that, you start a while look that continually checks for events, and inside there's code that changes your characters position... but your character is never drawn to screen again at it's new location. Also, note that you're only ever flipping your screen surface once, after the while loop has ended. You should do that every time once you've drawn everything to screen, each frame.

Here, this code should work (I'm only posting the main function here). Oh, and next time you post a lot of code, use the source tags. It makes code a lot easier to read and keeps post lengths down. :)

int main(int argc, char* args[])
{
if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
return 1;
}

screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);

if (screen == NULL)
{
return 1;
}

SDL_WM_SetCaption("Lucas Adventures", NULL);

character = load_image("character.bmp");
background = load_image("background.bmp");

// IMPORTANT! Always initialize variabeles before using them!
// It's good practice and helps avoiding nasty bugs.
int charx = 34;

// charr is never used... why leave these lines around here?
SDL_Rect charr;
charr.x = charx;

// Using a bool would be more appropriate here.
int end = false;

SDL_Event keyevent;
// (end == false) can also be written as (!end)
while (end == false)
{
while (SDL_PollEvent(&keyevent))
{
switch(keyevent.type){
case SDL_KEYDOWN:
switch(keyevent.key.keysym.sym){
case SDLK_LEFT:
charx -= 1;
break;
case SDLK_RIGHT:
charx += 1;
break;
case SDLK_ESCAPE:
end = true;
default:
break;
}
}
}

// IMPORTANT! Here goes the drawing stuff. Note that you should
// draw your character using charx, not simply 34, otherwise
// it would never move, obviously.
apply_image(0, 0, background, screen);
apply_image(charx, 315, character, screen);

// IMPORTANT! After all drawing is done, flip the screen surface.
SDL_Flip(screen)
}

SDL_FreeSurface(character);
SDL_FreeSurface(background);

SDL_Quit();
}

Share this post


Link to post
Share on other sites
Oh! Thanks man the code works!! [wink]
But when I press a arrow key it just move one pixel and the stops, so I need to click one time for every pixel :( I want it to keep going when I hold it down. How do I fix that?

Mrukki

[Edited by - mrukki on January 6, 2008 1:49:07 PM]

Share this post


Link to post
Share on other sites
You need to change your logic for that. Currently, you're changing your characters position only when a button is being pressed. That is, when it goes from up, to down, so to say. :)

A solution is to check if the up key is pressed each frame, and if it is, change the characters position. You could create a bool for this, which you set to true when you press the up key, and to false when you release the up key. Then, just before drawing the stuff, you check if that bool is true, and if so, you change your characters position accordingly.


I'll leave the code part up to you this time. Good luck! :)

Share this post


Link to post
Share on other sites
I made it!! [grin] I changed alot but it worked!! :)
I searched for "SDL_KeyboardEvent" on google and found some good things. Then I looked in my bookmarks for some good SDL tutorials an found a cool site(here) and there I found the perfect tutorial! :) I changed the hole movement system thing and replaced it with this cool stuff:


bool keysHeld[323] = {false};

while (end == false)
{
if (SDL_PollEvent(&keyevent1))
{
if (keyevent1.type == SDL_KEYDOWN)
{
keysHeld[keyevent1.key.keysym.sym] = true;
}
if (keyevent1.type == SDL_KEYUP)
{
keysHeld[keyevent1.key.keysym.sym] = false;
}
}

if (keysHeld[SDLK_ESCAPE])
{
end = true;
}

if (keysHeld[SDLK_LEFT])
{
charx -= 2;
chaar = 1;
}
if (keysHeld[SDLK_RIGHT])
{
charx += 2;
chaar = 0;
}
if (keysHeld[SDLK_UP])
{
chary -= 2;
}
if (keysHeld[SDLK_DOWN])
{
chary += 2;
}



You can see that I also made a new varible called chary that holds the value for the Y-axis and a varible chaar that holds a value of 2 pics, if chaar equals to 1 it displays the left pic of the character and the right pic if it equals to 0.
I know I could use a bool but I'll fix that later.
And this is the hole game code:


#include "SDL/SDL.h"
#include <string>

SDL_Surface *character_r = NULL;
SDL_Surface *character_l = NULL;
SDL_Surface *background = NULL;
SDL_Surface *screen = NULL;

SDL_Surface *load_image(std::string filename)
{
SDL_Surface* loaded_image = NULL;
SDL_Surface* optimized_image = NULL;

loaded_image = SDL_LoadBMP(filename.c_str());


optimized_image = SDL_DisplayFormat(loaded_image);

SDL_FreeSurface(loaded_image);

Uint32 colorkey = SDL_MapRGB( optimized_image->format, 255, 0, 255 );
SDL_SetColorKey( optimized_image, SDL_SRCCOLORKEY, colorkey );

return optimized_image;
}

void apply_image(int x, int y, SDL_Surface* source, SDL_Surface* destination)
{
SDL_Rect offset;

offset.x = x;
offset.y = y;

SDL_BlitSurface(source, NULL, destination, &offset);
}

int main(int argc, char* args[])
{
screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);

SDL_WM_SetCaption("Lucas Adventures", NULL);

character_r = load_image("character_r.bmp");
character_l = load_image("character_l.bmp");
background = load_image("background.bmp");

// IMPORTANT! Always initialize variabeles before using them!
// It's good practice and helps avoiding nasty bugs.
int charx = 20;
int chary = 305;
int chaar = 0;

// charr is never used... why leave these lines around here?

// Using a bool would be more appropriate here.
bool end = false;
SDL_Event keyevent1;
// (end == false) can also be written as (!end)
bool keysHeld[323] = {false}; // everything will be initialized to false

while (!end)
{
if (SDL_PollEvent(&keyevent1))
{
if (keyevent1.type == SDL_KEYDOWN)
{
keysHeld[keyevent1.key.keysym.sym] = true;
}
if (keyevent1.type == SDL_KEYUP)
{
keysHeld[keyevent1.key.keysym.sym] = false;
}
}

if (keysHeld[SDLK_ESCAPE])
{
end = true;
}

if (keysHeld[SDLK_LEFT])
{
charx -= 2;
chaar = 1;
}
if (keysHeld[SDLK_RIGHT])
{
charx += 2;
chaar = 0;
}
if (keysHeld[SDLK_UP])
{
chary -= 2;
}
if (keysHeld[SDLK_DOWN])
{
chary += 2;
}

// IMPORTANT! Here goes the drawing stuff. Note that you should
// draw your character using charx, not simply 34, otherwise
// it would never move, obviously.
apply_image(0, 0, background, screen);
if (chaar == 0)
{
apply_image(charx, chary, character_r, screen);
}
else if (chaar == 1)
{
apply_image(charx, chary, character_l, screen);
}
SDL_Flip(screen);
}
// IMPORTANT! After all drawing is done, flip the screen surface.


SDL_FreeSurface(character_r);
SDL_FreeSurface(character_l);
SDL_FreeSurface(background);

SDL_Quit();
}




I know it's ugly but I'll rewrite it all later, :)

Mrukki

Share this post


Link to post
Share on other sites
I'm not sure if LazyFoo's tutorials mentioned this, but an alternative to storing an array of keys is to increase the x and/or y velocity of the object at time of KeyDown, and subtract that velocity at time of KeyUp. The object still moves while the user holds the key down, and stops when they release.

Share this post


Link to post
Share on other sites

This topic is 3631 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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