Followers 0

# Programming a walk cycle

## 10 posts in this topic

Hi guys!

I created a RPG game and released it, one of the critiques about it is that the animation is not "smooth".

After lots of questioning the players, what I understood is the walk animation and the actual movement are not synchronized, so the player seems to slide.

Basically the pseudo code for walking is this:

if (key_pressed(up))

{

player->walking = true;

player->walktime = GetTime();

player->animation->play('walk');

}

if (player->walking == true)

{

player->position.y += time_elapsed() * WALK_SPEED;

if (GetTime() - player->walktime> WALK_DURATION)

{

player->walking = false;

player->animation->play('idle');

}

}

But this is kinda amateurish, the results are not good...

How professional games do it?

My character walk cycle animation is done "in place". I've heard about having animations with actual translations, I guess that would be the easy way to do it. But sadly I cannot change my animation, it would require lots of money that I dont have anymore.

Now what I ask, it is possible to avoid having the character "sliding" without having actual translations in the animation data, but instead, doing the movement programatically?

Any ideas how can I improve this situation?

My engine allows to specify callbacks for specific animation frames, so I guess I could make use of that, but I am not having a clue what to do with it, ideas?

Edited by Relfos
0

##### Share on other sites
You could speed up the animation a bit. Like deanery adepts * somevalue.
Or slow down the units speed
0

##### Share on other sites
On my phone and it's replace frametimedelt with deanery adepts lol
0

##### Share on other sites

What we did at my previous job was have a "root" bone that was keyed for where in 2d space the character was, and was transformed out of the animation (so all the animation data is at the origin) and the game could use it to move the character each frame by the amount it moved in the animation frame.

0

##### Share on other sites

Sliding can be seen where the feet are in contact with the ground.

Reason A: The animation is made so that the distance between feet is not constant although both are in contact with the ground.

Reason B: The speed of the center of mass does not correspond to the animation and its playback speed.

Now the question is how the animation system works. Is WALK_SPEED a constant or a player controlled variable? Is animation blending in use? Does the movement depend in any way from the ground and its slope? Is some locomotion system in use?

Okay, probably no locomotion system and also no animation blending. Under such conditions sliding due to reason A could of course not be eliminated but only minimized until you are willing to rework the animation poses themselves.

The suggestions made by ankhd and KulSeran can be used for both reason A and B. Both suggestions do not really prevent from sliding but reduce it to an amount where it is hopefully no longer visible (in the case of reason B). I.e. they don't guarantee that the contact point of a food on ground is preserved. The suggestion of ankhd has the lowest impact on code, while KulSeran's suggestion allows for finer control (i.e. positioning in dependence on the animation's phase).

A full solution would be to use a locomotion system where the contact points are under control and the body's position is computed backwards from a contact point, eventually utilizing inverse kinematics when dealing with several contact points. This however would require far reaching changes in both the animation data and the animation system, and hence seems not an option because it would be too costly.

2

##### Share on other sites

haegarr, WALK_SPEED is a constant. There are no slopes in the game, all movement is only in a 2D plane (altough the game is 3D).

I had originally this value somehow calibrated to the walking animation, but players told me the character walked too slow, so I increased the walking speed.

A full locomotion system is unfortunely not a possilibity, so I guess I will try to speed up the animation until the problem is somehow masked.

0

##### Share on other sites

I had the same problem before. The solution is to not have your movement logic in the keyPressed method because keyPressed is an asynchronous method which means you have no control over when this method gets called. This causes the sliding and the delay in response. Move your computational logic in to the update method of the given object.

keyPressed method should not contain any computation logic as this causes delay in response despite the computation being correct.

Edited by warnexus
1

##### Share on other sites

I had the same problem before. The solution is to not have your movement logic in the keyPressed method because keyPressed is an asynchronous method which means you have no control over when this method gets called. This causes the sliding and the delay in response. Move your logic in to the update method of the given object.

Actually my engine is single threaded so this makes no difference, actually the logic is inside the object Update() function

0

##### Share on other sites

I had the same problem before. The solution is to not have your movement logic in the keyPressed method because keyPressed is an asynchronous method which means you have no control over when this method gets called. This causes the sliding and the delay in response. Move your logic in to the update method of the given object.

Actually my engine is single threaded so this makes no difference, actually the logic is inside the object Update() function

Oh I see what the problem you are facing now! It is the conditions in both if statements. Don't make the condition be button dependent or based on a boolean flag. Make it dependent on a state and the direction of the character.

The reason you want it not to be button dependent is because you will run into future problems when you start implementing attack animations that depends on what key was pressed. I give you an example. Suppose pressing a key would trigger a boolean flag that increments the frame of the attack animation. If you let go of the key, the animation would finish. This is not the result you want and all games I have seen do not do this either because aesthetically it looks weird and it can threaten the balance of the game "hit and run tactic".

The second condition in the if statement will make things "look" more complicated because you have to juggle which boolean flag was turned on.

Again make your condition dependent on a state and the direction of the character and you will not face the future problems I spoke of earlier.

Edited by warnexus
0

##### Share on other sites

Ah, but it is state-based. When the key is pressed I start an animation state, I just did not include all in the pseudo code to simplify it a bit

0

##### Share on other sites

Ah, but it is state-based. When the key is pressed I start an animation state, I just did not include all in the pseudo code to simplify it a bit

Try my approach: Same code applies to the other states. This is how my run left animation code is structured in my rpg.

public void keyPressed(KeyEvent e) {

if(KeyEvent.VK_LEFT == e.getKeyCode() )
{
isLeftPressed = true;
isLeftReleased = false;

}
}

public void update()
{

if(isLeftPressed)
{
direction = Direction.LEFT;
}

}

if(isLeftPressed || isRightPressed || isUpPressed || isDownPressed)
{
state = ActionState.RUNNING;

}

if(state == ActionState.RUNNING && direction == Direction.LEFT)
{

soraRunLeftAnimation.incrementFrame();
if(isLeftReleased || soraRunLeftAnimation.isLastAnimFrame())
{
state = ActionState.IDLE;
soraRunLeftAnimation.resetAnim();
}

}
}

public void draw(Graphics2D g2D)
{

if(state == ActionState.RUNNING && direction == Direction.LEFT && !isRightPressed )
{
soraRunLeftAnimation.draw(g2D);
}
}

Edited by warnexus
0

## 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