• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Randall Perkins

SDL Player movement & animation glitch

13 posts in this topic

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

 

http://www.youtube.com/watch?v=3nMcextMAAg

 

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
0

Share this post


Link to post
Share on other sites

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.

0

Share this post


Link to post
Share on other sites

Milcho if i dont do it the way it is, then the player has the freedom to move in more then one direction at once which i dont want

0

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)

0

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.
0

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!"

0

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?

0

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

0

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.

1

Share this post


Link to post
Share on other sites

Milcho i am looking for sprite artist and coders for my project since im looking to make it open source on github

I thought you were saying that your animation was too fast - and I assumed you had the correct sprites for the animation. I still think your actual animation should be done outside the keydown handling, but if your problem is with the animation sprites not being as you want them, then I can't help you.

0

Share this post


Link to post
Share on other sites

i was not asking to help with sprite, i was just letting you know i might be making the project open source soon and thought you might have some interest in it!

im working on the animation at the moment 

 

here some of the maps so far :)

 

First map

21b51m1.png

 

route connecting to the next city

1zxs4jm.png

 

and the Ember City that the route connects to 

23s6hhl.png

0

Share this post


Link to post
Share on other sites

I anticipated your animation speed problem when I was making my previous post but figured I'd wait until you asked. (It's the next issue to arise in the logical order of what you're doing here.)

 

Simply use an animation step that is a multiple of the number of your animation frame count and then select the frame by integer division. This is going to get progressively more difficult if you don't either rearrange your sprite sheet or else abstract the positioning so that you can refer to the direction and animation separately. This function is already really big.

 

Check this out:

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

const int ANIMATION_FRAMES = 4;
const int ANIMATION_RATE = 15; //play with this number to control animation speed
const int ANIMSTEP_MAX = ANIMATION_FRAMES * ANIMATION_RATE;

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

DIRECTION direction = DIR_DOWN;
int animstep = 0;

static void player_movement(void) {
  //This should really be called from outside and handed in.
  //You want the same control state for the whole logical frame.
  Uint8* keystate = SDL_GetKeyState(NULL);
  DIRECTION dir = dir4(keystate);
  if(dir == DIR_NONE) {
    animstep = 0;
    return;
  }
  direction = dir;
  ++animstep;
  animstep %= ANIMATION_MAX;
  switch(direction) {
    case DIR_DOWN:  player_y += speed; break;
    case DIR_UP:    player_y -= speed; break;
    case DIR_RIGHT: player_x += speed; break;
    case DIR_LEFT:  player_x -= speed; break;
  }
}

After running player_movement your direction will be in 'direction'.
The frame of animation to render for that direction will be 'animstep / ANIMATION_RATE'.
 

dir4() imposes an order of precedence on your direction buttons, but that's really a pretty common thing in 4-direction schemes. If you really feel the need to direct according to the last button pressed then you can create a precedence function that reacts to key events and rewrite dir4() to prioritize that direction:

 

int priorityState = SDLK_DOWN;
DIRECTION priorityDir = DIR_DOWN;

void react_to_key_event() {
  if(control_event.type == SDL_KEYDOWN) {
    switch(control_event.key.keysym.sym) {
      case SDLK_DOWN:
        priorityState = SDLK_DOWN;
        priorityDir = DIR_DOWN;
        break;
      case SDLK_LEFT:
        priorityState = SDLK_LEFT;
        priorityDir = DIR_LEFT;
        break;
      case SDLK_RIGHT:
        priorityState = SDLK_RIGHT;
        priorityDir = DIR_RIGHT;
        break;
      case SDLK_UP:
        priorityState = SDLK_UP;
        priorityDir = DIR_UP;
        break;
    }
  }
}

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

 

Driving input by control events is heavy on the simulation (movement must be processed for every message) and reliant on the rate at which messages are generated and etc. While the code above times the animation based on the framerate, it's in the correct format to be adjusted to a variable timestep if and when you decide to do so. The best practice is to break the system up such that all inputs (not just control input but network input and etc as well) are available, then captured at their current state and passed through a single logical frame.

0

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  
Followers 0