Phaser: Making and using a generic Enemy class (ES6/ES2015)

The Metroid HTML5 remake is written in ES6/ES2015 and transpiled to ES5. It’s less advanced than it might sound, especially when you can find boilerplates with task/build runners on Github doing all the work for you so that you can focus on your project. I’m using this excellent Phaser ES6 Boilerplate but there are a few to choose between. It comes with a Gulp-script that will listen to changes and build transpiled and concated versions of your code while working, plus serve it in a local server.

This is my first tutorial. If it’s appreciated I will add more posts on different topics I think of while working on my Metroid remake. First up is how I decided code the enemies by creating a generic enemy class that extends Phaser.Sprite, and then add actual enemies as extensions of that class. This approach allows me to reuse code and to add new enemy types with limited effort focusing only on their uniqueness. I don’t want to clutter this page with full-length code from the game, but rather explain with stripped down and altered versions of the code. This is a tutorial focusing the topic in the tile, not on JavaScript (ES6/ES2015 or not) per se.

1. The generic enemy class

The generic enemy class extends Phaser.Sprite which means it inherits all the properties and methods sprites has and build on that. Native functions accepting a Phaser.Sprite as an argument will also except our Enemy class (such as physics tests). I put everything that’s not specific to a particular enemy type in this class, like what to do when being shot and behavior while being frozen.

2. Making an enemy type: Ripper

Yellow rippers in-game (the creatures without spikes)

Yellow rippers in-game (the creatures without spikes). Image borrowed from here.

Next step is to actually create an enemy. This is a ripper, a brainless creature that flies in a horizontal line changing direction when reaching a wall. There is two types, red and yellow. Both is immune to normal weapons, but the red one can be killed with a missile or screw attack. The ripper class extends the Enemy class we just made. If we wanted we could override anything in the Enemy class, like a custom hit-method or allowing gravity on the body. For the Rippers this is all we need though:

3. Adding Rippers into the game

To add a Ripper to the game you need to first create a ripper and then spawn it. You could skip the spawn-part and just add everything in the constructor. This approach makes it easy to create and add Rippers to a group (pool), and then reusing the Rippers by spawning those with “alive” property set to false. I’ll look into groups further in the next tutorial. The following code should be in the create method of a state.

4. Interacting with the Rippers

A bullet (in the bulletGroup) hit a Ripper (in the ripperGroup). Possible damage depending on Ripper color and bullet.type. The code could be in the state update method.

Samus collide with a Ripper and get hurt. This code could be in Samus own update method.

5. Bonus: Zeb

I thought I would describe my approach to Zebs to give some thoughts on overrides and how the Enemy class may be extended. What? You don’t know the names of the Metroid species by hand? A Zeb is creatures that rise from the ground, flying directly against Samus and continues in a straight path until it leaves the viewport. When the Zeb is gone, another one will spawn at the same origin and this repeats infinitely. Occasionally Zebs will drop energy dots or missiles when shot, in this cases no new Zeb will be spawn until the drop is gone. This is quite a different behavior than the Rippers’.

The way I solved the respawns was to reuse the same Zeb over and over, just resetting its position. The Zeb class has a death method of its own overriding the one in the generic Enemy class. Instead of killing the Zeb this death-method will hide it and set the it’s custom property “idle” to true. This will inform the Zeb’s update loop that it’s time to go back to the starting position and start over again (and I put a timer to delay the respawn).

The reason the Zebs won’t respawn until drops from the previous one is gone on the NES is probably limitations to the total sprite count, and that the drops on the NES are in fact the Zebs themselves in a new form. We don’t have to wrestle with that kind of limitations today but decided to imitate it. The Zeb class has a custom property (drops) that is used to refer to possible drops. Even if the Zeb idle property is set to true it will not respawn while the drops-property refers to an object and the alive-property of that object is set to true.


Obviously, there are a lot of flaws in the code above. Frozen enemies will not defrost without getting shot, Samus might be hurt multiple time from the same enemy within milliseconds etcetera. The code isn’t tested either and might contain both logical and syntax errors. However, I hope by stripping out most of the code and focus on a few parts I’ve managed to create something fairly easy to follow and that you found it useful.

If you have found something you disagree with or suggest to do in another way, please let me know. I’m doing the Metroid Remake as an exercise to learn more about JavaScript, game development and Phaser. Much of what I have written was new to me as late as one or two months ago. Also, English is a second language for me so don’t be shy to suggest changes on the texts too.

As I wrote in the beginning, this is my first ever tutorial. I haven’t decided if I will do more blog posts like this. It depends on how much time I’ll have at my disposal, but even more on how this is received. If you want me to continue, add a comment below and share this blog post. It’s been fun, but without feedback or traffic from visitors, I’ll probably loose interest. 🙂


  1. Thanks for sharing. Question : why you create a group of enemy instead of create new instance everytime (and destroy object when not needed) ? because I assume that in a video game you will have multiple types of enemy and if for each you keep 10 or more instance it will be high memory consumption for nothing.

    1. The technique is called pooling. Creating and destroying objects are quite expensive (triggering the garbage collector) while the memory impact of the objects needed is negligible. I would guess that this is true even if you have extremely high number of objects, far beyond what the computer would manage to handle in its update loop anyway.

  2. Niklas, thanks for this courageous work.
    I am a NES and Metroid huge fan and I am very happy that somebody started this venture.

    For several month I have been working, with my 9 years old son, on a game with phaser.
    My goal is to develop a NES-like game like you, maybe Kid Icarus.

    Please, continue to make us dreaming!

    1. Thank you for the kind words! I’m happy you enjoy the project. Did you know that Kid Icarus is actually based on the same engine as Metroid. When you think of it it’s also horizontal, vertical and single rooms but connected by shifting levels. I spent most time on this project parsing the map correctly, defining boundaries, scrolling between rooms etcetera. With Kid Icarus you would only need to load the levels as separate maps and let camera.follow do all the work. I would really recommend recreating a game as a practise, it’s like working with a team but everyone else finished their deadlines on day one.

Leave a Reply

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