Build a Space Shooter with Phaser 3 – 4

by | Feb 8, 2019 | Build a Space Shooter with Phaser 3 | 43 comments

In the last part of “Build a Space Shooter with Phaser 3”, we finished writing our base Entity class, our player class, and the player movement. In this part we will implement a couple enemies and give them basic AI. At this point you should have an error-free game where you can move the player around via the W, S, A, D keys. If so, it’s time to open Entities.js back up.

At the bottom of Entities.js under the Player class, add three new classes called ChaserShip, GunShip, and CarrierShip:

class ChaserShip extends Entity {
  constructor(scene, x, y) {
    super(scene, x, y, "sprEnemy1", "ChaserShip");
  }
}

class GunShip extends Entity {
  constructor(scene, x, y) {
    super(scene, x, y, "sprEnemy0", "GunShip");
    this.play("sprEnemy0");
  }
}

class CarrierShip extends Entity {
  constructor(scene, x, y) {
    super(scene, x, y, "sprEnemy2", "CarrierShip");
    this.play("sprEnemy2");
  }
}

Classes ChaserShip, GunShip, and CarrierShip should extend the Entity class that we have created in the last part. Then we effectively call the constructor of Entity with provide the corresponding parameters. We will be able to build on top of the Entity class and in a second build our simple AI for each enemy. For each enemy class, under the super keyword, add the following:

this.body.velocity.y = Phaser.Math.Between(50, 100);

The above line sets the y velocity of the enemy to be a random integer between 50 and 100. We will be spawning the enemies past the top of the screen, which will cause the enemy to move down the canvas.

Next, go back to SceneMain.js. We will need to create a Group to hold our enemies, the lasers shot by enemies, and the lasers shot by the player. In the create function after the line setting this.keySpace, add:

this.enemies = this.add.group();
this.enemyLasers = this.add.group();
this.playerLasers = this.add.group();

There still won’t be any enemies spawning from the top of the screen yet if we run our game. We first have to create an event (it will act as a timer) which will spawn our enemies. After our playerLasers group, add the following code:

this.time.addEvent({
  delay: 100,
  callback: function() {
    var enemy = new GunShip(
      this,
      Phaser.Math.Between(0, this.game.config.width),
      0
    );
    this.enemies.add(enemy);
  },
  callbackScope: this,
  loop: true
});

If we try running the game now, we should see many GunShip enemies moving down from the top of the screen. Now, we will give our GunShip enemies the ability to shoot. First, we have to create another class called EnemyLaser right after the Player class of our Entities.js file. EnemyLaser should extend Entity as well.

class EnemyLaser extends Entity {
  constructor(scene, x, y) {
    super(scene, x, y, "sprLaserEnemy0");
    this.body.velocity.y = 200;
  }
}

Now we can go back to our GunShip class, specifically the constructor. Under where we set the y velocity, we can add a new event.

this.shootTimer = this.scene.time.addEvent({
  delay: 1000,
  callback: function() {
    var laser = new EnemyLaser(
      this.scene,
      this.x,
      this.y
    );
    laser.setScale(this.scaleX);
    this.scene.enemyLasers.add(laser);
  },
  callbackScope: this,
  loop: true
});

Do note that we are assigning the above event to a variable called this.shootTimer. We should create a new function inside GunShip called onDestroy. onDestroy is not a function used by Phaser, but you can call it anything. We will be using this function to destroy the shoot timer when the enemy is destroyed. Add the onDestroy function to our GunShip class and add the following inside:

  if (this.shootTimer !== undefined) {
    if (this.shootTimer) {
      this.shootTimer.remove(false);
    }
  }

When you run the game you should see:

You should now see something like this if you run the game. That’s a lot of enemies!


When we run the game, you should see the army of gun ship enemies coming down from the top of the screen. All of the enemies should also be shooting lasers as well. Now that we see everything is working, we can cut back the amount of gun ships are being spawned at once. To do this, navigate to our SceneMain.js file and change the delay of the timer we made.

    this.time.addEvent({
      delay: 1000, // this can be changed to a higher value like 1000
      callback: function() {
        var enemy = new GunShip(
          this,
          Phaser.Math.Between(0, this.game.config.width),
          0
        );
        this.enemies.add(enemy);
      },
      callbackScope: this,
      loop: true
    });
That’s better!

Back in Entities.js, we will need to add a little bit of code to the constructor of the ChaserShip class:

this.states = {
  MOVE_DOWN: "MOVE_DOWN",
  CHASE: "CHASE"
};
this.state = this.states.MOVE_DOWN;

This code does two things: create an object that has two properties which we can use to set the state of the chaser ship, and then we set the state to the value of the MOVE_DOWN property (the value is the string "MOVE_DOWN".)

We can now add an update function to the ChaserShip class. The update function is where we will code in the AI for the ChaserShip class. We will code the intelligence for the ChaserShip enemy first, since it’s slightly more complicated. Navigate back to Entities.js and in the update function of the ChaserShip class, add the following:

    if (!this.getData("isDead") && this.scene.player) {
      if (Phaser.Math.Distance.Between(
        this.x,
        this.y,
        this.scene.player.x,
        this.scene.player.y
      ) < 320) {

        this.state = this.states.CHASE;
      }

      if (this.state == this.states.CHASE) {
        var dx = this.scene.player.x - this.x;
        var dy = this.scene.player.y - this.y;

        var angle = Math.atan2(dy, dx);

        var speed = 100;
        this.body.setVelocity(
          Math.cos(angle) * speed,
          Math.sin(angle) * speed
        );
      }
    }

With this code, chaser enemies will move down the screen. However, as soon as it is within 320 pixels to the player, it will start chasing the player. If you want the chaser ship to rotate, feel free to add the following right after (or at the end of) our chase condition:

if (this.x < this.scene.player.x) {
  this.angle -= 5;
}
else {
  this.angle += 5;
} 

In order to spawn the chaser ship, we will have to go back to SceneMain.js and add a new function called getEnemiesByType. Inside this new function add:

getEnemiesByType(type) {
  var arr = [];
  for (var i = 0; i < this.enemies.getChildren().length; i++) {
    var enemy = this.enemies.getChildren()[i];
    if (enemy.getData("type") == type) {
      arr.push(enemy);
    }
  }
  return arr;
}

The above code will allow us to provide an enemy type and get all the enemies in the enemies group. This code loops through the enemies group and checks if the type of the enemy in the loop is equal to the type that is given as a parameter.

Once we added the getEnemiesByType function, we will need to modify our spawner event. Within the anonymous function of the callback property let’s change:

    var enemy = new GunShip(
      this,
      Phaser.Math.Between(0, this.game.config.width),
      0
    );
    this.enemies.add(enemy);

to:

    var enemy = null;

    if (Phaser.Math.Between(0, 10) >= 3) {
      enemy = new GunShip(
        this,
        Phaser.Math.Between(0, this.game.config.width),
        0
      );
    }
    else if (Phaser.Math.Between(0, 10) >= 5) {
      if (this.getEnemiesByType("ChaserShip").length < 5) {

        enemy = new ChaserShip(
          this,
          Phaser.Math.Between(0, this.game.config.width),
          0
        );
      }
    }
    else {
      enemy = new CarrierShip(
        this,
        Phaser.Math.Between(0, this.game.config.width),
        0
      );
    }

    if (enemy !== null) {
      enemy.setScale(Phaser.Math.Between(10, 20) * 0.1);
      this.enemies.add(enemy);
    }

Going through this block, we add a condition that picks one of our three enemy classes: GunShip, ChaserShip, or CarrierShip to be spawned. After setting the enemy variable to either enemy class, we then add it to the enemies group. If a ChaserShip is picked to be spawned, we check to ensure there are not more than five ChaserShips before spawning another. Before we add an enemy to the group, we also apply a random scale to the enemy. Since each enemy extends our Entity class, which in turn extends Phaser.GameObjects.Sprite, we can set a scale to enemies, just as we can to any other Phaser.GameObjects.Sprite.

In the update function, we need to update enemies in the this.enemies group. To do so, add the following at the end of the update function.

    for (var i = 0; i < this.enemies.getChildren().length; i++) {
      var enemy = this.enemies.getChildren()[i];

      enemy.update();
    }

If we try running the game now, we should see that chaser ships should be moving towards the player ship once they get within distance.

Last, we will finish up this part by giving the player the ability to shoot. Navigate back to the Player class and in the constructor add:

this.setData("isShooting", false);
this.setData("timerShootDelay", 10);
this.setData("timerShootTick", this.getData("timerShootDelay") - 1);

We are setting up what I would call, a “manual timer”. We are not using events for the shooting ability of the player. This is because, we do not want a delay to shoot when initially pressing the space key. In the update function of the Player, we will add the rest of the logic for our “manual timer”:

if (this.getData("isShooting")) {
  if (this.getData("timerShootTick") < this.getData("timerShootDelay")) {
    this.setData("timerShootTick", this.getData("timerShootTick") + 1); // every game update, increase timerShootTick by one until we reach the value of timerShootDelay
  }
  else { // when the "manual timer" is triggered:
    var laser = new PlayerLaser(this.scene, this.x, this.y);
    this.scene.playerLasers.add(laser);
  
    this.scene.sfx.laser.play(); // play the laser sound effect
    this.setData("timerShootTick", 0);
  }
}

The only thing left we have to do is add the PlayerLaser class to our Entities.js file. We can add this class right under the Player class and before the EnemyLaser class. This will keep our player related classes together, and our enemy related classes together. Create a constructor inside the PlayerLaser class and add the same code to the constructor as we did with the EnemyLaser class. Then, remove the negate sign from where we set the y velocity value. This will cause player lasers to move up instead of down. The PlayerLaser class should now look like:

class PlayerLaser extends Entity {
  constructor(scene, x, y) {
    super(scene, x, y, "sprLaserPlayer");
    this.body.velocity.y = -200;
  }
}

The last thing we need to do to allow the player to shoot is go back to SceneMain.js and add the following condition under our movement code:

if (this.keySpace.isDown) {
  this.player.setData("isShooting", true);
}
else {
  this.player.setData("timerShootTick", this.player.getData("timerShootDelay") - 1);
  this.player.setData("isShooting", false);
}
Nice! We can shoot lasers and there’s a slight delay when shooting as well.

We are finished with adding the ability to shoot lasers for both the player and enemies! Before we move on to collisions, it will be a good idea to add what is called frustum culling. Frustum culling will allow us to remove everything that moves off screen, which frees up processing power and memory. Without frustum culling, if we let our game run for a while, it will look like this:

Yeah… it’s lagging pretty badly.

In order to add frustum culling, we will have to move to the update function of SceneMain. Currently, we should have a for loop where we update enemies. Inside the for after the ending curly brace where we update the enemy, add the following code:

if (enemy.x < -enemy.displayWidth ||
    enemy.x > this.game.config.width + enemy.displayWidth ||
    enemy.y < -enemy.displayHeight * 4 ||
    enemy.y > this.game.config.height + enemy.displayHeight) {

    if (enemy) {
      if (enemy.onDestroy !== undefined) {
        enemy.onDestroy();
      }

      enemy.destroy();
    }

}

We can also add the same for enemy lasers and player lasers:

    for (var i = 0; i < this.enemyLasers.getChildren().length; i++) {
      var laser = this.enemyLasers.getChildren()[i];
      laser.update();

      if (laser.x < -laser.displayWidth ||
        laser.x > this.game.config.width + laser.displayWidth ||
        laser.y < -laser.displayHeight * 4 ||
        laser.y > this.game.config.height + laser.displayHeight) {
        if (laser) {
          laser.destroy();
        }
      }
    }

    for (var i = 0; i < this.playerLasers.getChildren().length; i++) {
      var laser = this.playerLasers.getChildren()[i];
      laser.update();

      if (laser.x < -laser.displayWidth ||
        laser.x > this.game.config.width + laser.displayWidth ||
        laser.y < -laser.displayHeight * 4 ||
        laser.y > this.game.config.height + laser.displayHeight) {
        if (laser) {
          laser.destroy();
        }
      }
    }

To add collisions, we will navigate to our SceneMain.js and at a look at our create function. We will need to add what’s called a collider below our enemy spawn event. Colliders allow you to add a collision check between two game objects. So, if there’s a collision between the two objects, the callback you specified will be called and you will receive the two instances that have collided as parameters. We can create a collider between this.playerLasers and this.enemies. In code, we would write this as:

this.physics.add.collider(this.playerLasers, this.enemies, function(playerLaser, enemy) {
  
});

If we wanted to have the enemy destroyed upon being hit by a player laser, we can write inside the anonymous function:

if (enemy) {
  if (enemy.onDestroy !== undefined) {
    enemy.onDestroy();
  }

  enemy.explode(true);
  playerLaser.destroy();
}

