Jump to content
  • Advertisement
Sign in to follow this  
Randall Perkins

SDL Player movement & animation glitch

This topic is 1969 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

This is a video of the bug ill explain and post code below

 

">

 

when you just press down the player moves down with the animation 

if you press a another direction key with down it will take it direction sprite and move down

 

heres the code

 

        if(in_game_state == 1 && app_state == 5) {
                keystate = SDL_GetKeyState(NULL);
                if(keystate[SDLK_DOWN]) {
                    if(btnPressed == 1) {
                        if(player_pos == 2) {
                            player_pos = 1;
                        }else if(player_pos == 1) {
                            player_pos = 3;
                        }else if(player_pos == 3){
                            player_pos = 2;
                        }
                    }else{
                        player_pos = 2;
                    }
                    move_y -= 1;
                    btnPressed = 1;
                }else if(keystate[SDLK_UP])   {
                    player_pos = 11;
                    move_y += 1;
                    btnPressed = 1;
                }else if(keystate[SDLK_RIGHT]) {
                    player_pos = 8;
                    move_x -= 1;
                    btnPressed = 1;
                }else if(keystate[SDLK_LEFT]) {
                    player_pos = 5;
                    move_x += 1;
                    btnPressed = 1;
                }else{
                    btnPressed = 0;
                }


        }

 

Defining variables 

 

in_game_state -  is just that it that the player is on the map and is allowed to move

app_state - is just so we know we are on the map part of the game

btnPressed - is just if the button pressed or not

move_x - is the players position on the screen

move_y - is the players position on the screen

player_pos = is the position of the sprite being used ( this is how im doing the animation ) 

Edited by MrPhoenix

Share this post


Link to post
Share on other sites
Advertisement

I don't use SDL to know exactly how the keystate works, but if it works how I imagine then:

 

Your code:

if(keystate[SDLK_DOWN]) {
...
}else if(keystate[SDLK_UP]) {
...
}else if(keystate[SDLK_RIGHT]) {
...
}else if(keystate[SDLK_LEFT]) {
...
}
 

 

should be

if(keystate[SDLK_DOWN]) {
...
}else if(keystate[SDLK_UP]) {
...
}

if(keystate[SDLK_RIGHT]) {
...
}else if(keystate[SDLK_LEFT]) {
...
}
 

Because that if/else meant that if down was pressed, then it wouldn't account for any other keys being pressed.

