Jump to content
This forum will be closing down. Please move to the respective dedicated project forums.

Has anyone used an ECS pattern in their Phaser project?


David
 Share

Recommended Posts

This isn't necessarily a Phaser- specific question, but I'm just curious about the patterns that are being leveraged in the Phaser community..

 

In my current project, I'm following the simple and common structure that can be seen in things like XNA.

 

That is, I have my entities acting as wrappers for the phaser sprite something like this:

 

entities/foo.js

FooEntityFactory = function(someInitParams) {    //some initialization code    return  {        sprite: game.add.sprite(10, 20, 'sprite1');        update: function(game) {            //some update code        }    };};

And then I can keep my states relatively tidy by not cluttering it with entity logic and leaving more room for state-specific logic:

 

states/bar.js

BarState = {    entities: [],    create: function() {        this.entities.push(FooEntityFactory());    },    update: function(game) {        this.entities.forEach(function(entity) {            entity.update(game);        };    }};

However, I'm trying to get some ideas on out how to augment things with an Entity-Component-System pattern.

 

Has anyone else organized their code in such a way that that utilizes this pattern?  How about EC?

Link to comment
Share on other sites

Yes I did - however reverted back as count of abstraction layers became inadequate to my game complexity :)

 

I think that's reasonable approach - especially that it removes risk of name conflicts caused when extending Phaser.Sprite object

 

All you have to do is to not forget about removing sprite object when it is no longer necessary. (as in calling destroy)

 

As Phaser is a kind of entity system already you will be probably adding all collision, position etc bindings to this.sprite object

thanks to getters/setters you could use a bit of magic for obvious elements like

{  sprite: game.add.sprite(10, 20, 'sprite1'),  get x() {    return this.sprite.x;  }} 

For states, stages, scenes I would create a new constructor:

GAME.Scene = function(args) {  extend(this, args);  this.entities = [ ];  ...};GAME.Scene.prototype = {   update: function() {     for(var i = 0, len = this.entities.length; i++) {      this.entities[i].update(I_WOULD_PUT_DELTA_TIME_HERE);    }  }  ...};GAME.titleScreen = new GAME.Scene({    update: function() {    GAME.Scene.prototype.update.apply(this, arguments);    /* whatever specific to the state */  }});

Then you would probably have some game or app object that wraps around Phaser.Game - and this is where I gave up because of the evergrowing stack of abstractions.

Link to comment
Share on other sites

Thanks @Rezoner!  Using getters n' setters is definitely a great way to hide the fact that you're wrapping the sprite.

 

Looking back, it seems I obfuscated my actual question a bit by going into detail about my current layout.  I was actually wondering if anyone successfully used an entity-component-system design pattern while using Phaser, which on my first impression seems like it doesn't necessarily lend itself to that too well.

 

Here is more on a related entity-component pattern: http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/

 

In an entity-component-system pattern, you have entities which are nothing more than containers with an ID, components which are nothing but data, and systems which are logic that mutate component data.

 

For example, I might have an entity that has the components position and speed.  The position component is just an x,y pair.  And the speed is nothing more than magnitude and direction (which of course depending on your usage, could also be an x,y pair).

 

Then, you might have a "physics" system that gets all entities that have the components "position" and "speed" and uses speed to update the position values each tick.  And if you take away the "speed" component, then the "physics" system will no longer act on it, keeping the entity stationary.

 

Obviously, this type of simple example wouldn't apply if using a library like Phaser since physics is handled automatically.  But, being able to add/remove components like "jetpack" or "shields" across a number of entities is quite powerful.

 

But perhaps I'm barking up the wrong tree entirely.  I know that Phaser is based on Flixel, which I'm not familiar with.  Does anyone know what patterns are common in the Flixel world?

 

I suppose I'm just trying to leverage existing best practices rather than reinvent the wheel and run into issues that might already be solved problems.  But, then again, Phaser is kinda new, so maybe there aren't any real best practices yet?

Link to comment
Share on other sites

@Mefteg It will be nice if someone has done this with Phaser.  However, in my (limited) experience, I've seen this successfully applied when either the library supports it outright or the library is lower level and applies to one domain (like EaselJS for graphics).

 

I'm going to chew on this for a bit and see if there is a way I can work in this pattern without getting in the way of Phaser.  The real challenge here is that it does so much so well (not to mention that I only have moderate experience with the pattern).

 

On a related note, here's a more recent article on ECS and from the perspective of a web developer.

 

http://blog.lmorchard.com/2013/11/27/entity-component-system

Link to comment
Share on other sites

@ooflorent.  Ditto on @mwatt.  I'm taking my own stab at it at the moment as well.  And since I'm still relatively new to the pattern (I'm primarily a javascript app dev who lives in things like BackboneJS, CanJS, etc), I'm interested in seeing how those more familiar with the pattern would approach the problem.

Link to comment
Share on other sites

This post describes a similar case: Phaser/Pixi + Ash.JS.

 

The main issue while integrating Phaser with an ECS engine is how deep you want to use ECS components. In my opinion, the best approach is to decouple the update loop into systems and match game objects using groups. Phaser has a lot of features such as rendering, physics or audio management. Delegating these to systems seems pointless to me. As I said before, business centered systems are a better options.

 

So, how to implement them? I would create a custom Phaser.Sprite class with a flags property to apply component masks on my game objects and then the game systems are iterating over all game objects (using optimized data structures). In this implementation there are no components, only entities (which are game objects) and systems. The flags property emulates components since the Sprite contains everything it need.

 

If you want a complete ECS implementation, then you may have to drop Phaser or use only low level APIs.

Link to comment
Share on other sites

@ooflorent  Awesome.  I did a little learning project a few months ago in order to get my feet wet with ECS (with the actual ECS modules here).

 

I'm in the middle of a rewrite from some of the face-palm learning point I've made since then and making it general enough to use with Phaser or any other game library.  While I'm doing that, I'll definitely be comparing notes to your implementation.

Thanks!

Link to comment
Share on other sites

That is for sure.  Right now, I'm trying to understand the pattern itself more than anything so I can learn how to decompose the problem when thinking about implementation.

 

At the moment, I can look at any given web UI design and instantly know how to break it into efficient, maintainable modules and know what data is driving any given one.  But being a noob in the game development world, I'm still hampered by the architecture.  And when I follow the standard advice and just go with "doing what works", I always end up painting myself into corners.

Once I can come up with an idea and instantly know how to break it down, then I'll definitely be using existing, well tested libraries like yours.

 

In fact, it's awesome to have this second library to compare implementations against.  Thanks again.

Link to comment
Share on other sites

I agree that you should avoid deep inheritance trees and blobs. But as for every pattern I don't think you should keep it 100% clean. Using a phaser Sprite as "entity" might not be a plain entity in the sense of ESC  but still is not a BLOB. So I see no reasons why you should not avoid to put too much stiff into your sprite but still keep the framework logic inside.

 

I made the same experience with an server based game I develop since ~8 years. At some point you want to split the logic from the structure and data. Still it is not bad to keep some small inheritance trees that work fine and are not worth refactoring. 

 

The articles are very interesting and I will see if I can adopt some more aspects of the "plain" ECS in my future programmings.

Link to comment
Share on other sites

Got it ready. Introduced just a quick approach to create a spawner using ECS: https://github.com/Niondir/LifeInLife

 

Yet it only yells "spawn" but together with an PositionComponent and a SpriteComponent it might be able to actually move an object to the world.

 

If you are not forced to save your components inside a database you could also add callback functions to the components. That would be quiet helpful in a scenario like a spawner. Or you start implementing a whole stack of "SpawnSystems" for any purpose, but then you should find a way to auto register them all at once to the update loop, still taking care of the order relative to other systems.

 

Maybe here it would be even better not to call the component "Spawn" but "DelayCall" to keep it more generic and reusable.

 

 

Edit 1: What I see from you first post is, you are iterating over the entities, which is basically wrong since you want to execute the systems in a given order. e.g. first update velocity on all entities, then update position on all entities.

Iterating over the systems and not the entities gets important, when one system will access other entities and relies e.g. on updated positions.

 

Edit 2: I added a second System to count neighbors of a sprite. You can check it out in the gitgub repo above. Works pretty well, even it just spams the console yet ;) But creating and entity for an existing sprite (that is programmed however it is) and  just a a SpriteComponent to reference the sprite works out.

 

My conclusion yet is: It was really hard to get my mind arround to realize this pattern. But it really helps to keep objects small and concerns separated.

Edited by Tarion
Link to comment
Share on other sites

I read a lot about ECS and I'm working on my own implementation, I also started a topic about that here  : http://www.html5gamedevs.com/topic/1171-entity-systems-have-you-used-them-in-html5-game-dev/ :)

actually, I don't think that using Phaser with a ECS pattern is the good way to go, as phaser already implement most of behaviours you'll want to implement in your systems.

 

for example, rendering is a system by itself, but if you use phaser, you can't control how rendering is done. same thing about mouse/keyboard Input.

a typical ECS for a game should define separate Rendering system, Input system, Physics system ...etc

you can for example use ECS with Pixi witch is the rendering engine used by Phaser.

when using ECS you must forget OOP and inheritence, you also need to really separate every behaviour in an independent module that can handle a type of entities.

I'm working on a code example where I combine ECS and OOP, but ECS is the lower level layer, the only role of OOP is to provide a hight level API to developer.

you can check my "work in progress" ECS implementation here : https://github.com/Ezelia/eee

the included demo uses native canvas2D for rendering, I'll add a demo using Pixi rederer later + other demos later.



 

Link to comment
Share on other sites

  • 1 month later...

actually, I don't think that using Phaser with a ECS pattern is the good way to go, as phaser already implement most of behaviours you'll want to implement in your systems

 

when using ECS you must forget OOP and inheritence, you also need to really separate every behaviour in an independent module that can handle a type of entities.

 

I have a different point of view on this...  While ECS can be and has been implemented without OOP, it can also be implemented WITH OOP.  It just means you use composition instead of inheritance.  Composition is just as important in OOP as inheritance.  I think ECS could work just fine with Phaser.  Although your Entities will already have many systems baked in by Phaser, any new ones that you code yourself could be implemented as components.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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