Making it a game
Updated: Sep 20, 2024
In this chapter, we’ll turn your WebXR experience into a simple game by adding a
proximity-based hit test for the targets and implementing a scoreboard to track
the player’s score. These additions will make your scene more interactive and
engaging, providing immediate feedback when a target is hit.
Setting up the scoreboard
To display the score, we’ll use the troika-three-text
library, which allows us
to render high-quality text in Three.js. The score will be displayed on a
monitor in the space station scene, giving the player a clear view of their
progress.
First, we define the score text and an updateScoreDisplay
function to manage
the scoreboard:
import {Text} from 'troika-three-text';
let score = 0;
const scoreText = new Text();
scoreText.fontSize = 0.52;
scoreText.font = 'assets/SpaceMono-Bold.ttf';
scoreText.position.z = -2;
scoreText.color = 0xffa276;
scoreText.anchorX = 'center';
scoreText.anchorY = 'middle';
function updateScoreDisplay() {
const clampedScore = Math.max(0, Math.min(9999, score));
const displayScore = clampedScore.toString().padStart(4, '0');
scoreText.text = displayScore;
scoreText.sync();
}
- Score text setup: The
Text
object is used to display the score. We
configure its font size, color, and position, ensuring it fits well within the
scene. updateScoreDisplay
function: This function updates the score text
whenever the score changes. It clamps the score between 0 and 9999 and formats
it to be a four-digit number, which is then displayed on the monitor.
Adding the scoreboard to the scene Next, we add the score text to the scene in setupScene
:
function setupScene({scene, camera, renderer, player, controllers}) {
// Other setup code...
// Add the score text to the scene
scene.add(scoreText);
scoreText.position.set(0, 0.67, -1.44);
scoreText.rotateX(-Math.PI / 3.3);
updateScoreDisplay();
}
- Score text positioning: The score text is positioned and rotated to align
with a monitor in the space station scene, making it look like the monitor is
displaying the player’s score. You will need to adjust it if you are using a
different environment.
Implementing proximity-based hit test
To determine whether a bullet hits a target, we use a proximity-based hit test.
This method checks the distance between the bullet and each target, and if
they’re close enough, the target is considered “hit”:
function onFrame() {
// ... unchanged params
Object.values(bullets).forEach(bullet => {
// ... unchanged logic
targets
.filter(target => target.visible)
.forEach(target => {
const distance = target.position.distanceTo(bullet.position);
if (distance < 1) {
delete bullets[bullet.uuid];
scene.remove(bullet);
// make target disappear, and then reappear at a different place after 2 seconds
target.visible = false;
setTimeout(() => {
target.visible = true;
target.position.x = Math.random() * 10 - 5;
target.position.z = -Math.random() * 5 - 5;
}, 2000);
score += 10; // Update the score when a target is hit
updateScoreDisplay(); // Update the rendered troika-three-text object
}
});
});
}
- Proximity-based hit test: This method checks if the distance between the
bullet and a target is less than 1 unit. If it is, the bullet is removed from
the scene, and the target is temporarily hidden.
- Updating the score: Each time a target is hit, the score is increased by
10 points, and the
updateScoreDisplay
function is called to refresh the
displayed score. Respawning targets: After 2 seconds, the target becomes visible again and
is repositioned randomly within the scene.
- Why proximity-based?: This approach is simple and effective for our
scenario because the targets are round and facing the player. However, for
more advanced and reliable hit detection, especially with irregularly shaped
objects or targets that aren’t facing the player, you would need to look into
using raycasting.
In this chapter, you’ve transformed your WebXR scene into a simple game by
adding hit detection and a scoreboard. The proximity-based hit test provides a
straightforward way to register hits, while the scoreboard keeps track of the
player’s score, making the game more engaging and interactive.
Here’s what your game looks like now: