DEV Community

Cover image for Space Defender - part 3 - the enemies
Mr. Linxed
Mr. Linxed

Posted on • Updated on • Originally published at mrlinxed.com

Space Defender - part 3 - the enemies

In the last part we created the player's ship and made it move. In this part we'll create the enemies and make them move. And then we'll shoot them down!

Creating the enemies

We're going to do something similar as when we created the bullets. We're going to create a template enemy that we'll clone every time we want to create a new enemy. We also need to keep track of the enemies via an array because there can be more than one at the same time.

But first, we'll create the method that creates the enemy. Add the following code after the createBullet method:

let enemyTemplate: PIXI.Graphics | undefined = undefined;
function createEnemy() {
    if(!enemyTemplate) {
        enemyTemplate = new Graphics();
        enemyTemplate
            .poly([
                0, 0,
                50, 0,
                25, 25,
            ])
            .fill(0xFF6666);
    }

    const enemy = enemyTemplate.clone();
    enemy.x = 25 + (Math.random() * 480) - 50;
    enemy.y = -50;

    return enemy;
}
Enter fullscreen mode Exit fullscreen mode

As you can see, it's pretty similar to the createBullet method. We create a template enemy that we clone every time we want to create a new enemy. We then position the enemy at a random x position at the top of the screen. The enemy has the same shape as the player's ship, but it's red and upside down.

We specify the spawn location of the enemy by setting the x and y properties. The x property is set to a random value between 25 and 480 - 50, so that the enemy is always within the game screen. The y property is set to -50, so that the enemy is just outside the screen, and will move into it.

Next up, we need to call this method to create a new enemy every few seconds.

Spawning enemies

We'll use the setInterval method for this. Add the following code right after where we defined the bullets array:

const enemies: PIXI.Graphics[] = [];

const enemySpawnInterval = 2500;
function spawnEnemy() {
    if(!document.hasFocus()) {
        return;
    }
    const enemy = createEnemy();
    enemies.push(enemy);
    app.stage.addChild(enemy);
}

setInterval(spawnEnemy, enemySpawnInterval);
spawnEnemy();
Enter fullscreen mode Exit fullscreen mode

We create a new array called enemies to keep track of all the enemies. We then create a new variable called enemySpawnInterval that specifies how often we want to spawn a new enemy. We then create a new method called spawnEnemy that creates a new enemy and adds it to the enemies array and the stage. We then call this method every enemySpawnInterval milliseconds using the setInterval method.

Cool, now we have enemies spawning at the top of the screen every 2.5 seconds. But they're not moving yet, and we don't see them because they're out of the screen. Let's fix that.

Moving the enemies

We need to update the enemies' position in the game loop. Add the following code to your game loop, right under where we update the bullets' position:

for(let i = 0; i < enemies.length; i++) {
    const enemy = enemies[i];
    enemy.y += 2.5;

    if(enemy.y > app.screen.height + 50) {
        app.stage.removeChild(enemy);
        enemies.splice(i, 1);
    }
}
Enter fullscreen mode Exit fullscreen mode

This part of the code will loop over all the enemies, update their position by moving them down 2.5 pixels and check if they are out of bounds. If they are, we remove them from the stage and the enemies array.

Nice! if you run your game now you'll see enemies spawning at the top of the screen and moving down.

Now it's time to shoot them down!

Shooting the enemies

Add the following code to your game loop, right under where we update the enemies position:

for(let i = 0; i < bullets.length; i++) {
    const bullet = bullets[i];
    for(let j = 0; j < enemies.length; j++) {
        const enemy = enemies[j];
        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);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

This part of the code will loop over all the bullets and all the enemies and check if a bullet hits an enemy. If it does, we remove both the bullet and the enemy from the stage and their respective arrays.

You could optimize this code by breaking out of the inner loop when a bullet hits an enemy, but for now, this is fine. You could also combine the bullet position update loop with the bullet hit check loop, but I like to keep them separate for clarity of this tutorial.

And that's it! You now have a game where you can move left and right, shoot bullets, and shoot down enemies. In the next part, we're going to add some HUD elements to the game and keep track of the player's score, level and lives.



Don't forget to sign up to my newsletter to be the first to know about tutorials similar to these.

Top comments (0)