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
}
});
});
}
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: