Now, we can move around with the player on the map, but the camera still points to the starting position. Let’s follow the player with the camera. In this chapter, we attach the camera to the player so that they move together. We also adjust how the shadow camera casts shadows.
Following the Player with the Camera
Attach the Camera to the Player
We attached the camera to the scene in the main file. This way, it has a static position. Instead of that, we want to move it with the player. We could adjust its position at every animation frame just like the player, but it’s easier to add the camera directly to the player to move them together.
Once we attached the camera to the player, some strange things happen. The camera is moving together with the player now, but it’s also turning whenever the player turns, and moving up and down whenever the player jumps. This is not what we want. We want the camera to follow the player, but we want it to stay level and not turn or jump.
Fix the Player Animation
To ensure the camera follows the player but doesn’t turn or jump with it, we wrap the player objects into another group. This new group will be a container that moves horizontally on the map but doesn’t jump or turn. We add the camera to this group. Then, the original group containing the player objects won’t move horizontally anymore but keeps turning and jumping as before.
Let’s adjust the player animation to use this new structure.
if (direction ==="forward") position.currentRow +=1;
if (direction ==="backward") position.currentRow -=1;
if (direction ==="left") position.currentTile -=1;
if (direction ==="right") position.currentTile +=1;
}
In the utility functions of the animatePlayer function, we need to adjust how we set the player’s position and rotation to work with the new structure. When moving the player along the x and y axes, we need to move the outer group, but when the player turns or jumps, we need to adjust the inner group.
These functions receive a reference to the outer group. We set the x and y positions as before. When we set the position or rotation along the z-axis, we set it on the inner group with player.children[0].
src/animatePlayer.ts
28 collapsed lines
import*as THREE from"three";
import {
player,
position,
movesQueue,
stepCompleted,
} from"./components/Player";
import { tileSize } from"./constants";
constmoveClock=newTHREE.Clock(false);
exportfunctionanimatePlayer() {
if (!movesQueue.length) return;
if (!moveClock.running) moveClock.start();
conststepTime=0.2; // Seconds it takes to take a step
As the player moves further away, another strange behavior occurs. At one point, the objects no longer cast shadows.
If we zoom out even more and add a helper box to show the shadow camera’s frustum, we can see that some parts of the game are now outside it. Here, the gray box shows the shadow camera’s frustum and the red rectangle represents its projection to the ground. Drag the scene to see how it works.
Shadows are only calculated within the frustum of the shadow camera, which is statically attached to the directional light. We need to attach the directional light to the player as well.
Add the Directional Light to the Player
We need to attach the directional light to the player to make the shadows follow the player. We can do that in our main file, just like we did it with the camera.
Directional lights shine from their position toward a target. By default, the target is the origin [0, 0, 0]. This was fine when the light was attached to the scene, but now that it’s attached to the player, we also need to adjust the target. Otherwise, the light and shadows will keep changing direction.
Let’s set the directional light’s target in the main file to the player.