The above code checks if the enemy is still active (and not destroyed), and then destroys it if true.

If we run the game, we should see that instances in the this.enemies group are able to destroy enemies. The next step is to add a collider between this.player and this.enemies:

this.physics.add.overlap(this.player, this.enemies, function(player, enemy) {
  if (!player.getData("isDead") &&
      !enemy.getData("isDead")) {
    player.explode(false);
    enemy.explode(true);
  }
});

We can also add a collider between this.player and this.enemyLasers. By essentially copying the code from above, we can accomplish the same effect, but instead with the enemy lasers.

this.physics.add.overlap(this.player, this.enemyLasers, function(player, laser) {
  if (!player.getData("isDead") &&
      !laser.getData("isDead")) {
    player.explode(false);
    laser.destroy();
  }
});

If we run this, we will get an error that explode is not a function. No worries though, we can just head back to Entities.js and take a look at the Entity class. In the Entity class, we need to add a new function called explode. We will be taking in canDestroy as the sole parameter of this new function. The canDestroy parameter determines whether when explode is called, if the entity will be destroyed, or just be set invisible. Inside the explode function we can add:

    if (!this.getData("isDead")) {
      // Set the texture to the explosion image, then play the animation
      this.setTexture("sprExplosion");  // this refers to the same animation key we used when we added this.anims.create previously
      this.play("sprExplosion"); // play the animation

      // pick a random explosion sound within the array we defined in this.sfx in SceneMain
      this.scene.sfx.explosions[Phaser.Math.Between(0, this.scene.sfx.explosions.length - 1)].play();

      if (this.shootTimer !== undefined) {
        if (this.shootTimer) {
          this.shootTimer.remove(false);
        }
      }

      this.setAngle(0);
      this.body.setVelocity(0, 0);

      this.on('animationcomplete', function() {

        if (canDestroy) {
          this.destroy();
        }
        else {
          this.setVisible(false);
        }

      }, this);

      this.setData("isDead", true);
    }

If we run the game, you may notice that the player can still move around and shoot, even if the player ship explodes. We can fix this by adding a check around the player update call and the movement and shooting calls in SceneMain. The ending result should appear as:

if (!this.player.getData("isDead")) {
  this.player.update();
  if (this.keyW.isDown) {
    this.player.moveUp();
  }
  else if (this.keyS.isDown) {
    this.player.moveDown();
  }
  if (this.keyA.isDown) {
    this.player.moveLeft();
  }
  else if (this.keyD.isDown) {
    this.player.moveRight();
  }

  if (this.keySpace.isDown) {
    this.player.setData("isShooting", true);
  }
  else {
    this.player.setData("timerShootTick", this.player.getData("timerShootDelay") - 1);
    this.player.setData("isShooting", false);
  }
}

We have accomplished the “meat and potatoes” of this course in this part. We have added enemies, player lasers, enemy lasers, frustum culling, and collisions. In the next part I will be covering how to add a scrolling background, create the main menu, and the game over screen. I hope you have found this course fruitful so far as much as I have. Please don’t hesitate to ask questions, I’m glad to help! If you would like to receive updates on future courses I release, please feel free to fill out the form.

