# Smooth movement in a tile based game

How can we make our character move smoothly across tiles? He moves tile by tile, but that looks unprofessional. In addition, when you hold down the arrow keys he zips across the screen. How can we prevent that from happening?

• You're using integers for player movement. Try using floats instead. – Mokosha Nov 4 '13 at 23:31
• It's best if you reduce your code to the minimum required to demonstrate/communicate your issue/question. Also, you might be interested in this question. – kevintodisco Nov 4 '13 at 23:34
• I removed the unnecessary parts of your question. It's best to get to the point and not add additional code or other fluff. – MichaelHouse Nov 4 '13 at 23:38

Smooth movement can be achieved in a number of ways. And it really depends on what kind of movement you want to allow.

• Movement still restricted to tiles. This type is the easiest for doing things like collision detection and other movement checks. For this type of movement you'll simply be interpolating the position over time as you transition between tiles. It can be as simple as adding something like the following to the update loop.

Pseudo code:

 if(GetDistance(position, targetposition) > minDistance) {
position = MoveTowards(position, targetposition, deltatime);
}


Where MoveTowards just takes the current position and adds a portion of the distance between it and the target position.

• Movement is not restricted to tiles. This gets a lot more tricky to implement. Essentially with this method you just store the position and update it via velocity. That is, change in position over time.

Holding down the arrow keys to move characters can also be implemented in a few different ways. Likely what you're doing is something like:

if(keydown(left))
tilePosition.X--;


This would indeed cause the character to zip across the screen. Since you'd be updating the position many times per second. A bit better way to implement this would be to add a delay. Something like

if(keydown(left)) {
if(leftKeyHeldTimer > movementDelay) {
tilePosition.X--;
leftKeyHeldTimer = 0;
} else {
leftKeyHeldTimer+= deltaTime;
}
}


This will add a delay timer and only update the tile position when the movementDelay value has been met.

I can identify two issues. The first related to smooth movement and the second is related to the character zipping off screen.

To create a smooth movement, you can use a technique called Linear Interpolation or (LERP) to smooth movement. Basically how it works is between your starting point and end point you calculate a set of decreasingly small distances to emulate smooth movement and slowing down as the endpoint is nearly reached.

The simplest example of this function would be:

//point1 is the current position, will be starting position on first call
//point2 is the target position
//epsilon is the % of the distance between current and target you want
//to cover per game physics loop (a fixed realworld time based loop).
//The smaller the % the "smoother" the motion.

float lerp(float point1, float point2, float epsilon)
{
return point1 + epsilon * (point2 - point1);
}


As the character moves closer to point 2 it will gradually slow down. Note though they will never actually touch point 2 but get infinitely close. You would need to correct this and if the player is less than an infinitely small distance from point 2 we can consider the player being on point 2.

The second issue you mentioned is related to your character flying offscreen. This is a result of the input being read every game loop refresh combined with the instant movement between tiles.

Ideally to solve this, in your code you need to decide

1. How much realworld time it would take for the character to move from point 1 to point 2.
2. Set your Lerp to run between point 1 and two over this duration
3. Read input again once point 2 has been reached to decide where to go