It's ok to have the down/up and left/right in a if/else block because the user won't press both at the same time (or at least, you can't move both up AND down), but the user CAN move both up/down AND left/right at the same time.

Share this post


Link to post
Share on other sites

Ah, I didn't realize that you didn't want player to move in more than one direction at once.

Then the solution isn't to use the keystate.

 

What you need is to receive the key-down events from SDL - I'm sure there's some way. Because what you're talking about then is basing the direction the player is moving based on which key was pressed last. In pseudo-code you would need some function that would look something like this:

 

 

void ReceiveSDLKeyEvent ( key )
{

  if (key == SDLK_UP)
  {
    movementDirection = MOVE_UP; //define MOVE_UP as some value, or make it part of an enum
  }
  else if (key == SDLK_DOWN)
  {
    movementDirecton = MOVE_DOWN;
  }
  else if (key == SDLK_LEFT)
  {
    movementDirecton = MOVE_LEFT;
  }
  else if (key == SDLK_RIGHT)
  {
    movementDirecton = MOVE_RIGHT;
  }

}



After this, your loop (the code you posed) would look something like this:

 

if( movementDirecton == MOVE_DOWN ) {
...
}else if( movementDirecton == MOVE_UP ) {
...
}else if( movementDirecton == MOVE_RIGHT ) {
...
}else if( movementDirecton == MOVE_LEFT ) {
...
}

 

You can't do that with just using states, because knowing the state won't tell you which key was pressed last. (admittedly there's a roundabout way to keep track of the last state, and extract the information of which key was pressed last by comparing the last and current keystates, but that's just reworking what I'm sure SDL already provides you with - which is the even information)

Share this post


Link to post
Share on other sites
Yeah, if player_pos does not have a value from 1-3 and btnPressed is 1, then the code isn't going to change player_pos if you are holding the down button. I would change this code:
                    if(btnPressed == 1) {
                        if(player_pos == 2) {
                            player_pos = 1;
                        }else if(player_pos == 1) {
                            player_pos = 3;
                        }else if(player_pos == 3){
                            player_pos = 2;
                        }
                    }
by changing the line "}else if(player_pos == 3)}" to just "}else{", which will allow the code to respond correctly if player_pos is taking a value corresponding to the other movement directions.

Share this post


Link to post
Share on other sites

If you arrange your sprite sheet so that rows represent directions to face and columns represent steps being taken then you can keep your direction separate from the animation step and just calculate your source rect x/y independently.
 
http://imageshack.us/photo/my-images/843/bigsprites.jpg/sr=1
 
If no direction is held then set the animation counter to zero. Otherwise set the direction and increment the animation counter. You can loop the animation by modulating it whenever you increment it:
 

int main() {
  int x = 0;
  int y;
  for(y = 0; y < 16; ++y) {
    ++x;
    x %= 4;
    printf("X is %i.\n", x);
  }
}

 
It may also help both readability and utility if you implement a direction function:

 

enum DIRECTION {
  DIR_DOWN,
  DIR_UP,
  DIR_LEFT,
  DIR_RIGHT,
  DIR_NONE
};

DIRECTION dir4() {
  if(keystate[SDLK_DOWN]) return DIR_DOWN;
  if(keystate[SDLK_UP]) return DIR_UP;
  if(keystate[SDLK_LEFT]) return DIR_LEFT;
  if(keystate[SDLK_RIGHT]) return DIR_RIGHT;
  return DIR_NONE;
}

Remember that you can optionally assign values to enumeration keys:

 

 

enum STUFF {
  THINGY = 1,
  CRUD = 2,
  HERP = 17
};

 

An alternative to all this would be to simply detect the circumstance where the player is holding two directions and pop up a window that says

 

"Electric Slide Bonus

555 points

You dancin' GOOD!"

Share this post


Link to post
Share on other sites

i think the error is when i change the player_pos int

Are you trying to make it so that if Down is pressed and the user presses Right then your player will continue moving down, without changing the sprite to be using the 'move right' animation?

Or are you trying to make it so that if Down is pressed and you press Right, the player starts moving to the right, with the correct animation?

Share this post


Link to post
Share on other sites

this is what i ended up coming up with that seem to work pretty good

    static void player_movement(void) {


        if(control_event.type == SDL_KEYDOWN) {

            switch(control_event.key.keysym.sym) {
                case SDLK_DOWN:
                    if(btnPressed == 1) {
                        if(player_pos == 2) {
                            player_pos = 3;
                        }else if(player_pos == 3){
                            player_pos = 1;
                        }else{
                            player_pos = 2;
                        }
                    }else{
                        player_pos = 2;
                    }
                    move_y -= 1;
                break;
                case SDLK_UP:
                    if(btnPressed == 1) {
                        if(player_pos == 11) {
                            player_pos = 12;
                        }else if(player_pos == 12) {
                            player_pos = 10;
                        }else{
                            player_pos = 11;
                        }
                    }else{
                        player_pos = 11;
                    }
                    move_y += 1;
                break;
                case SDLK_RIGHT:
                    if(btnPressed == 1) {
                        if(player_pos == 8) {
                            player_pos = 9;
                        }else if(player_pos == 9) {
                            player_pos = 7;
                        }else{
                            player_pos = 8;
                        }
                    }else{
                        player_pos = 8;
                    }
                    move_x -= 1;
                break;
                case SDLK_LEFT:
                    if(btnPressed == 1) {
                        if(player_pos == 5) {
                            player_pos = 6;
                        }else if(player_pos == 6){
                            player_pos = 4;
                        }else{
                            player_pos = 5;
                        }
                    }else{
                        player_pos = 5;
                    }
                    move_x += 1;
                break;
                default:
                    break;
            }
            btnPressed = 1;

        }else{
            btnPressed = 0;
        }


    }

 

 

only thing now is that the animations seem to fast

Share this post


Link to post
Share on other sites

So you did end up using the keydown events, as I suggested. The keystates you were using before are distinctly different from the keydown events. Keystates are persistent, and won't just report which key was last pressed - which is what the key events report. :) 

 

The reason your animation may be odd now is because the key down events are automatically sent at a certain rate (determined by the OS) when you hold down a key. Proper animation should be done outside the key down handling, you should set some flag to indicate which direction you're moving in, and animate somewhere else (outside the keydown event handling) based on that flag. See what I suggested in my previous post.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!