In this recipe, we'll explore jMonkeyEngine's ChaseCamera
class. This camera is a bit different from the previous cameras we've explored since we don't have direct control over its position. It is not like the camera-on-a-stick method we tried in the Creating a reusable character control recipe. While it still follows and looks at the character, it can float around the character more freely and also be controlled by the player.
The default control for the camera is to hold down the left mouse button and drag it to rotate the camera around the character. This is a very common control pattern in third-person games on consoles, where you rotate the camera with the left stick and control the character with the right.
We will implement a behavior where the character moves in the direction the camera is facing rather than the direction the character is facing when you press the forward key. This is common in console games.
Out of convenience, we'll extend, or modify, the GameCharacterControl
class from earlier. This way, we'll get some of the basic functionality and save some time.
To start off, we can create a new SimpleApplication
class in which we'll apply the following steps:
spatial
, to be followed, and the input manager, as follows:ChaseCamera chaseCam = new ChaseCamera(cam, playerNode, inputManager);
ChaseCamera
class has lots of settings to suit different kinds of games. To start off, we turn off the need to hold down the left mouse button to rotate the camera. It's not something we want for this recipe. This is implemented as follows:chaseCam.setDragToRotate(false);
chaseCam.setSmoothMotion(true);
spatial
, which in this case, would be Jaime's feet. We can easily make it look at a higher-up point, such as waist.chaseCam.setLookAtOffset(new Vector3f(0, 1f, 0));
.minDistance
:chaseCam.setDefaultDistance(7f); chaseCam.setMaxDistance(8f); chaseCam.setMinDistance(6f);
ChasingSensitivity
method defines how quickly the camera will follow spatial
. If it's 1
, it will follow slowly and if it's 5
, it will follow quickly. We want the camera to be pretty responsive in this recipe:chaseCam.setChasingSensitivity(5);
RotationSpeed
method defines how quickly the camera moves when moving it:chaseCam.setRotationSpeed(10);
ChaseCamera
. Let's see what we need to do to the GameCharacterControl
class to suit this kind of game.modelForwardDir
and modelLeftDir
in the update
method:Vector3f modelForwardDir = cam.getRotation().mult(Vector3f.UNIT_Z).multLocal(1, 0, 1); Vector3f modelLeftDir = cam.getRotation().mult(Vector3f.UNIT_X);
viewDirection.set(walkDirection);
PhysicsCharacter
as follows:setViewDirection(viewDirection);
The ChaseCamera
class is a convenient class that offloads a lot of camera handling from the coder. It has a lot of settings that can be tweaked to get the desired behavior. Camera tweaking is a delicate and time-consuming matter, and if you're working in a team, this is something a designer might do if the properties would be exposed in a text file and loaded during startup.
If you press forward and then rotate the camera, the character will move in that direction, instead. In many games of this type, however, the character would keep running in the direction it had before the player rotated the camera. We can apply this behavior to our character with a few tweaks.
To do this, we need to change modelForwardDir
and modelLeftDir
into private fields in the class. Then, we make sure we only update these when the character isn't receiving any input from the player. In this recipe, this would mean an if
statement, as follows:
if(!forward && !backward && !leftStrafe && !rightStrafe){ modelForwardDir = cam.getRotation().mult(Vector3f.UNIT_Z).multLocal(1, 0, 1); modelLeftDir = cam.getRotation().mult(Vector3f.UNIT_X); }
3.15.12.34