Chase Camera Sample

This sample demonstrates how to create a simple chase camera with spring physics.

Sample Overview

In this sample, you can pilot a Spacewar ship from a third-person chase camera view. The motion of both the ship and the camera are governed by simple physics. When the ship speeds away, the camera pulls back. When the ship turns, the camera lags behind in the turn to show a partial profile view of the ship. When the ship stops moving, the camera gradually slides back into place.

By pressing a button, you can compare and contrast the spring-based camera with a rigid, fixed-offset camera. You will notice that the spring-based camera provides a greater sense of speed and the ship will feel more natural to control.

Minimum Shader Profile

Vertex Shader Model 1.1
Pixel Shader Model 1.1

Sample Controls

This sample uses the following keyboard and gamepad controls.

Action Keyboard Control (Windows) Gamepad Control Windows Phone
Steer. UP ARROW, DOWN ARROW, LEFT ARROW, and RIGHT ARROW Left thumbstick Touch (Screen Edge)
Accelerate. SPACEBAR Right trigger Touch (Center)
Toggle camera spring enabled A A Touch (Top-Left Corner)
Exit the sample. ESC or ALT+F4 BACK BACK

How the Sample Works

The three classes in this sample are ChaseCameraGame, ChaseCamera and Ship. The game class demonstrates the usage pattern for the ChaseCamera class. The ChaseCamera class implements the physics behavior and can easily be reused as is in your own games. The Ship class exists solely for the sake of having something to chase.

Using the ChaseCamera Class

During initialization, the game creates a Ship and ChaseCamera. The camera is initialized with values that will not change throughout the course of the sample such as the near and far plane distance. At this point, the camera's positioning is also defined. DesiredPositionOffset and LookAtOffset determine the resting location of the camera as well as the point the camera will look at. Both values are relative to the position of the camera and are specified in object space. That means that an offset of (0,1,1) will be one unit behind and one unit above the chased object regardless of which direction the object and camera are facing.

Each time the ship moves (once at initialization and during every frame) the camera must be informed of the new goals to chase. This is done by the game's UpdateCameraChaseTarget method, which simply copies the ship's position, direction, and up vectors to the appropriate properties of the ChaseCamera object.

Once the new chase targets are set, the camera's Update method is called to apply the physics logic. The Update method also updates the camera's view and projection matrices, which must be used when drawing the scene.

Understanding the ChaseCamera Class Implementation

At first glance, the ChaseCamera class has a lot of properties, which can be quite intimidating. The following figure, which maps the key properties, may be equally intimidating, but after studying it carefully, you will find the camera's behavior to be less mysterious.

These properties are described in full detail in their associated comments. Take special care to understand which coordinate system or units each of the properties use.

Notice that the camera is attached to a spring anchored at the desired position (which is some offset from the chase position). This spring pulls the camera toward the desired position. When the ship comes to rest, the spring subsequently brings the camera to rest as well. The exact behavior of the spring is dependant on both the spring’s stiffness and damping as well as the camera's mass, position, and velocity.

Spring Physics

When you stretch or compress a spring, it exerts a force on the attached bodies that is directly proportional to the elongation or compression of the spring. This force acts in the direction opposite of the elongation or compression. You can represent the displacement from the resting position as a vector originating at the camera's current position and extending to the desired camera position.

Vector3 stretch = position - desiredPosition;

You calculate the force of the spring by using Hook's Law, which formalizes the direct proportion between the elongation of a spring and the force it exerts. Do this by using a coefficient representing the stiffness of the spring. Because the spring force acts in the direction opposite the elongation, this stiffness coefficient is negated.

Vector3 force = -stiffness * stretch;

Given only this force in the absence of air resistance, internal friction, and other forces that act against an object with velocity, an elongated spring would oscillate infinitely. In order to combat this behavior, a simple linear damping force is employed in the force calculation. The force calculation is extended to the following:

Vector3 force = -stiffness * stretch - damping * velocity;

Once you've calculated the force, you apply it to the body by calculating acceleration using Newton's second law of motion. You then integrate acceleration to get the velocity, and integrate velocity to identify the new camera position. This sample uses Euler integration by simply multiplying by elapsed time.

// Apply acceleration
Vector3 acceleration = force / mass;
velocity += acceleration * elapsed;

// Apply velocity
position += velocity * elapsed;

Ideas to Expand

Want to create an even cooler camera? Try these ideas.

  • Add a method to shake the camera to look like an earthquake in a movie.
  • In many scenes, a larger field of view creates a greater illusion of speed. Animate the field of view so that it is larger when the camera is moving faster.
  • Add collision with your game world. If the camera or some bounding sphere collides with the game world, add another spring to prevent the camera from sticking out of the world.