43 Comments

  1. Ernst Nolte

    Hi, thanks for this tutorial.
    Maybe I missed something, but I cannot find where you define a explode functions on enemy and player and javascript complains that these are not functions. Can you tell me what I missed?

    Thanks

    Reply
    • Jared York

      Hi Ernst! Thanks for checking out my course. Right near the end of this part I mention adding the explode function to the Entity class. The relevant code that belongs in the function is right below that. Please let me know if you have any more questions. I hope this helps.

      Reply
      • Ernst Nolte

        Thanks – I found it – my bad. Almost completed the whole tutorial!

        Reply
        • Jared York

          Cool! I’m glad it’s going well for you.

          Reply
  2. Matt

    Hey Jared,

    This is a great tutorial that I found after I had started creating my own space shooter. I am stuck though. How would I assign health to each individual spawned enemy? Right now, i want it to take 2 lasers to kill each enemy. The problem is, the way it’s working is that when the the timer calls the function to spawn a new enemy, the health resets to 2.

    Reply
    • Jared York

      Hi Matt! First, thank you for checking out my tutorial! It really means a lot to me that it’s beneficial for people. As for your question, you can add an hp property to each of the enemy classes: ChaserShip, GunShip, CarrierShip, etc. In the collider between player lasers and enemies, remove everything inside and add the following:

      if (enemy) {
        if (enemy.hp – (HP AMOUNT TO TAKE) > 0) {
          enemy.hp -= (HP AMOUNT TO TAKE);
        }
        else {
          if (enemy.onDestroy !== undefined) {
            enemy.onDestroy();
          }

          enemy.explode(true);
        }
        playerLaser.destroy();
      }

      Really, it’s a fairly simple condition checking if the enemy would explode taking the hit, if not, decrease the value of the enemy’s HP property. If the enemy would explode taking the hit, we just destroy it as before. Thanks for the question! Hope this helps.

      Reply
  3. Jovan Cahiles

    Hey there, first thank you for creating this great tutorial!

    Anyway, I have an issue right now with the destroy stuff. I added the code that you wrote which destroys the enemies once they are off-screen, but I keep getting an error once an enemy does go offscreen: \”Uncaught TypeError: Cannot read property \’sys\’ of undefined at EnemyLaser.GameObject…\”

    Not sure if I missed something or I did something wrong.

    Reply
    • Jared York

      Hi Jovan! Thanks for checking out my tutorial, and I appreciate the kind words! From first glance it’s hard for me to guess what might be causing that error. Would you mind sending my a ZIP file containing your project? I would be happy to take a look at it.

      Reply
      • Jovan Cahiles

        Hey, thanks for replying. Sure, how do I send it to you?

        Reply
        • Jared York

          I use Mediafire or Dropbox personally. Once you upload it, just send me the link to the download. Let me know if you need help zipping it up. 🙂

          Reply
  4. Jovan Cahiles

    Hey there, thanks for the reply and help. I figured out what was wrong with my code. I was missing the part where the spawn for the enemy laser is remove. I added it on the onDestroy function already and the code worked like a charm. Thanks for being responsive!

    Reply
  5. Harmeet Singh

    I tried following the tutorial, but I get this error when trying to destroy enemies if they go out of bounds: –

    Uncaught TypeError: Cannot read property ‘sys’ of undefined
    at EnemyLaser.GameObject [as constructor] (phaser.js:3391)
    at new Sprite (phaser.js:11882)
    at new Entity (Entities.js:4)
    at new EnemyLaser (Entities.js:137)
    at GunShip.callback (Entities.js:111)
    at Clock.update (phaser.js:110737)
    at EventEmitter.emit (phaser.js:2357)
    at Systems.step (phaser.js:41029)
    at SceneManager.update (phaser.js:81023)
    at Game.step (phaser.js:152466)

    Reply
    • tianyagulvke

      the function ‘onDestroy’ should be in class GunShip not class EnemyLaser

      Reply
  6. Edward Thomas

    Hi. I followed the tutorial step by step (I hope) to page 3-4, but I’m having a problem now. The game is working until the player’s ship collides with the enemy laser, then it freezes. I’ve been over the code several times, but I don’t see the bug. Any advice?

    Reply
    • Jared York

      Hi Edward,

      Thanks for reaching out to me! Would you mind emailing a ZIP file containing your project to me? I would be more than happy to take a look at it. My email address is jared.york@jaredyork.com.

      Reply
      • Edward Thomas

        Thanks for the reply. I’ll send my project tonight.

        Reply
        • Jared York

          Okay, so I ran the project with both Chrome and Firefox and the following error was displayed:

          player.onDestroy is not a function

          In the Player class, I noticed you didn’t define the onDestroy function. You can find the directions for adding this function near the bottom of part five (available here). After adding the onDestroy function to your Player class, everything seemed to be running well again. Hope this helps.

          Reply
          • Edward Thomas

            Yes, that did solve the problem. Thank you very much!

  7. Brian

    Hey Jared. Thanks for the tutorial. I seem to have run into an error though. Perhaps I’m just missing something. But I added the getEnemiesByType() function at the bottom of my level which I’ve titled SceneMain.js beneath the Update() function and I’m getting an error in the browser that says…

    “Uncaught TypeError: enemy.getData is not a function”

    It’s throwing an error for this line…

    var enemy = this.enemies.getChildren()[i];
    if ( enemy.getData( ‘type’ ) == type )
    {
    array.push( enemy );
    }

    Is there something I missed or am I placing the getEnemiesByType (‘type’) function in the wrong place?

    Reply
    • Jared York

      Hi Brian, I’m glad you like the tutorial. Do you have the following line for your for loop inside getEnemiesByType?

      for (var i = 0; i < this.enemies.getChildren().length; i++) { Please let me know if this helps.

      Reply
  8. Brian

    Yes. I just didn’t want to put the entire code in there but I copied it line by line from the tutorial..

    getEnemiesByType( type )
    {
    var array = [];
    for ( var i = 0; i < this.enemies.getChildren().length; i++ )
    {
    var enemy = this.enemies.getChildren()[i];
    if ( enemy.getData( 'type' ) == type )
    {
    array.push( enemy );
    }
    }
    return array;
    }

    I can push my code to Github if you want and maybe you can see where I've made my mistake

    Reply
    • Jared York

      Pushing the code to GitHub would be a great help. I don’t see anything obvious here that would cause this issue. Please let me know the link when you push it.

      Reply
  9. Brian

    https://github.com/blewis101/space-shooter-dapp/blob/master/js/scenes/sceneMain.js

    Thanks for all the help. I was following someone else\\\’s PhaserJS tutorial on Udemy, so there\\\’s a lot of extra stuff there, but if you comment out lines 176-188 it runs perfectly fine without errors. I get enemies that spawn and shoot lasers (no collision detection set up yet).

    It\\\’s when I try to add in lines 176-188 that I get an error message and honestly that\\\’s just one error. If you notice, I have line 172 commented out too because that was throwing an error as well. It looks like a recursive update function within update. I wasn\\\’t sure about that either so if I comment out line 172 with lines 176-188 also commented out…I have no problems.

    However, my ships don\\\’t follow the playerShip the way your tutorial shows and it\\\’s also not spawning various enemies like it should. This might also help…

    I split up the different classes into their own respective file instead of having every class in one file. I don\\\’t think that\\\’s what\\\’s causing my issue though but I could be wrong.

    enemy.js and chaser.js are the two files I\\\’ve done most of the work on.

    Reply
    • Jared York

      Hi Brian, Thanks for sending the link. I will try to take a look at it within the next day or so.

      Reply
    • Jared York

      Hi Brian,

      I took a look at your code. The first problem I noticed is when you added your this.enemies group, you put ‘bombers’ and ‘chasers’ as parameters when adding the group. These are not accepted arguments when adding a group. See this page of the Phaser 3 documentation: https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.Group.html

      Also it looks like you’re referencing the ‘bomber’ texture key instead of the animation key. I think you intended to use ‘badfly2’? I haven’t checked for any other problems beyond this. Hopefully this helps, let me know if you have further questions.

      Reply
  10. Brian

    Wow thanks that did it! I added a few other things as well. Now the only thing I need to do to be back on track is to actually get the chaserShip to chase my playerShip. I did it slightly different from your tutorial as I was following another. I\’ve updated Github and all of the ships now drop and shoot. I think the issue is with the way I\’ve tried to change the code in the chaser.js file

    https://github.com/blewis101/space-shooter-dapp/blob/master/js/entities/chaser.js

    I tried to rewrite it this.scene.playerShip because playerShip is what I called it in sceneMain. But I should probably change that because I should have a class specifically for the playerShip. I\’ll try to figure out a proper way to do it.

    https://github.com/blewis101/space-shooter-dapp/blob/master/js/scenes/sceneMain.js

    Reply
  11. Marc Holman

    Hi,

    First, thank you for the excellent tutorial. It just so happened to be EXACTLY what I had been searching for and will help me to complete my own game. I hope you create more in the future – the quality is superb.

    I have a question about the code. In SceneMain we loop through all the children of the enemies group and call .update() on each one. However (at least at this point), only ChaserShip actually has an update method.

    So why does the code work? Why don’t we get an error something like ‘someenemytype.update is not a function’?

    Reply
    • Jared York

      Hi Marc,
      I’m glad you enjoyed the tutorial! It’s always good to know that people appreciate the work that goes into these, so thanks for that. I will try to give you a detailed response within the next few days and answer all of your questions.

      Reply
  12. Marc Holman

    I see there is an update method built into Phaser.GameObject.Sprite but the documentation says this isn’t typically called directly. Is this the method called for those enemy entities for whom we have not specified an update method?

    Reply
  13. Marc Holman

    I also noticed this with respect to the laser classes – update is called but never specified in our code. What is actually happening here?

    Reply
  14. Mike S

    Hi – Thanks for the great tutorial. I am running into an error within the Gunship constructor (in Entities.js file).

    Specifically it crashes after a few moments with an error of “TypeError: scene is undefined” tracing through “GameObject -> Sprite -> Entity -> EnemyLaser -> GunShip/this.shootTimer Clock emit -> Systems SceneManager Game bound self-hosted:920:17 -> TimeStep bound self-hosted:916:17 -> step” (in FF) and similarly but identified as “Uncaught TypeError: Cannot read property ‘sys’ of undefined” – but same trace back (in Chrome).

    I figure I’ve typed something wrong within the Gunship Constructor area related to this.shootTimer = this.scene.time.addEvent …. but I can’t seem to spot the error or the difference between my code and your tutorial.

    Reply
    • jared

      Hi Mike,

      Thanks for reaching out to me. Sorry you’re having trouble with the code. Do you think you could upload your project and send it to me? Even though you sent me a stack trace, there could be other factors contributing to your error.

      Thanks!
      Jared

      Reply
      • jared

        I’ll take a look at it (hopefully today sometime). Thanks for sending the ZIP.

        Reply
      • jared

        So I took a look a hard look at your project, and it turns out that you just have a typo with the method onDestroy of class GunShip. Change ondestroy to onDestroy in your method declaration. That should fix it. Hope that helps!

        Reply
      • Mike S

        Thanks – That did it… I will do some more digging around on my own… but my ‘Chaser’ ships don’t chase… they just truck along as though my space ship is in ‘stealth’ mode LOL…

        But thanks again!! =D

        Reply
        • jared

          Haha! Definitely reach out to me if you need help getting your chaser ships to chase. Having a stealth mode would be pretty cool though; I have to admit. I’m always happy to help, glad you got the main issue resolved. 🙂

          Reply
  15. Aala

    Hi Jared first of all, I really like your tutorial. I was just wondering how would I make the enemy laser go when the player hits the enemy. I have tried a couple of different ways but to no avail. When my bullet hits the enemy that does not shoot I don’t get an error but when I shoot the GunShip it gives me an error?

    Thank you

    Reply
    • jared

      Hi Aala,

      I’m happy to hear you like my tutorial. Could you clarify what you mean by “how would I make the enemy laser go when the player hits the enemy”? Regarding the shooting problems, could you please upload a ZIP file of your game so I can take a look at it?

      Reply
  16. Aala

    Hi, thanks for replying.

    So basically I added a collider and made a function for the player to shoot the enemy and then for the enemy to disappear however when I shoot the enemy that has lasers it comes back with an error so I am assuming the laser of the enemies is the problem it needs to go? When the enemy dies you can still see it’s laser going down and then the game stops due to errors.

    I hope the comments help.
    Here is the link: http://www.mediafire.com/file/unpct81xvi1vrlj/intothedark.zip/file

    thanks again

    Reply
    • jared

      Hi Aala,

      Sorry it’s taking so long, I hope to have a chance to look at your project later today.

      Reply
    • jared

      Hi Aala,

      There’s not really a single problem I can pinpoint in regards to the issue you’re having. Most likely there’s a variety of issues in the code that may be causing this problem.

      Here are several pointers I can give you from looking through your code:
      – Remove the = signs in your script tags in the index.html file
      – Rename scene2.js to Scene2.js in your game files, this prevents the game from loading.
      – Change the super(““) to super({ key: “” }) in both of your scenes.
      – Remove setTimeout calls and instead use this.time.addEvent()
      – There are several occurances of the += operator being typed as +=, this is problematic.
      – I would suggest that you properly indent your code to make it more readable.

      Hopefully these tips help. It’s difficult for me to find issues in your project if many of your functions are renamed from those I wrote in the tutorial. However, some of these points should help you get back in the right direction.

      Please let me know you have further questions and I’ll try to get you in the right direction.

      Kind regards,
      Jared

      Reply

Submit a Comment

Your email address will not be published. Required fields are marked *

Subscribe To Our Newsletter

Subscribe To Our Newsletter

Join our mailing list to receive the latest news regarding tutorials and courses we publish!

Please check your inbox to confirm your subscription.

Share This