官术网_书友最值得收藏!

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.

主站蜘蛛池模板: 岳普湖县| 监利县| 顺平县| 岑巩县| 河北省| 红桥区| 新昌县| 金寨县| 岳普湖县| 同德县| 贞丰县| 阿瓦提县| 江川县| 工布江达县| 绥棱县| 永安市| 庆城县| 贡嘎县| 宁晋县| 锦屏县| 宜黄县| 阆中市| 遂昌县| 奉贤区| 沁阳市| 奈曼旗| 定日县| 三门峡市| 正安县| 叶城县| 正镶白旗| 北流市| 曲靖市| 共和县| 利辛县| 池州市| 潢川县| 睢宁县| 肃南| 宣威市| 岳阳县|