Making the camera follow units

This recipe will cover some principles on how to make the camera follow something in the game world. While it might seem like an easy task at first, there are some tricky bits too.

Getting ready

The recipe will build upon the Creating an RTS camera AppState object recipe of this chapter. All of the steps described in this recipe will be applied to AppState.

How to do it...

To make the camera follow units, perform the following steps:

  1. We start by adding two new variables, which we'll use for the new functionality. A Vector3f variable, called targetLocation, will be used to track the target, and a Boolean variable called follow, will be used to declare whether the camera should track the target or not. These are set from external classes.
  2. Out of convenience, we also define a final Vector3f variable, called UNIT_XZ, which we set to(1f, 0, 1f). We'll use this to convert 3D positions to 2D.
  3. Then, we need to add some functionality in the update method just before cam.setLocation(camLocation);.
  4. First, we add a check to see whether the camera has been moved by the player. If so, we turn off the tracking as follows:
    if(tempVector.length() > 0){
      follow = false;
    }
  5. Since the camera is up in the air and the target is (most likely) on the ground, we transform the camera's location to a position on the same horizontal plane as the target. The targetLocation vector is pretty simple to handle. We just flatten it by zeroing on the Y value as follows:
    Vector3f targetLocation2D = targetLocation.mult(UNIT_XZ);
  6. The camera is a bit trickier; since we're interested in the target's position in relation to the point the camera is looking at, we need to first find out where it is looking. First, we get the relative position of the point the camera is looking at by multiplying the height with the direction as follows:
    Vector3f camDirOffset = cam.getDirection().mult(camDistance);
  7. Then, we add it to the camera's location (you can say that we project it on the ground) to get its world position. Finally, we flatten this as well with UNIT_XZ as follows:
    Vector3f camLocation2D = camLocation.add(camDirOffset).multLocal(UNIT_XZ);
  8. We're using a linear interpolation that moves the camera's focus point 30 percent closer to the target location each cycle. Then, we reverse the addition we did earlier (or unproject) to get a new 3D position for the camera. The distance check is optional, but since we're going to use interpolation, we might save a few calculations by only interpolating if the distance is above a certain threshold as follows:
    if(targetLocation2D.distance(camLocation2D) > 0.01f){
      camLocation2D.interpolate(targetLocation2D, 0.3f);
      camLocation.set(camLocation2D);
      camLocation.subtractLocal(camDirOffset);
  9. To show that these changes work, we need to change a few things in our test application. We can grab Jaime from our scene and use his translation as the target location. We use worldTranslation and not localTranslation in this case:
    appState.setTargetLocation(jaime.getWorldTranslation());
    appState.setFollow(true);
  10. Then, in the update method of the test case, we make him slowly move along the x axis as follows:
    jaime.move(0.2f * tpf, 0, 0);
  11. While running the application, we should see the camera follow Jaime until we move it manually.

How it works...

Another way of handling it would be not to move the camera during the input but the actual point it looks at, and have the camera troll along. No matter which way you choose to do it though, practicing and thus getting a better understanding of these trigonometric problems is always a good idea.

Since we're using linear interpolation here, camLocation2D will never actually reach targetLocation; it'll just get infinitely closer. This is why an if statement can be useful in these cases to see whether it's worth actually changing the distance or not. Finding the right threshold to break off is empiric and varies from case to case.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.31.125