In this third part of my 2D game camera article I want to talk about object tracking.
We will explore different types of tracking and I finally show you a simple approach for a fixed instant object tracking system.
On top of that I will show how to use linear extrapolation to add some damping to the tracking. This makes the camera movement smoother and far more appealing.
What is Object Tracking for?
In the first part of this article we talked about camera movement executed with a CameraMove(x,y) method.
But to let the camera follow a certain game object, it would be much easier to, you guessed it, just tell the camera, which game object it should track.
For example with a CameraTracking( gameObject ) method.
(Under the hood, the CameraTracking() should use the CameraMove() method. Re-using code makes it more reliable and faster to develop)
When tracking objects, there are some things to consider:
- which object should be tracked and
- at which conditions should tracking occur?
The second point can be very easy or rather complicated.
Let’s say the object should always be at the center of the screen. This is a simple case because tracking does always occur and the camera gets constantly snapped to the objects position.
But lets say you want to track your player character and you want some kind of safe zone on the screen where no tracking should occur.
Furthermore a safe zone can be defined differently like you can see in the two image below.
Or imagine this: in horizontal direction the camera should instantly snap to the tracked object, but in vertical direction only if the object reaches a certain distance to the screen border.
Moreover: should the camera snap instantly to the object, or should it be a damped movement?
In fact the possibilities to track a game object are endless.
Itay Keren wrote an article of his talk Scroll Back – The Theory and Practice of Cameras in Side-Scrollers where he discussed many examples of different object tracking techniques.
Very interesting how many different and smart tracking approaches exist to meet the individual requirements to each game.
Unfortunately after I read Itay Keren’s article I did understand that there is not the one and only camera system you ever need when it comes to object tracking.
You have to think about which tracking technique suits best to your game and implement it to your code.
Instant Object Snapping
Now that we have dived into the art of camera tracking let’s talk about the most simple approach: the fixed camera snapping.
This approach snaps the camera constantly to the tracked object. Let me show what happens if the ball in our example scene moves.
As you can see, the ball always stays at the horizontal center of the screen. But what happens under the hood?
Let’s say the ball moves 50 px to the right (maybe because the player or a physics engine moved it).
If the ball moves 50 px to the right, it is not in the centre of the screen anymore.
The camera system knows which object to track because of the parameter of CameraTrackObject( gameObject ). gameObject would be the ball in our example.
If you save the tracked objects position on each game loop, you can calculate the difference between the current ball position to the ball position from last game loop.
Let’s call these the dx and dy. These variables store how far the ball has moved since last game loop. In our example dx = 50 and dy = 0.
Now just use the CameraMove( dx, dy ) method to move the camera and all its layers appropriately.
In our example, if the ball moves 50 px to the right, this means that all layers moves 50 px to the left, as we have already discovered in part 1 of this article. The CameraMove() method takes care of this.
Since the ball is part of the layer system it gets moved 50 px to the left, too. Now the ball is in the horizontal centre of the screen again.
Smooth Camera Tracking
To make the tracking smoother we can use LERP (linear interpolation).
function LERP(float v0, float v1, float t) return v0 + t(v1-v0); }
A simple function that calculates a result that lies between a start v0 and end value v1 at a certain time t.
The smaller the time value t the closer the result is to the first value v0.
The bigger the t value the result tends to the end value v1.
As you can see, this method is very cheap: no cos/sin or square roots which heavily slows down the game loop.
For smoothing our camera movement we do the following steps:
- calculate the distance from the tracked object to the center of the screen.
- use the LERP() method to calculate a linear interpolation of the distance value. Use LERP(0, distance, t).
- use t as a smoothing value. The smaller the value the smoother the movement will get.
- Let’s call the result of the LERP() method damping
- Multiply dx and dy with the damping value before you use the CameraMove(dx,dy) method.
Making t too small will make the camera movement too slow. I found a good range from 0.5 to 0.0001 for t.
Here is a short movie that demonstrates the smoothed tracking:
You should now have a good understanding of how a camera system for 2D games can be developed.
In part 1 you learned how a parallax effect can be achieved.
Part 2 explains how to make the parallax even more convincing by adding depth of field effects.
And this third part introduced some theories about object tracking and how the tracking can be smoothed with linear interpolation.
Hope this article was useful to you. If you have any questions use the comments.