Space Invaders meet ConfigCat and MelonJS

manuelpopa

Manuel Popa

Posted on February 21, 2022

Space Invaders meet ConfigCat and MelonJS

Growing up as a child of the ’90s has always been a bitter-sweet kind of experience, but it certainly also came with a multitude of benefits. We’ve been exposed to countless priceless moments that have come and passed, moments that stand to make history and which may never be experienced again by newer generations. One such example of a beautiful lived-through historical moment is growing up with the fabled Space Invaders game.
Simple yet memorable, Space Invaders made waves across the world and undoubtedly served as a catalyst for the revival of a previously stale and dying gaming industry that’s now priced at no less than 173.7 billion USD.

What we're going to do

Nostalgia trip aside, the plan here is to rebuild “Space Invaders” in MelonJS while also taking advantage of ConfigCat's feature flag management service to toggle your player's ship from the default one to another, more custom version.

What is MelonJS​ ?

MelonJs
Well, silly naming scheme aside (which may or may not give you a craving for melons), it’s an:

  • actively maintained
  • open-source
  • JS-powered game engine that’s licensed under MIT

Personally, I’d go for MelonJS 2, as it’s a modern remake of the engine that's perfectly adapted to support ES6 class, inheritance, as well as many other goodies. If you want to learn more about what it can do, check out their docs right here.

What are Feature Flags?

In short, you can visualize a feature flag as a switch that’s used to activate or deactivate certain functionalities that may be present in your application.

Here are some examples of why you may want to use feature flags:

  • give early access to new features to only a select few
  • targeting specific demographics
  • various other testing purposes
  • releasing things in a more ordered and stable manner

Why use ConfigCat? cat

What makes ConfigCat attractive is that they offer a very balanced forever-free plan, which includes a plethora of things, including their entire security stack (while most other competitors would have you pay extra for those). This eliminates any artificial incentive for you to upgrade unless your business organically scales to new requirements.

You could technically create your own in-house feature flag service, but it would make more financial sense to just use an already existent one like ConfigCat’s.

Time to build Space Invaders!

spaceInvaders
The version of Space Invaders that we’ll be building won’t be anything truly fancy, just your average, stripped-down base game with no extra bells and whistles. We’ll have a set of ships arranged in an 8 by 4 grid rushing toward our ship.

Project structure

The easiest way to start your project is by getting the ES6 boilerplate provided by MelonJS. After that just trim your excess folders and files, and the result should look like this:

src
└── data
|    ├── img
└── js
|    ├── renderables
|    └── stage
├── index.js
├── index.css
├── index.html
├── manifest.js
Enter fullscreen mode Exit fullscreen mode


`
Here's the repo link of the finished game, in case you want to follow along.

Building the game

To start using MelonJS, we’ll just add the following line to the top of each file where we’ll need to use its functionalities:

`

import * as me from 'melonjs/dist/melonjs.module.js';
Enter fullscreen mode Exit fullscreen mode


`

For this project, we’ll add three more files under the js folder:

  • constants.js - used to define things like laser’s width and height
  • laser.js - used to define the Laser entity
  • enemy-manager.js - used to manage the creation and movement of the enemy ships

The entry point for your project is the index.js file where the canvas is prepared and all the prerequisites for the game are preloaded by the onReady() method:

`

me.device.onReady(() => {
    setTimeout(() => {
        if (!me.video.init(
                1218, 562,
                {parent: 'screen', scale: 'auto', scaleMethod: 'flex-width'})) {
            alert('Your browser does not support HTML5 canvas.');
            return;
        };
        me.audio.init('mp3,ogg');
        me.loader.crossOrigin = 'anonymous';
        me.loader.preload(DataManifest, function() {
            me.state.set(me.state.PLAY, new PlayScreen());

            me.pool.register('player', PlayerEntity);
            me.pool.register('ships', EnemyEntity);
            me.pool.register('laser', Laser);

            me.state.change(me.state.PLAY);
        });
    }, 5000);
});
Enter fullscreen mode Exit fullscreen mode


