Jump to content

Using mixins/components with Phaser


Max
 Share

Recommended Posts

Hi everybody!

 

Let me start off by saying that I'm pretty new to Phaser – I've been playing around with it for a bit but never made a game with it... so I'm not super-familiar with it yet. However, I have made games using CraftyJS and while that engine pales in almost all aspects when compared to Phaser, I really loved its entity component architecture. Not having to create complicated inheritance tress to share functionality among game objects that are otherwise quite diverse makes so much sense to me.

 

Here's what I've done to add similar functionality to my Phaser project, without touching the Phaser source. I want to get your guys' opinions on it. Also, I'm not completely familiar with the terminology so I'm not sure if these things I'm adding to game objects are mixins, components, traits or something else.

 

1. Create GameObject constructor function

 

GameObject will be the constructor function that every visible object in the game will use/extend. GameObject extends Phaser.Sprite and adds some methods for managing components on a game object, for example:

GameObject.prototype.addComponentGameObject.prototype.removeComponentGameObject.prototype.hasComponentGameObject.prototype.requireComponent // ensures that the game object has a particular component, otherwise throws an error

Currently, GameObject provides an update method that goes through all registered components on the instance and calls their update-methods if they are provided:

GameObject.prototype.update = function() {	for (var componentName in this.components) {		var component = this.components[componentName];		if (typeof component.update === 'function') {			component.update();		}	}};

2. Create a component

 

Here's a simple movement component that requires another component called "speed" to exist on the game object (entity).

var movement = autoCurry(function(entity) {	this.requiresComponent('speed');	var speed = entity.speed;	var cursors = entity.game.input.keyboard.createCursorKeys();	return {		name: 'movement',		update: function() {			// prepare			var velocity = entity.body.velocity;			// movement			velocity.setTo(0, 0);			if (cursors.left.isDown) {				velocity.x = -speed;			}			if (cursors.up.isDown) {				velocity.y = -speed;			}			if (cursors.down.isDown) {				velocity.y = speed;			}			if (cursors.right.isDown) {				velocity.x = speed;			}		}	};});

I'm using autoCurry to make the syntax a bit more appealing.

 

3. Add component to a game object

var Player = function(game, x, y) {	GameObject.call(this, game, x, y, 'player');	this.addComponents(speed(150), movement());	game.physics.enable(this, Phaser.Physics.ARCADE);};util.inherits(Player, GameObject);

What do you guys think of this approach? Obviously there are alternative ways to provide components. You might want to have components be constructor functions or plain objects instead of curried functions returning an object – I think that part is probably preference. I'm interested in the viability of using such a system with Phaser particularly.

 

I'm looking forward to a constructive discussion, thanks for posting your thoughts! :)

 

Best,

Max

Link to comment
Share on other sites

I will soon have a very similiar "problem" like you so your post is of high interest to me, thanks for starting it! I really love the idea behind pure ECS like I found it in Artemis, having Components be only data and Systems acting on them. I think that approach is very elegant and seems to work well in another game project of mine. In Artemis a System registers itself to a set of entities of interest for that System. The System itself then gets every entity passed to a process method instead of having an update method called on the component themselves.

 

I think maybe by having a central component register and implementing a system approach I could replicate that behavior in Phaser. I am blissfully ignorant of the performance implications though but on the other hand it is probably not really an issue. I'll probably try to look into having a Phaser plugin to be on the save side.

Link to comment
Share on other sites

Myself and Ldlework discussed this a bit irc.

My general conclusion is that this *could* be a very positive enhancement; if not overdone.

The examples of speed and to an extent basic movement are not that good. I would certainly steer strongly away from making property components.
This is best suited for larger subsystems, such as health or inventory of a player or NPC.

Considering I have to manually override a large potion of the built-in health system, as well as methods like sprite.reset() for my game, I would be in favor of this for components like this, and possibly physics.

The challenge would no doubt be getting the correct level of abstraction to deal with. Nothing too core that requires too much linkage, yet still very usable.


Ldlework also proposed a very interesting idea that he would use if he could; using components as finite state machines for different behaviours, running / jumping states as components, power-ups as components, etc.


My overall feel is positive for this.

Link to comment
Share on other sites

Thank you for the discussion, guys! :)

I really love the idea behind pure ECS like I found it in Artemis, having Components be only data and Systems acting on them.

Using ECS over EC is probably the more sophisticated approach. I don't have any experience with it, as CraftyJS uses an EC approach. But now that you mentioned it, I might try to get a basic ECS working with Phaser.

The examples of speed and to an extent basic movement are not that good. I would certainly steer strongly away from making property components.

This is best suited for larger subsystems, such as health or inventory of a player or NPC.

Can you explain why you don't think it's good to have "property components"? Are you talking about it being overkill to have a component just for adding one property (like "speed") to an entity? I think there is an argument to be made that these types of components are great if you think of the single responsibility pattern.

Or do you think naming conflicts could be an issue? If so, you could just set the properties on the component itself and have it act as a namespace instead of setting them on the entity.

I'm glad you two are also liking the idea of Entity-Component in Phaser. Obviously it could be quite a big undertaking to get the whole framework to function like this but I think even just implementing a small system of your own (like I did with the examples in the first post) that doesn't touch or conflict with Phaser source could be beneficial to keeping your code organized.

Looking forward to more thoughts on this! :)

Link to comment
Share on other sites

I'm a favor of mixins but not as a replacement to inheritance. I use CoffeeScript, so I already get inheritance.

Obviously core game engine stuff would probably always be done using inheritance. This post isn't so much about changing the Phaser engine, but more about adding your own component-system on top of it.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...