An important aspect of almost any game is that things move right. The movement of objects needs to feel natural or intuitive, so that the players can interact with them effortlessly. We can use the manipulation of velocities and accelerations in order to achieve this.
Basic linear movement
Let us imagine a simple game like a side scrolling platformer or a top down space shooter.
In games like this, the player has relatively free movement along at least one axis, or even multiple, as in the case of the space shooter.
Let us say the player can control their character/avatar/space ship with the arrow keys.
With the simplest form of movement we can implement, we simply check if the appropriate keys are pressed each frame and then move the character a tiny bit in that direction.
That code might look something like this:
var vx = 0; if (keyIsDown(Key.Left)) vx -= 5; if (keyIsDown(Key.Right)) vx += 5; // frame dependent movement this.xPosition += vx; // frame independent movement this.xPosition += vx * timeDelta;
Note that I give both the code for frame dependent and frame independent movement. I recommend using the latter under virtually any circumstance for a variety of reasons. However, the first tends to result in simpler code, and so I like giving it as well here, to show the difference.
The case for linear movement
This implementation is very straight forward, and it will work fine. The player can now move their character by 5 units every second.
Clearly, while moving the speed of the player will be 5, and while standing still it will be 0. Each frame, exactly one of these is the case.
This means that there is no transition between standing still and moving fast. The player can accelerate, stop and turn around instantly and at will.
In principle there is nothing wrong with this. It allows the player very good control over their avatar, and will allow them to move in a very precise way – or in as precise a way their reaction time and the framerate of the game allows them.
For some games this is exactly what we want. For example, many bullet-hell type shooters have these very tight controls to allow the player to weave their way through large numbers of enemy projectiles relatively effortlessly.
Problems with linear movement
However, for a lot or even for most games, this kind of movement is not appropriate. It feels harsh, sudden and unnatural, especially when switching between standing still and moving at fast speeds instantly.
What we want instead is for there to be a slight (or maybe larger) transition in which the player speeds up, and then slows back down.
This can be achieved in a number of different ways.
Moving the goal post
One method that can be used, is to not move the player directly. Instead the input of the player can move an imaginary point, a goal, that the player object will try to reach.
The movement of that goal would work exactly like implemented above.
The player however would lag behind that goal. One way to implement this is to let the player object move only a certain fraction of the distance to the goal per time interval.
var fractionToGoal = 0.5; var differenceToGoal = goalPosition - this.position; // frame dependent movement this.position += differenceToGoal * fractionToGoal; // frame independent movement this.position += differenceToGoal * Math.Pow(fractionToGoal, timeDelta);
Note how we use the power of the fraction to move towards the goal in the frame independent case, because this type of movement follows an exponential curve as it approaches the goal.
By choosing the fraction the player object moves towards the goal point, we can now control how sudden or smooth the object moves.
For example, if we let the object move towards the goal with a fraction of 0.95 per second, it will be very quick, yet still feel a bit more natural than in the case before – which is equivalent to using a fraction of 1 here.
With a fraction of 0.3 however, the objects will move behind the goal point in a very sluggish way, hardly ever reaching it, if we continue to move the goal.
This method has an interesting impact on games with a physical level or obstacles that would stop the player’s movement. If we simulate these collision physics for the goal point, instead of the player, the player’s avatar will appear to slow down and gently touch the obstacle, instead of running straight into it. Whether this is desirable will of course depend on the specific game.
Velocity is the rate of change of an object’s position. In our previous cases, the velocity of our objects is merely implied. We can calculate it by subtracting the current and last known location and normalising by time if needed.
In this next approach, instead of directly changing the position of an object, or directly moving a goal point for the object to reach, we can instead change the object’s velocity, and simulate its movement accordingly.
var ax = 0; if (keyIsDown(Key.Left)) ax -= 5; if (keyIsDown(Key.Right)) ax += 5; // frame dependent movement this.xVelocity += ax; this.xPosition += this.xVelocity; // frame independent movement this.xVelocity += ax * timeDelta; this.xPosition += this.xVelocity * timeDelta;
Note the similarity of this to our first snippet of code, just that in case of setting a fixed
vx velocity value, we now set an
ax acceleration value.
The added step – sort of an indirect way of modifying the object’s position – is mathematically equivalent to (discretely) integrating over the velocity to obtain the object’s position.
Since this code will cause the velocity to grow linearly if accelerated into the same direction, it will make the position change – and thus the object move – quadratically, as if following a parabola.
This causes very smooth acceleration and movement.
Slowing down with friction
Unfortunately, the above code has one flaw: if we keep holding down our arrow keys, our player will continue to speed up forever, without anything stopping them.
In some games this may not be a problem, or even desirable. In these cases there will be some level geometry, or other forces causing the player to move at acceptable speeds, or maybe the game explicitly allows for continued acceleration. This could for example be the case in a more realistic space flight simulator.
In most games however, we would like for our character to stop once we stop holding down any movement keys. Further, we want there to be a maximum speed the character can achieve, since that feels more realistic in most scenarios.
We can achieve these goals by introducing friction: a force opposing any movement we make that will eventually slow down our character to stand still.
While in some games, like space shooters, it may not be physically correct to simulate friction, in terms of playability and to give the player the feeling of control, this is a great way to limit accelerated movement speed and reduce velocity when no movement keys are pressed.
For a simple simulation of friction, we can use formulas very similar to the ones that had us approaching a goal point exponentially above. Just that in this case, the goal point is 0 velocity.
We just add the following line to our program.
// frame dependent movement this.velocity *= frictionConstant; // frame independent movement this.velocity *= Math.Pow(frictionConstant, deltaTime);
Again, we see the power operator for our exponential curve.
0 < frictionConstant < 1 these lines of code will eventually slow down any object to a stand stiff. The closer the constant is to 0, the quicker the object will slow down.
Note that this code also limits the maximum velocity, as long as our acceleration is bounded. Imagine for example that our
acceleration is 1, and the
frictionConstant 0.5. We can never a velocity higher than
acceleration / frictionConstant = 2, since at that point, the friction multiplication will reduce the velocity as much as we accelerated.
Starting from basic linear movement, we went over the most common implementations of fluid movement in video games.
While there are other options, the mentioned ones are the most straight forward, and easy to implement.
I hope you found this interesting, and if so make sure to share the post on your favourite social media.
Also feel free to let me know if you any questions, or suggestions for future topics to write about.
Enjoy the pixels