Toggle Menu
Home Blog Projects Newsletter

Space defender - part 4 - Adding a HUD

Space defender game & code displayed

In the previous part we created the enemies and shot them down. In this part we'll add a HUD (Heads Up Display) to show the player's lives, level, and score.

Adding a HUD

We're going to add a HUD to the game. This will show the player's lives, level, and score. We'll use a simple HTML structure for this, and some CSS to make it look nice. In bigger games the HUD is usually part of the game canvas, but for this tutorial we'll keep it separate to keep things simple.

In part 1 we already added all the HTML and CSS. So we don't need to do that again. Now we'll just need to update the values in the HUD.

Creating the update function

To do this we'll create a new helper function that we'll use to write out values to the HUD. Add the following code to the bottom of your main.ts file:

function setHudValue(targetId: string, value: number) {
    const target = document.getElementById(targetId);
    if(target) {
        target.innerText = value.toString();
    }
}

This function takes two arguments, the id of the element we want to update and the value we want to set it to. It then finds the element by id and sets the inner text to the value.

Starting values

We also need to set the starting values for the player's lives, level, and score. Add the following code right after where you defined the bullets array:

let lives = 3;
let level = 1;
let score = 0;

setHudValue("gameLives", lives);
setHudValue("gameLevel", level);
setHudValue("gameScore", score);

This code sets the starting values for the player's lives, level, and score. It then updates the HUD with these values.

Updating our lives

Now we'll update the lives value when the player fails to shoot down the enemy and the enemy reaches the bottom of the screen. In our gameloop, where we check if the enemy is off the screen, update the code to look like this:

if(enemy.y > app.screen.height + 50) {
    app.stage.removeChild(enemy);
    enemies.splice(i, 1);
    // New code
    lives--;
    setHudValue("gameLives", lives);
    // End new code
}

And at the end of the gameloop we'll add this piece of code as a placeholder for when we have a proper game over state

if(lives <= 0) {
    console.log("Game Over");
}

Right now the game doesn't actually end when we run out of lives, but we'll fix that in the next part.

Updating the score

We're going to give the player 100 points for every enemy they shoot down. In the part where we check if a bullet hits an enemy, update the code to look like this:

if(
    bullet.x > enemy.x &&
    bullet.x < enemy.x + 50 &&
    bullet.y > enemy.y &&
    bullet.y < enemy.y + 25
) {
    app.stage.removeChild(bullet);
    app.stage.removeChild(enemy);
    bullets.splice(i, 1);
    enemies.splice(j, 1);
    // New code
    score += 90 + (level * 10); // Starts at 100
    setHudValue("gameScore", score);
    // End new code
}

This code will give the player 100 points for every enemy they shoot down. The score is then updated and the HUD is updated with the new score. This also includes a bit of logic that when the level goes up, the player gets more points for shooting down an enemy.

Updating the level

The level goes up every time the player reaches a certain score. The level is also what makes the game harder over time. Add the following code to the end of the gameloop:

// The score requirement gets higher every level
if(score >= (level * 1000) + (level * 100) - 100) {
    level++;
    setHudValue("gameLevel", level);
    setEnemySpawnInterval();
}

The first level requires 1000 points to reach. Every level after that requires 100 more points than the previous level. To make the game actually harder as the levels go up, we'll also call a method called setEnemySpawnInterval that we'll create in a bit.

Find the follow line of code: setInterval(spawnEnemy, enemySpawnInterval); And replace it with this:

function setEnemySpawnInterval() {
    spawnInterval && clearInterval(spawnInterval);
    // Starts at 1 enemy every 2.5 seconds
    spawnInterval = setInterval(spawnEnemy, enemySpawnInterval - (level * 100) + 100);
}
setEnemySpawnInterval();

This code will clear the current interval and set a new one with a shorter interval every time the level goes up. This will make the game harder over time. Because of this the game will be impossible at a certain point as enemies will spawn too fast. But that's okay for this game.

And that's it! You now have a game where you can move left and right, shoot bullets, and shoot down enemies. And you have a HUD that shows the player's lives, level, and score.

In the next part we're going to add some state to the game and make it so that the game actually ends when the player runs out of lives.

Recent articles

Make a simple game using PixiJS and TypeScriptPixiJS setup with Vite and TypeScriptHow Your Coding Skills Can Make a Real Difference in the WorldA guide to writing clean and readable codeAccomplish more with the "Cult of Done"Host your web app for free on Cloudflare PagesFinally got around to making a website for myself