GameDev – Entity Component System for Phaser.io

This is Part 1. Here’s Part 2 of the series.

Entetey Compowhat?

So the other day I saw on invrse.co that there was interest in having an entity component system for JavaScript games, to which I self-fived myself and promptly tweeted how cool it was.

This is my 'stache
And then I instantly grew an awesome ‘stache. That’s how happy I was.

 

A couple of days earlier I had started looking into ECS, for a Phaser game I’m currently working on. I strongly suggest that you read invrse’s post up there, it’s super interesting and well written, and if you’re unfamiliar with ECS, I urge you to read it!

So hey, one little disclaimer before we move on: I am totally half-assing this. I’m pretty sure I’m miles away from the real way an ECS should be done, but bear with me, what’s coming is pretty cool!


Half-assing in all its glory

ALRIGHTY-O, let’s get started with a quick (half-assed) recap.

  • Entities are your “objects” or “actors”, such as the player, an NPC, an orc, a sword, a crate, a textfield…
  • Components are the additional properties and behaviors that you might want to add to your Entities. For example, a popular one would be a Physics component, so as to add gravity and collision to your entities.

We’re just adding behaviors and properties to an object.

With this information, let’s take a look at how components should behave:

  • Components should be parameterizable (pretty sure that’s how it’s spelled)
  • Components need to know on what they are applied (entity)
  • Components need to be updated every frame (game loop)
  • Components need to be added and removed at will (they’re optional)
  • Components sometimes need to talk to each other (event, signal, or callback system)

Ok, ok, that’s cool. Let’s take a look at a basic component without any behavior at all. Like I said before, some kind of physics component is usually used during game development, so we’ll create the Body component.

var Components = Components || {};

Components.Body = function() {

	// Reduce conflicts
	var self = this;

	// Name
	self.name = "Body";
	

	// -------------------------
	// Methods
	// -------------------------
	self.update = function() {
		// console.log("[Body] :: update");
	};

};

As you can see, there are is a name property, and an update() method.  These two things will make much more sense later, but for now let me explain quickly: the name property is used to identify which component we are dealing with. The update() method will be called by the Entity in its own update() method.

Now, the next step is to add the target, or simply put, the entity to which we are referring to, and the subject of the components behaviors.

var Components = Components || {};

Components.Body = function() {

	// Reduce conflicts
	var self = this;

	// Name
	self.name = "Body";

	// Target
	self.target = null;


	// -------------------------
	// Methods
	// -------------------------
	self.setTarget = function(t) {
		self.target = t;
		console.log("[Body] :: added target " + t);
	}


	self.update = function() {
		// console.log("[Body] :: update");
	}

}

Awesome. This is pretty much the basis for all our next components. You can copy paste and rename them to your liking. Personally, I like to give them adjectivized names, to quickly understand that they’re components, and what they do, for example FlammableDroppable, Throwable, you get the idea…

Now here comes the meat for our Body component.

var Components = Components || {};

Components.Body = function() {

	// Reduce conflicts
	var self = this;

	// Name
	self.name = "Body";

	// Target
	self.target = null;


	// -------------------------
	// Properties
	// -------------------------
	self.physicsEngine = Phaser.Physics.P2JS;


	// -------------------------
	// Methods
	// -------------------------
	self.setTarget = function(t) {
		self.target = t;
		console.log("[Body] :: added target " + t);

		t.game.physics.enable(t, self.physicsEngine);
	}


	self.update = function() {
		// console.log("[Body] :: update");
	}

}

So we’ve set some default properties (self.physicsEngine), and we’re enabling the object in the physics world of your game.

Ladies and gentlemen, we’ve just created our first component, and it is absolutely simple. Don’t be fooled by the apparent number of lines, there are many lines of comments and whitespace.


FISRT!11!!

So we’ve created our first component. Now, how do we use it? Let’s imagine we have a Player class.

// Player class
// ...

// Utility method to add / register components.
Player.prototype.addComponent = function(comp) {
    
    // see, I told you the component name would be used!
	this.components[comp.name] = comp;          
	
	// setting the target 'initializes' the component
	this.components[comp.name].setTarget(this); 
	
	// return the component for other uses
	return comp;
}


Player.prototype.create = function() {

	// Add Component(s)
	this.addComponent(new Components.Body());

};

// ...

You need a this.components array. Storing the components you add to an entity makes them accessible, and you can then call the update method of ALL your components in easily:

Player.prototype.update = function() {
    
    // ...
    
    Object.keys(this.components).forEach(function(componentName) {
        this.components[componentName].update();
    }, this)    
    
    // ...
}

Well?

Well, this wraps up the first Entity Component System post. I hope it made sense to you, and don’t hesitate to comment!

Now on to Part 2.

Comments

  1. Hey Paolo 🙂

    I realy like your approach – I like how the component works with targets and how simple it is to call all components from within a class. There is a lot good about your implementation, specially given the constraints of working with a non ecs engine, kudos! 😀

    Personally, I tend to favor objects over functions for this so that I can pass arguments like name and be done with it:

    // —————-
    Components.new = function(name, obj) {
    obj.name = name;
    Components[name] = obj;
    };

    //So we could start creating the Body component like this

    Components.new(‘Body’, {
    update: function() {
    //code
    }
    });

    // —————-

    It does add a layer of complexity because it requires me to either deal with objects copying (which is a pain in JS) or to use workarounds.

    Nice work, looking forward to new posts 😀

    1. Thanks Otto!

      I’ll keep fleshing this out in the next days to show a practical example, especially to show components talking to each other 🙂 You’re gonna like it!