Saturday, November 6, 2010

A JavaScript Game Framework, not Engine

Now that I recently started game development in HTML5 (and even the DOM) I feel compelled to use some sort of framework to do the low level stuff, but it turns out none exists (for canvas anyway). The promising ones end up bought by Zynga and never seen again.

Since I started my JavaScript Minecraft clone, I wrote everything from scratch including Input, Physics, Collision Detection, Redraw Regions (for optimization), Inventory system, the works. Although they are not fully functional, it seems like a waste of time spent on such trivial aspects. Wouldn't it be nice to have a library do that?

Reading this brilliant repo of game development links I discovered an alternative to long chains of inheritance called Entity Systems. They work by having three aspects: Entities, Components and Systems. My interpretation is you have an entity which is just a unique ID (integer) and Components which when joined to an entity will augment its functionality. The systems just tie everything together and therefore low coupling between the entities and components. So instead of lots of instances of 'Player', 'Monster' -> 'EvilRedMonster' classes, you create an entity and just apply a set of components relevant to the entity. See the diagram below from another great article by Mike West.



This sounded very appealing so I decided to have a go creating a framework, and not an engine. Josh outlines why one should not fall into the Game Engine trap. This engine framework would use the low level functionality I wrote for Minecraft 2D but nicely packaged as ready to use components.

Let's call the little framework NAE (not an en-- you get the point). The important thing for me was to write the API just how I would like a game framework to behave rather than thinking how it would be implemented.

var entity = Nae.e();

Simple. We have an entity. The entity variable will just be a Number but under the covers will mean much more.

Nae(entity).addComponent("2D");

Look familiar? jQuery is very popular and very handsome so why not use the syntax. So we have selected our newly made entity and attached a component with the label '2D'. Of course it will be chainable so other methods can be used directly after.

Nae.c("2D", {
x: 0,
y: 0,
w: 0,
h: 0,

area: function() {
return this.w * this.h;
}
});

That was a basic component. Our entity will inherit those attributes and functions so we can do something as such:

Nae(entity).attr({w: 10, h: 50}).area();

Which will return as you can imagine... 500.

That is just a very, very basic example of my interpretation of entity systems and how they could be implemented in JavaScript.

7 comments:

  1. Nice, I was also looking at doing this in JS. After I read Mike West's article, I found this series of articles about entity systems: http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/

    But I thought of doing it pretty much the opposite way from that described in those articles, using multiple inheritance (via something like JS.Class), and keeping all the entity's data in an entity object. This looks similar to the way you're approaching it.

    ReplyDelete
  2. Yes one level of multiple inheritance is basically my interpretation and how I plan to implement it. That way the components can rely on other components, talk to each other and is a lot more modular.

    ReplyDelete
  3. You can't (performantly) use components in the way you've described. There's a data access issue where you'll inevitably want to look things up by their (position, alignment, type, hitpoints, etc.) so that you can iterate over them in one big pass, but if the only access method is to iterate over all entities looking for those properties, you're screwed and take a massive CPU hit. You have to design around the various lookup methods from the beginning to avoid this.

    Thus you tend to want to maintain the component instances independently of their host entities, and this means that components tend to introduce a huge amount of boilerplate to correctly set up references and allocate/deallocate the component when the parent entity requests it. A naive entity can just try removing itself from all lookup structures, whether or not it actually used them.

    The optimal lookup strategies will vary from game to game anyway - often times it comes down to stupid-simple stuff like marking one field as "player" and another as "enemies" or "pickups" and dumping the appropriate entities in each - no detailed properties necessary. You can't even be 100% correct if you use a collision strategy independent of gameplay(e.g. something like Box2D), since you can oftentimes do other things to filter the potential-collision set before you even go into collision checks.

    So having tried to put it at that level myself, I would say that entity composition is too much of a "sexy engine feature" to be useful at the framework level - there's a transition point of complexity, where for games below a certain amount of sophistication, it's simpler to make overspecified "God Class" entities, than it is to try to slice everything up into a perfect set of components and try for the lightest possible per-entity overhead. Where you really need to make something slimmer(e.g. a particle effect), you can do a one-off for that.

    The framework is a good approach but best utilized when it assists at the "really boring necessary" stuff: Data formats and pipelines. Coordinate systems. Basic collision methods(not even necessarily physics or a broadphase - those can both use customization). Debug scaffolding(performance profiling tools, debug UI).

    ReplyDelete
  4. Looks good! I plan on doing a gradual refactoring of my 'framework' to get remove all the inheritance nonsense that has crept into my codebase.

    I'm still in the thinking phase where I'm contemplating all the repercussions of this major change. How do deal with the issues 'jwhx' brought up and how to deal with inter-component communication both within entities and between entities.

    ReplyDelete
  5. I haven't had time to post a good enough response to jwhxs great comment, but I will make a quick one.

    That is a very good point. Never thought of selecting entities by attribute. Although is that likely to happen?

    It is possible to select by component label so you could just add a component to a specific entity even if the component has no functionality, then select by that. Not ideal but if the performance is that much of an issue I can always create a lookup table with each component and the entity IDs.

    ReplyDelete
  6. A great example of having to selecting entities by component would be a "render" component.

    You don't want to have to loop through all entities to get just the ones needing to be rendered, so the overal entity manager will have to bucket the entities based on components.

    By attribute - perhaps only objects smaller than a certain size on screen are affected by a game action. Now you need to know what has a render component (might be on screen), then if it is a) actually on screen b) over a certain size.

    Making that search space as small as possible is needed.

    Then again, nothing in there is an argument against an entity system - it just means that you need to have a good manager of that system.

    ReplyDelete
  7. Thanks for sharing your info. I really appreciate your efforts and I will be waiting for your further write ups thanks once again.
    flash to html5 converter

    ReplyDelete