`
Under the renderables folder we have two files important for the movement and interactions of the ships soon to be battling each other:

  • enemy.js - used to define EnemyEntity
  • player.js - used to define PlayerEntity

The epic battle will be staged in the stage folder, inside the play.js file where we have the onResetEvent(), onDestroyEvent() and checkIfLoss() methods which will dictate the way our game will work.

All the images we’ll need can be found in the "data/img folder" and we’ll use them in the manifest.js file as such:

`

const DataManifest = [
    {name: 'player', type: 'image', src: 'data/img/player.png'},
    {name: 'player2', type: 'image', src: 'data/img/player2.png'},
    {name: 'ships', type: 'image', src: 'data/img/ships.png'},
    {name: 'bg', type: 'image', src: 'data/img/bg.jpg'}
];

export default DataManifest;
Enter fullscreen mode Exit fullscreen mode


`

Tips and Tricks

  • If you want to add a custom background picture to the game, use the following code to the OnResetEvent() method, located in the play.js file:

`

 me.game.world.addChild(new me.ImageLayer(0, 0, {
    image: "bg", 
    repeat: "repeat",
    z: 0
 }), 0);
Enter fullscreen mode Exit fullscreen mode


`

  • One issue that you may encounter is with the game’s resetting functionality when calling the checkIfLoss() function. The bug seems to be caused by the bounds.bottom argument which may sometimes equal infinity. You can easily go around this bug by just adding the following check at the end of the first if statement in the enemy-manager.js file - at the time of writing, this was at line 40.

`

if (me.state.current() instanceof PlayScreen) {
me.state.current().checkIfLoss(bounds.bottom);
};
Enter fullscreen mode Exit fullscreen mode


`

In the end, if all goes well and the Gods of coding are merciful, you should be able to see this:

gif1

Using ConfigCat's Feature Flags in Space Invaders

Let's say that I want to change the main ship with a custom version to be displayed to a specific audience. The easiest way to do this without having to change the code and make another deployment of the new version is to implement a feature flag, which can be switched on and off with ease.

I intend to show the custom version of the ship only if the evaluation of the flag is true. And since the application is written in Javascript, I’ll choose ConfigCat's Javascript SDK, for which the process of installing is fairly straightforward and well documented.

Just fire up npm and run

npm install configcat-js

, after which just import it in constants.js file via the following line:

`

 import * as configcat from "configcat-js";
Enter fullscreen mode Exit fullscreen mode


`

The next thing that you need to do is to quickly head over to ConfigCat’s registration page and create a free account for yourself. After which you’re all set to create your first feature flag. I named mine "isMyFirstFeatureEnabled".

feature flag

I'm now free to go to constants.js and add my SDK key (which you can grab from the ConfigCat Dashboard where you created the flag earlier). Once in the dashboard, you'll see a button in the upper right-hand corner called “View SDK Key”.

I then create the client like this:

`

  let flag ;
  const client = configcat.createClient(sdkKey);
  const getFlag = () => flag;
  client.getValue("isMyFirstFeatureEnabled", false, value => {
     flag=value;
  });
Enter fullscreen mode Exit fullscreen mode


`

Now that the client is in order, we should now hop in the player.js file, import the getFlag() method from constants.js and use it to load the player with a new ship depending on the flag’s value:

`

  if (getFlag()) {
    image = me.loader.getImage("player2");  
  } else {
    image = me.loader.getImage("player"); 
  }
Enter fullscreen mode Exit fullscreen mode


`

Last but certainly not least, all that’s left to do now is to use the ConfigCat Dashboard, flip the flag to "true" and then reload the game.

BAM! The result should be something like this:

gif2

Conclusion​

MelonJS is a powerful JS game engine and as a testimony to this stands the vast documentation that you need to read in order to unleash its true power. It certainly can help you in case you want to have a chance at making the next big game hit. Feature Flags can be outstandingly scalable and useful, and I’m glad that I found ConfigCat to help me out with this.

Here’s the git repo link in case you want to check out this tiny Space Invaders remake and I hope you that you'll get to relive some nice childhood memories playing it.

If you are looking for more articles like this, make sure to check out ConfigCat’s blog posts or you could follow them on your Facebook, Twitter or LinkedIn accounts.

💖 💪 🙅 🚩
manuelpopa
Manuel Popa

Posted on February 21, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Space Invaders meet ConfigCat and MelonJS
configcat Space Invaders meet ConfigCat and MelonJS

February 21, 2022