Sign in to follow this  
Stromberg

SDL Moving Picture

Recommended Posts

1. How can I have a non-stop moving of my picture? That means, that I want to hit an arrow key, an the increment of the variable X or Y does not stop. Still just now I have to hit the key all the time again. 2. The LEFT and UP Key don't work? Only RIGHT and DOWN work. How to solve this problem? Can help me anybody please? Here's the Code:
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include <string>
using namespace std;

SDL_Surface * LoadImage(const string &filename);
bool ApplySurface(short x, short y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *frame = NULL);

SDL_Surface *screen = NULL;
const short SCREEN_X = 640;
const short SCREEN_Y = 480;
const short SCREEN_COLOUR = 32;

int main(int argc, char *args[])
{
    //Variables
    SDL_Surface *background = NULL;
    SDL_Event event;
    bool exit = false;
    short X=0;
    short Y=0;

    //Initialisation
    if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
    {
        return 1;
    }

    screen = SDL_SetVideoMode(SCREEN_X, SCREEN_Y, SCREEN_COLOUR, SDL_SWSURFACE);
    if(screen == NULL)
    {
        return 1;
    }

    background = LoadImage("keen6art.jpg");
    if(background == NULL)
    {
        return 1;
    }



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

            if(event.type == SDL_KEYDOWN)
            {
                switch( event.key.keysym.sym )
                {
                    case SDLK_UP: Y=Y-4;
                    case SDLK_DOWN: Y=Y+4;
                    case SDLK_LEFT: X=X-4;
                    case SDLK_RIGHT: X=X+4;
                    default:;
                }
            }


        }

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

        if(!ApplySurface(X,Y,background,screen)) return 1;
    }

    SDL_FreeSurface(background);
    SDL_Quit();

    return 0;
}

SDL_Surface * LoadImage(const string &filename)
{
    SDL_Surface *loadedImage = NULL;
    SDL_Surface *optimizedImage = NULL;
    loadedImage = IMG_Load(filename.c_str());
    if(loadedImage != NULL)
    {
        optimizedImage = SDL_DisplayFormat(loadedImage);
        SDL_FreeSurface(loadedImage);
    }
    return optimizedImage;
}

bool ApplySurface(short x, short y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *frame)
{
    SDL_Rect offset;
    offset.x = x;
    offset.y = y;
    if(SDL_BlitSurface(source, frame, destination, &offset) != -1)
    {
        return true;
    }
    else
    {
        return false;
    }
}
3. How can I improve my Code? If you can find style erros...or if you know a better way for me to do something, please tell me! Only on this way I cann improve myself. Stromberg

Share this post


Link to post
Share on other sites
1. Use SDL_GetKeyState to determine if a key is currently held down each frame. The SDL_KEYDOWN event only fires once when you press the key down. If you must use events, you could e.g. set a flag on the SDL_KEYDOWN event and clear it on the corresponding SDL_KEYUP to keep track of just the arrow keys' state.

2. Your switch is broken because you don't have a "break;" between the cases. This means that when you press left, the program continues to also execute the "right" case and results in no movement.

Share this post


Link to post
Share on other sites
If you want the movement to be non-stop you're going to need some code to keep updating the sprites position in the specified direction when the key is not pressed. Currently the position is only changed on a key press event. In addition to the x and y position I would have xVelocity and yVelocity
so that the increment is x += xVelocity and y += yVelocity. Every time a key is press the appropriate velocity is incremented or decremented by a fixed amount, 4 for example, and each through your loop you increment y an x by yVelocity and xVelocity respectively.

I recommend you add breaks to your cases eg:

case SDLK_UP:
Y=Y-4;
break;




hope that helps.

Share this post


Link to post
Share on other sites
Now I made it this way. But although the non stop increment doesn't work.


#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include <string>
using namespace std;

SDL_Surface * LoadImage(const string &filename);
bool ApplySurface(short x, short y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *frame = NULL);

SDL_Surface *screen = NULL;
const short SCREEN_X = 640;
const short SCREEN_Y = 480;
const short SCREEN_COLOUR = 32;

int main(int argc, char *args[])
{
//Variables
SDL_Surface *background = NULL;
SDL_Event event;
bool exit = false;
short X=0;
short Y=0;
Uint8 *allKeys = SDL_GetKeyState (NULL); //???

//Initialisation
if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
return 1;
}

screen = SDL_SetVideoMode(SCREEN_X, SCREEN_Y, SCREEN_COLOUR, SDL_SWSURFACE);
if(screen == NULL)
{
return 1;
}

background = LoadImage("keen6art.jpg");
if(background == NULL)
{
return 1;
}





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

//???
if (allKeys[SDLK_UP]) Y=Y-4;
if (allKeys[SDLK_DOWN]) Y=Y+4;
if (allKeys[SDLK_LEFT]) X=X-4;
if (allKeys[SDLK_RIGHT]) X=X+4;

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

if(!ApplySurface(X,Y,background,screen)) return 1;

}


}

SDL_FreeSurface(background);
SDL_Quit();

return 0;
}

SDL_Surface * LoadImage(const string &filename)
{
SDL_Surface *loadedImage = NULL;
SDL_Surface *optimizedImage = NULL;
loadedImage = IMG_Load(filename.c_str());
if(loadedImage != NULL)
{
optimizedImage = SDL_DisplayFormat(loadedImage);
SDL_FreeSurface(loadedImage);
}
return optimizedImage;
}

bool ApplySurface(short x, short y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *frame)
{
SDL_Rect offset;
offset.x = x;
offset.y = y;
if(SDL_BlitSurface(source, frame, destination, &offset) != -1)
{
return true;
}
else
{
return false;
}
}


