Sign in to follow this  
Silenex

Walking - Logic

Recommended Posts

Silenex    100
I'm a fairly experienced programmer, not particularly in games, but anyway, I'm trying to accomplish a simple task and I'm having trouble with it.

The concept is straightforward: I have a tile based game and moving with the arrow keys moves you in 1 of four directions. I also have animations sequenced with these movements. Seems very simple, right? Well the problem that I'm running into is that I want the animations between tiles to be very smooth when continuously walking, for example holding down the arrow key for several tiles. Currently, at best I can get a short pause between tiles.

I know the problem must be that I'm simply not a very experienced game developer so I'm probably going about it all wrong. I would really appreciate it if someone could give me some pseudo code and explain the general process that this should be done.

Here's what I'm basically attempting right now (pseudo code, will write code for only 1 key, to simplify it)

[code]// called every frame
function () {
if(left_key_down)
++left_key_down_frames;
else
left_key_down_frames = 0;

if(left_key_down_frames > 6)
player.walk()
}

player.walk function() {
if(!player.canWalk)
return; // player can't walk

player.move(movement_finished_callback()); // move player to correct place
player.animate(); // animate the frames accordingly..
}

movement_finished_callback function() {
player.canWalk = true;
}[/code]

Share this post


Link to post
Share on other sites
braincell    115
Can the player be anywhere except in the center of the tiles? I mean, can he move freely or is it like chess? I am assuming that it's like chess based on what you said.

Why does the player need to wait 6 frames of holding the key to start walking? Is it for some kind of "start walking" animation to play or something else? Perhaps that's why you're getting the short pause between tiles, but it shouldn't happen if the player keeps holding the button. Either way, you shouldn't do it on a frames basis but on an ElapsedTime basis (ms) multiplied by frames. If it's by frames count, then people with lower/higher framerates will have different gameplay.

Does the player.move move the player incrementally (++x,y) , or does it direct him to move until he reaches the destination (ie the position update is in a different loop)?

Share this post


Link to post
Share on other sites
Silenex    100
Sorry I wasn't clear. The player does move incrementally, it's a smooth animation during which there's also a walking animation played on the character.

The reason there's a 6 frame delay for walking is because there's also the ability to turn in place. I didn't include that in the pseudo-code, but basically any pressing of the key less than 6 frames long will simply turn the player in place rather than move them.

Share this post


Link to post
Share on other sites
wild_pointer    291
[quote name='Silenex' timestamp='1306779872' post='4817601']
Sorry I wasn't clear. The player does move incrementally, it's a smooth animation during which there's also a walking animation played on the character.

The reason there's a 6 frame delay for walking is because there's also the ability to turn in place. I didn't include that in the pseudo-code, but basically any pressing of the key less than 6 frames long will simply turn the player in place rather than move them.
[/quote]

How would you expect movement to continue through multiple tiles when movement only begins after you have held down the key and then release it? I'd suggest better separating the moving and turning states of the player and better defining exactly what you want to have happen when the player presses the movement button and then proceeding from there.

Share this post


Link to post
Share on other sites
Silenex    100
The movement doesn't start after the button is released. It starts while the button is being pressed.

I know my method doesn't work. I'm not a very experienced game developer and it's the small things like this that get me stuck.

What I want to happen:

If the button is pressed for a short period of time it will just turn the user. If the button is held for a longer period of time it will move the user continuously between tiles, without a short pause between tiles.

Share this post


Link to post
Share on other sites
braincell    115
That's not a very good control scheme, and I haven't played any games that use it. Have you?

If the movement is relative to the screen (up/down is always up/down) then why do you need turning? If it's just for aiming, perhaps you can use a mouse to aim in a certain direction.

In case it's like GTA 1 where it's relative to the player facing (up/down key can be left/right movement if player is facing 90 degrees) then you have two options:
1- Make left/right only turn the player, and up/down be forward/backwards
2- Use two separate keys (eg < and > ) to turn the player, and the four directional keys to move fwd/back and strafe left/right.
3- Again, use the mouse to have the player facing a certain direction so he always follows the cursor. This depends on the gameplay.

If you really want to stick with the scheme you have in mind (short press is turning) then I suggest you make the player start moving as soon as the left key is pressed. However, if it's released in less than 6 frames, the player only turns. That way you will get instant movement and no stopping, but you may have the player appear to move a short distance as the key is pressed. There is simply no way around this problem since you are trying to use one key for both functions (movement and turning). And again, you shouldn't use frames, you should multiply movement rate with an accurate timer measuring milliseconds to have consistency between different systems.

Share this post


Link to post
Share on other sites
Silenex    100
I understand what you're saying, but I'm fairly set on this control mechanism, and yes I have seen it in other games.

The problem with your solution is that users can't be permanently be in between tiles. A player must be on a specific tile while they're stationary. The only time a user can be in between tiles is when they're in the process of walking between two tiles.

Perhaps a demo of what I'm talking about will makes things much more clear: [url="http://dev.rakuhana.org/CANVAS/wut/pc.php"]http://dev.rakuhana....NVAS/wut/pc.php[/url] (You'll have to be using a newer browser that supports canvas, preferably chrome).

As you can see, the turning mechanism works pretty good, but when you hold down a key and walk for multiple tiles there's an ever so slight pause between tiles.

And yeah, the code is pretty hacky at the moment.

Share this post


Link to post
Share on other sites
wild_pointer    291
[quote name='Silenex' timestamp='1306784197' post='4817629']
The movement doesn't start after the button is released. It starts while the button is being pressed.

I know my method doesn't work. I'm not a very experienced game developer and it's the small things like this that get me stuck.

