Sign in to follow this  

When to switch to hero_idle animation?

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

Guys, I spent whole day trying to find a solution to this. I don't know how to say to the game to show the Ryu's IDLE animation. The only thing that comes to mind is: If no key is pressed, show_ryu_idle(), so I need to check all the possible buttons on my keyboard every single frame, but I'm sure there is more elegant solution, but nothing comes to mind. I tried to to do it like this: if ( no other animation is currently been shown ) { set anim to idle }, but the problem is that the SDL_KEYDOWN doesnt work that way. For example if I press UP ARROW, and i hold the up arrow for 120 frames, it will count as the key was down only once. So if I set the animation when the key is pressed, it will only work for the 1st frame... If you understood something from this, tell me how you made your own games to handle this??

Edited by Heelp

Share this post


Link to post
Share on other sites

Afaik, SDL sends you "key pressed down" and "key released" events, ie it detects changes between on and off only.

If you want the current state of a button, you need to store the last event for that button, like

 

boolean button = false;

 

if (key_down) buton = true;

if (key_up) button = false;

 

and in your idle animation:  if (!button) ....

Share this post


Link to post
Share on other sites

So, I need to declare variables for all the buttons, and check every frame if they are false???( so i can make the IDLE anim)

Edited by Heelp

Share this post


Link to post
Share on other sites

If you want the idle animation when the user has nothing pressed, yes

 

You should probably keep the details of that logic eg in the user input somewhere, and compute "isIdle" there, which you can use in the remainder of the game.

One step further you can hide all key details that way. If you ever want to allow changing the used keys, that would be a simple local change.

 

You can also merge all those functions into one

enum KeyDirection {
  KD_NONE, // or KD_IDLE
  KD_LEFT,
  KD_RIGHT,
  KD_UP,
  KD_DOWN,
};
  
KeyDirection getDirection(); // in the keyboard handler.

Share this post


Link to post
Share on other sites

i use getAsyncKeyState to get similar keyboard info from the winAPI.

 

all input is processed immediately, not deferred for later processing.

 

once input is processed, i then figure out which animation to play, based on the input.

 

so yes, i check all the keys, then determine the animation.

Share this post


Link to post
Share on other sites
I think it would be better to set a player action state depending on the player's position of action. This is because the way you describe, if the player attacked, and didn't press anything since pressing the attack button, no key would be pressed, or if the character would be falling.

For example: A player would have one action state set at a time, and you could select an animation depending on this. Idle animation could be played if the speed is == 0, and if they player is not currently in the process of another state such as falling or attacking.

Share this post


Link to post
Share on other sites
An action state could in itself have a few states, such as if it is complete, or if it is still in the process, and it's priority. The priority would determine whether or not it would or could be cancelled. Such as an idle state, which could be cancelled by walking or falling.

Share this post


Link to post
Share on other sites

Guys, sorry for the reaaally slow answers, I had 29308742 courseworks this month.... Java, Assembly,, ADT, Matlab, Arduino and maybe a few more I don't even remember. I haven't touched my game for two weeks. Now about the code - I read somewhere that it's better to divide the code to 4128239 header and source files, and I decided to give it a try, regretted that decision immediately. Now most of my mistakes are: forgot to add #include, forgot to declare function in header, forgot to add file to project.. and so on. Ok I attached the two files as .txt, see them and if you are too lazy, just give me pseudocode, nothing more.Basically I want to somehow handle all animations and make the code readable somehow ( including idle_anim ). Also see that frames_something variables, I have frame variable for every animation and I'm copy/pasting it cuz I cant find something better.
And any feedback concerning code modularity and simplicity is appreciated. Thanks for reading.

Share this post


Link to post
Share on other sites

Should I attach the whole project? ( I can attach the SDL 1.2 libs if you want, too )

EDIT: here is the project and libs and exe.

Share this post


Link to post
Share on other sites

You can achieve that with sometihg like this, i hope it helps:

 

in the input function:

void input()
{
  //KEY PRESSED
  if(KEYDOWN_LEFT)
  {
     player.setWalkingLeft(true);
  }
  if(KEYDOWN_RIGHT)
  {
     player.setWalkingRight(true); 
  }
  if(KEYDOWN_DOWN)
  { 
    player.setCrouch(true); // I dont know, use your imagination :D
  }
  //KEY RELEASED
  if(KEYUP_LEFT)
  {
     player.setWalkingLeft(false);
  }
  if(KEYUP_RIGHT)
  {
     player.setWalingRight(false);
  }
  if(KEYUP_DOWN)
  {
     player.setCrouch(false);
  }
}
   

The player could have some boolean variables indicating what is doing. And then in you can make this:
 