PS: Excuse my bad english.

Stromberg

Share this post


Link to post
Share on other sites
1. Now I made it with the Function "SDL_EnableKeyRepeat". And it works good.
What do you think about? How can I still improve the Code?

2. I want to hit 2 arrow keys simultaneous. For exemple, LEFT + DOWN. But it does not work. Only LEFT works in this combination.
But how can I hit keys simultaneous?

CODE:

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include <string>
using namespace std;

SDL_Surface * LoadImage(const string &filename);
bool ApplySurface(short x, short y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *frame = NULL);

SDL_Surface *screen = NULL;
const short SCREEN_X = 640;
const short SCREEN_Y = 480;
const short SCREEN_COLOUR = 32;

int main(int argc, char *args[])
{
//Variables
SDL_Surface *background = NULL;
SDL_Event event;
bool exit = false;
short X=0;
short Y=0;
Uint8 *allKeys = SDL_GetKeyState (NULL); //???

//Initialisation
if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
return 1;
}

screen = SDL_SetVideoMode(SCREEN_X, SCREEN_Y, SCREEN_COLOUR, SDL_SWSURFACE);
if(screen == NULL)
{
return 1;
}

background = LoadImage("keen6art.jpg");
if(background == NULL)
{
return 1;
}



SDL_EnableKeyRepeat ( 1, 10); // <- !!!

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

if(event.type = SDL_KEYDOWN)
{

switch(event.key.keysym.sym)
{
case SDLK_UP:
Y=Y-1;
break;
case SDLK_DOWN:
Y=Y+1;
break;
case SDLK_RIGHT:
X=X+1;
break;
case SDLK_LEFT:
X=X-1;
break;
default:
break;
}
}


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

if(!ApplySurface(X,Y,background,screen)) return 1;

}


}

SDL_FreeSurface(background);
SDL_Quit();

return 0;
}

SDL_Surface * LoadImage(const string &filename)
{
SDL_Surface *loadedImage = NULL;
SDL_Surface *optimizedImage = NULL;
loadedImage = IMG_Load(filename.c_str());
if(loadedImage != NULL)
{
optimizedImage = SDL_DisplayFormat(loadedImage);
SDL_FreeSurface(loadedImage);
}
return optimizedImage;
}

bool ApplySurface(short x, short y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *frame)
{
SDL_Rect offset;
offset.x = x;
offset.y = y;
if(SDL_BlitSurface(source, frame, destination, &offset) != -1)
{
return true;
}
else
{
return false;
}
}


Thanks

Stromberg

Share this post


Link to post
Share on other sites
SDL_EnableKeyRepeat is almost always the wrong thing to do, unless you're collecting text input (eg. for a text box). It will just keep generating the last event over and over, which is no good for you here.

Either check SDL_GetKeyState for all keys you're interested in instead of checking events, or change a velocity value on the object when keys are pressed and released and update their position based on that.

Share this post


Link to post
Share on other sites
Mh, I've still got a problem. With SDL_GetKeyState, I can only find out if a key was pressed, not if the key is pressed! But I want to know if a key is pressed. How to find out about that?

Stromberg

Share this post


Link to post
Share on other sites
Quote:
Original post by Stromberg
Mh, I've still got a problem. With SDL_GetKeyState, I can only find out if a key was pressed, not if the key is pressed! But I want to know if a key is pressed. How to find out about that?

Stromberg


Would you mind elaborating on that? SDL_GetKeyState gets the current key state.

Share this post


Link to post
Share on other sites
replace your main function with this..

int main(int argc, char *args[])

{

//Variables

SDL_Surface *background = NULL;

SDL_Event event;

bool exit = false;

short Xvel=0;

short Yvel=0;

short X=0;

short Y=0;



//Initialisation

if(SDL_Init(SDL_INIT_EVERYTHING) == -1)

{

return 1;

}



screen = SDL_SetVideoMode(SCREEN_X, SCREEN_Y, SCREEN_COLOUR, SDL_SWSURFACE);

if(screen == NULL)

{

return 1;

}



background = LoadImage("keen6art.jpg");

if(background == NULL)

{

return 1;

}







while(exit == false)

{

while(SDL_PollEvent(&event))

{

if(event.type == SDL_QUIT)

{

exit = true;

}



if(event.type == SDL_KEYDOWN)

{

switch( event.key.keysym.sym )

{

case SDLK_UP: Yvel=-4;

case SDLK_DOWN: Yvel=4;

case SDLK_LEFT: Xvel=-4;

case SDLK_RIGHT: Xvel=4;

}

}

if(event.type == SDL_KEYUP)

{

switch( event.key.keysym.sym )

{

case SDLK_UP: Yvel=0;

case SDLK_DOWN: Yvel=0;

case SDLK_LEFT: Xvel=0;

case SDLK_RIGHT: Xvel=0;

}

}




}



if(SDL_Flip(screen) == -1)

{

return 1;

}

X += Xvel;
Y += Yvel;

if(!ApplySurface(X,Y,background,screen)) return 1;

}



SDL_FreeSurface(background);

SDL_Quit();



return 0;

}

This checks for a key down event, and sets the velocity to 4. When it sees a key up event, it puts it back. This should work for pressing two buttons together, ie Up and Right. If you wanted the values to add up, so your image got faster and faster, change the four case SDLK_ lines in the SDL_KEYDOWN if, so that it says Xvel += 4, or Xvel -= 4 and the same with the Yvel.

Thats what I have used in the past, but I just added those modifications in from memory.. they might be slightly wrong.

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