What I want to happen:

If the button is pressed for a short period of time it will just turn the user. If the button is held for a longer period of time it will move the user continuously between tiles, without a short pause between tiles.
[/quote]

The formatting makes it seem so at a glance. At any rate, my advice stands. There's not really enough information to guess what might be wrong. I have no idea what your animate or move functions do or how you detect that you've reached a new tile and what you do then. Who knows, maybe the animation itself just doesn't loop seamlessly. There's nothing really special to game development in this case, if you're an experienced programmer then bring your standard deductive reasoning skills to to bear =P

Share this post


Link to post
Share on other sites
Silenex    100
[quote name='wild_pointer' timestamp='1306794550' post='4817687']
[quote name='Silenex' timestamp='1306784197' post='4817629']
The movement doesn't start after the button is released. It starts while the button is being pressed.

I know my method doesn't work. I'm not a very experienced game developer and it's the small things like this that get me stuck.

What I want to happen:

If the button is pressed for a short period of time it will just turn the user. If the button is held for a longer period of time it will move the user continuously between tiles, without a short pause between tiles.
[/quote]

The formatting makes it seem so at a glance. At any rate, my advice stands. There's not really enough information to guess what might be wrong. I have no idea what your animate or move functions do or how you detect that you've reached a new tile and what you do then. Who knows, maybe the animation itself just doesn't loop seamlessly. There's nothing really special to game development in this case, if you're an experienced programmer then bring your standard deductive reasoning skills to to bear =P
[/quote]

Oh, I see how you could have been lead to believe that now. The else condition on the statement only applied to this line:

[code]left_key_down_frames = 0;[/code]

I have a few new ideas, so I'll try some things.

Share this post


Link to post
Share on other sites
braincell    115
OK i've seen the canvas thing. Well, in that case you simply need to check if the key is pressed the same frame the animation and movement from tile 1 to tile 2 is finished. If it's pressed upon walk ending, then keep moving without resetting the frames to 0. That means a different resolution for the end of movement, which includes to first check if the key is pressed. Then if it's not pressed, do the movement stop as it should be, ie reset the frame count. If it's pressed simply make the animation running. You can artificially set the frames to 6 or whatever more elegant and propperly designed solution you want to implement.

Share this post


Link to post
Share on other sites
Kian    239
The OP is right about the movement scheme he is trying to copy. Games like pokemon use that kind of movement, where you move in a grid and can turn if you tap the movement key or move if you press and hold.

My advice: Don´t measure how long the key is down, but whether it has been lifted. Subtle difference. Also, don't measure frames, measure milliseconds. For instance, I don't know if your target FPS is 60 or 30, but 6 frames would be a delay of either 0.2 or 0.1 seconds, or 200 to 100 milliseconds.

Say the key is pressed. You set the character's state to move in the desired direction. He immediatly turns in place. Then you poll for key up events. If the key is lifted before 200 milliseconds, he stops moving (facing the new direction). Else he continues to move. Then you can have a continuous movement. When they finally release the key, you finish the movement into the next tile.

Share this post


Link to post
Share on other sites
lauris71    841
This may be overkill for such simple case, but I have found useful to separate the control into two parts - planning and animation.

Something along the lines (rough pseudocode):

[code]
enum State { IDLE, TURN_LEFT, WALK_LEFT };

function () {
if (left_key_down)
++left_key_down_frames;
else
left_key_down_frames = 0;

if(left_key_down_frames <= 6)
player.plan (TURN_LEFT)
else if (left_key_down_frames > 0)
player.plan (WALK_LEFT)
else
player.plan(IDLE)
}

class Player {
State requested_state;
State current_state;
};

Player::plan (State request) {
// One can test the possibility of action (for example movement) here
requested_state = request;
}


Player::timeSlice (double worldTime) {
animate (worldTime);
if (animation.finished ()) {
switch (requested_state) {
case IDLE:
current_state = IDLE;
break;
case TURN_LEFT:
// Here we should test what is current state - if already facing left we do not have to turn
current_state = TURN_LEFT;
break;
case WALK_LEFT:
if (can_move_left ()) {
current_state = WALK_LEFT;
break;
} else {
current_state = IDLE;
break;
}
break;
}
startAnimation (worldTime);
}
}
[/code]

Thus AI-controlled characters can share the animation code, only planning is implemented differently.

Share this post


Link to post
Share on other sites
braincell    115
[quote name='Kian' timestamp='1306816077' post='4817760']
The OP is right about the movement scheme he is trying to copy. Games like pokemon use that kind of movement, where you move in a grid and can turn if you tap the movement key or move if you press and hold.

My advice: Don´t measure how long the key is down, but whether it has been lifted. Subtle difference. Also, don't measure frames, measure milliseconds. For instance, I don't know if your target FPS is 60 or 30, but 6 frames would be a delay of either 0.2 or 0.1 seconds, or 200 to 100 milliseconds.

Say the key is pressed. You set the character's state to move in the desired direction. He immediatly turns in place. Then you poll for key up events. If the key is lifted before 200 milliseconds, he stops moving (facing the new direction). Else he continues to move. Then you can have a continuous movement. When they finally release the key, you finish the movement into the next tile.
[/quote]

Hmm that's exactly what I said he should do, a few posts up. :)

Share this post


Link to post
Share on other sites
O-san    1900
I am using a wanted angle and an actual angle in my game. If the wanted angle is not aligned with the actual angle the player should turn. If the angles are aligned the player should walk. Then always strive to have the actual angle aligned with the wanted using small increments (time based). Good luck!

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