void Update()
{
 if(player.getWalkingRight() == true)
 {
    player.WalkingRightAnim();
 }
 else if(player.getWalkingLeft() == true)
 {
   player.WalkingLeftAnim();
 }
 else if(player.getCrouch() == true)
 { 
   player.CrouchedAnimation();
 }
 else
 {
   player.Idle_animation();
 }
}

I hope this pseudocode helps you get the idea. You need to specify which action is the player doing. If none of those is being made, you play de Idle animation

Share this post


Link to post
Share on other sites

While reading the project code I noticed a few things that you could change. I failed to understand the logic of the various ryu animations, but let's discuss that further down this post.

 

Ok, the first thing I noticed was some global variable magic. A fragment:

void Ryu::handle_walking()
{
    //If a key was pressed
    if( event.type == SDL_KEYDOWN )

Where does this "event" come from? Ryu is just one of the game characters, and SDL is the game-wide library, but it has no "event" variable of itself. A small search revealed it's a global and you set it here:

        while( SDL_PollEvent( &event ))
        {
            currentState->handle_events();

I think if you change the "handle_events" to "handle_events(const SDL_Event &event)", and pass in the event returned by the pollEvent, you can remove the global event variable.

 

In the other direction, you seem to change state:

void Stage18::handle_events()
{
    //If the user has Xed out the window
    if( event.type == SDL_QUIT )
    {
        //Quit the program
        set_next_game_state( STATE_EXIT );

If you give this new state as return value, I think you can drop the nextState variable, since a few lines below the poll loop you do "change_game_state();" that needs the new state.

 

Similar considerations hold for other global variables, like "screen". "background" doesn't look used?

 

I have more to say about Stage18::handle_events below.

Before going there, I'd like to discuss switching game states.

void change_game_state()
{
    //If the state needs to be changed
    if( nextState != STATE_NULL )
    {
        //Delete the current state
        if( nextState != STATE_EXIT )
        {
            delete currentState;
        }
    }

    //Change the state
    if( nextState == STATE_INTRO )
    {
        currentState = new Intro();
    }

    if( nextState == STATE_MENU )
    {
        currentState = new Menu();
    }

    .....

The logic of trying "if( nextState == STATE_INTRO ) ..." when "nextState == STATE_NULL" is beyond me, but what I wanted to talk about is the bigger picture.

You have several game states that you switch between. I think that is a good idea. Maybe there are better solutions, but I don't know any currently.

 

The question I have here is why do you repeatedly throw the "old" state away (and with it all loaded images and so on), and "new" a new state? Chances are soon you will leave this state as well, and go back to one you just deleted. The C++ code that you have looks fine, you nicely free all resources every time, but is that really needed?

Why not do something like

Intro intro;  // Instantiate all game states
Menu menu;
...

// elsewhere
// Switch state by just setting the pointer to the right state.
switch (nextState) {
    case STATE_NULL:
        break; // Do nothing

    case STATE_INTRO:
        currentState = &intro;
        currentState->Reset(); // Let the new state know it was chosen so it can reset itself (if required).
        break;
    ...
}

In your current setup, a state that you enter is "new"-ed, so it automatically initializes it local variables. In my proposal, you need to explicitly tell the state that it is chosen again so it can reset itself (unless none of your states has local variables of its own of course).

 

This will of course load all game states and all art that they carry, so it will take more memory.

 

 

 

Back to the "handle_events". You seem to handle all keys in the game state. That in itself is a good idea, since you know what to do with a key like "up". On the other hand, the "exit" case appears everywhere, and you just pass a result back to the main program since you cannot do anything with it.

An alternative is to stack key handlers. Instead of one place handling all, have several places, one after the other. First the "main" code gets a turn, if it cannot handle the key, the game state tries. If the game state doesn't know, the character gets a turn, and so on (although I may have listed all levels already :) ).

This ties the key handling code of a key to the point where you can do something useful with the information, less need to pass information up or down.

 

With the character, I am quite lost in what you're doing.

void Ryu::handle_events()
{
    handle_walking();
    handle_l_punch();
    handle_l_kick();
}

This suggests Ryu can do walking, lpunch, and lkick all at the same time? (they all get a change to handle keys or change animations).

I would expect there is one place where you select what you do, and you only do one of the above rather than all.

 

Maybe you are doing that, the entire movement logic is difficult to follow, you have so many functions. Also, this post is already too long. I think this would be enough for now.

Share this post


Link to post
Share on other sites

1st - the global variable magic biggrin.png
     When I have only 1 variable of a given type, I make it global so I don't have to pass it as an argument everywhere. For example I have only 1 window and only 1 event, so this means that I make them global. Now I don't do this because basically everyone says that it's bad practice so now I almost unlearned it, but I wrote that code months ago.

 

2nd - about dropping the nextState variable.
     Normally I need only 1 function and that is change_game_state(), but in 1 tutorial some guy said that in order my code to be more modular, I need to first set it and only change it only after all the logic() and before the render() cuz I shouldn't be "changing game objects all over the place"... so I have set() function and change() function...forget this, I got used to it and don't give it much thought now. biggrin.png

 

3rd - unused global variables:
     I do this a lot, maybe because I know the game is only 2-4 MB and I subconsiously become sloppier ,who knows biggrin.png

4th - about the STATE_NULL.
    Basically, the program loops through while() once every frame. So every frame it sets the nextState to STATE_NULL. And if I want to change the level, I pass a new state to set_next_game_state(newState) and the actual change happens in change_game_state().  And then immediately STATE_NULL is assigned. Because if I don't do this, It will load the level every frame. Forget this too, it's not important. Normally I change my code every month when I see something new biggrin.png

 

5th - about repeatedly throwing the old state again. I just saw this used in a tutorial, I haven't thought about that. It's good cuz its saving RAM, but it uses more processing power, because you need to load everything a lots of times. But the game is small so I don't care. But in large games I don't really know which is better, load everything once and forever, or kill it if you don't use it. I never even wondered about this...

 

6th - about the ryu handle_events() function. Normally, I need to do all the stuff in 1 function. 1 function for handle_events(), 1 for logic() and 1 for render(). Because if I have everything on a different place, I can't follow through. and in these functions, there are IF statements all over the place, so it actually says: if "u" is pressed,  set_next_anim() to light punch, and if "j" is pressed, use handle_l_kick() function and set_next_anim() to low kick, and then change the animation after the logic in change_animation().
And if you run the exe file, and spam the light kick and light punch, you see that there is no delay, you can interupt the animations whenever you want, that I can't fix. So basically all my problems are in ryu.cpp and ryu.h files. I fixed some of the errors that you were getting and I attached the project again and I hope you can compile it. If you can't, tell me where the errors are.

Edited by Heelp

Share this post


Link to post
Share on other sites

And if you run the exe file, and spam the light kick and light punch, you see that there is no delay, you can interupt the animations whenever you want, that I can't fix.
Your pre-condition fails already, windows .exe file don't work at Linux systems :p

 

I deduced your findings from reading the source code though. You run the "handle_events" from all moves, and each of them sets a new animation without regard to what is currently being shown. Iirc you don't reset the animation frame counter (although maybe you do that somewhere hidden?), in which case the next animation would start at the frame where the previous animation was.

 

That is why I asked if ryu could do all 3 actions at the same time, but my reason was not clear enough to you, as you gave a different answer :)

 

 

With your new post it is now also more clear to me what your problem actually is. You want to have better control when you can switch an animation.

Unfortunately, the solution is not so simple. I wrote an article about it I realize now, but perhaps that's a bit too generic for you to just throw the link in :)

 

As a small introduction towards the solution, you're dealing not with 1 but with 2 different (but tightly connected) problems. The first problem is most obvious, and it is what you already said to be the problem. You don't want to switch animations at any point in time, you want to control when it may happen (and in particular, when it may NOT happen).

The solution to this problem is a state machine. Just like the player can see only one GameState at a time, your character can only show one animation at a time. After starting, the animation is in full control. It progresses through its frames, and decides when the player input should be honoured (and give control to another animation, or restart itself (eg the 2nd punch immediately after the 1st one finishes). In general, action sequences should probably played til the end, but eg a walk cycle could be aborted at some point, and "idle" would always accept player input to a different animation.

 

This should work, but leads to the same code duplication problem you have in the key handlers of the game states. Every game state handles all keys. To solve that, you can see the key-input as a separate problem from the animation display. The former processes keys pressed by the player, and "posts" suggestions like "player likes to punch". The animation plays its animation, and decides whether the suggestion is allowed by its rules. If it is not, the suggestion is ignored. If it is, the animation is switched to the suggested one.

 

The third problem that is ignored here so far, is the capabilities of the player. For example, to kick, you need special shoes, which you may not have won yet. This may not be relevant in your game though, but I hope you can see the general case can be quite complicated.

 

To make an already long story a bit shorter, http://www.gamedev.net/page/resources/_/technical/game-programming/from-user-input-to-animations-using-state-machines-r4155 is what I wrote earlier about this subject. I hope it makes sense. The general solution may be a bit too much, but hopefully it acts as a source of inspiration for you.

Share this post


Link to post
Share on other sites

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