Ash – a new entity system framework for Actionscript games

I’ve been doing a lot of stuff with entity systems recently. At try{harder} I gave a presentation about entity systems, which was warmly received and led to many interesting conversations. I also created example projects with the Ember and Xember frameworks and had fruitful conversations with Tom and Alec about their projects, even contributing a few minor bits of code to them.

But now I’ve written an entity system framework of my own. It’s called Ash and you can find it on Github.

A few of the features of Ash are

I plan to build a game with Ash, so more features will come as I need them, and more posts on this blog. Meanwhile, if you’re building an actionscript game why not take Ash for a spin. And for comparison, check out Ember2 and Xember.

Tom in particular has done a lot of work to develop the ideas behind entity systems on the Flash platform. Without that work to feed my ideas machine I wouldn’t have built Ash, so thank you Tom.

And thank you to Till who added a feature to SwiftSuspenders to enable me to inject linked lists based on their content type.

Update

Here is a follow-up post explaining entity system frameworks and a further post explaining some of the reasons why I like using an entity system framework for my game development projects.

Update 2

Ash now has a website, at www.ashframework.org.

32 thoughts on “Ash – a new entity system framework for Actionscript games

  1. Hi Robert

    The performance on dispatch is very similar for my simplified signals. The actual dispatch loop is pretty much identical, but my signals don’t test the parameters first, and no array is created in the background to hold the parameters passed to the dispatch method because I don’t use the …(rest) parameters construct. This produces a slight performance improvement, but it’s insignificant. The only item of minor significance to me is, because no parameters array is created there’s nothing to garbage collect later, which helps in making a game that does minimal memory allocation and disposal during gameplay.

    The performance on add is markedly faster in my signals (approximately 10x in my tests). But that too is not particularly significant.

    The main reason for creating my simplified signals is to alter the logic slightly. With my signals, when you remove a listener it is removed immediately, even if removed during the dispatch loop. So I can guarantee that the listener will not be called after removal.

    I assume the reason As3-Signals completes the dispatch loop on all listeners that were present at the start of the loop is to make the functionality independent of the order of listeners. That’s why i didn’t question the functionality in As3-Signals or suggest it be changed.

    However, in Ash it’s common for a system to alter the state of the game, adding and removing other systems. When a system is removed, it will clean up after itself. With As3-Signals, the system may subsequently receive an update signal because it was later in the update listeners list than the system that removed it. Every system would need additional code to prevent errors in such a situation. Using signals that guarantee immediate removal prevents this.

    The alternative is to queue all system changes until after the update loop is finished, which I considered but rejected purely because it’s more complicated to implement. I may change my mind later ;-) .

  2. In the entity system I’ve been building for the past year (unfortunately not open source – hopefully in the future it will be), I’ve implemented pre- and post- loop calls to perform system changes, and also for entity/component cleanup, which has helped to avoid issues where a component is removed part way through a loop but then expected later in the loop.

  3. I would like to see the presentation, otherwise I’d like to know what you mean with entity framework. Thank you.

  4. Hi Ben.

    I’ve been thinking about this since my reply to Robert above, and spurred by your idea, which gives the developer control to schedule actions to occur outside of the update loop, I’ve added an update complete signal. I think this is sufficient and is simpler than adding additional methods to the systems that won’t be used in most cases.

    If a system wants to schedule something to occur outside of the update loop, it would add a listener to this signal.

    Thanks for the suggestion.

  5. Hi Sebastiano

    I am writing a rather long blog post about entity frameworks for games, loosely based on my presentation at try{harder}. I hope to be able to publish it next week.

  6. Great stuff, I’ve tried Ember and have used it in 2 projects – event though I was not always using the best practices it definitely helped maintain my application. Now I am giving ASH a try on another project.

    One thing I would like to see is a blog post about serializing/deserializing.

    I know Tom mentioned it was fairly easy but I would love to see a concrete example to wrap my head around.

    Keep up the good work.

  7. Hi Phil

    I’ll see what I can do. The key to the easy serialisation in a framework like Ash is that

    1. The state of the game is encapsulated in the entities.
    2. The entities are made of components only.
    3. The components are just value objects.

    So to save the game state, you just have to serialise a bunch of value objects, which tends to be straightforward (most of the time). It gets a bit tricky when one of the properties in a component is a movie clip, for example, but for most components you can just convert them to a format like json and spit them out.

  8. Richard, sounds good.

    Another issue I ran into with my application was communication between Systems. What I would do is inject some class into any system that needed to communicate – that class would contain a variety of signals (onComplete, onStart) or whatever applied to the context. Systems would simply fire/listen to the appropriate signal – this worked to decouple the systems from one another but led to them being coupled to the events – is this a good approach or would you recommend something else?

  9. Hi Phil

    I think the first choice you have to make is between immediate communication, via events, signals or similar, or delayed communication, by setting state properties in components that other systems can read and react to when their update method is called.

    If you choose immediate communication, then I would be inclined to dispatch signals directly from the services. One of the benefits of signals over events is they can be defined in an interface, so you can define an interface for the dispatcher of a signal, and inject that dispatcher into classes that want to listen for the signal, based on it implementing the interface. You can see an example of this, in an MVC architecture rather than entities, in this blog post.

  10. Richard,

    Injecting interfaces with Signals has been what I’ve been doing so far so based on your comments it sounds like it has been the right approach.

    Thanks!

  11. Hi !

    I am using the Ash framework to implement a Tower
    Defence Game, and during the the first implementation
    step i have found found some questions, after reviewing the source code i am not sure what i understood was correct or not:

    There is no way to know which position component begins to the tower or creeps?? so i have to create
    2 types of position class and the corresponding 2 nodes for determine which one begins to the tower/creeps.

    i think maybe i understood bad, can explain the node and the family more further ??

    Thanks for ur effort & time !!

  12. Hi, Richard, i have a problem when using Ash.
    The NodeList’s nodeAdded signal was dispatched when adding an component to Node’s entity. I don’t know whether it’s correct or not.

    for example following:

    //in "addToGame"...
    objs = game.getNodeList(ObjectNode);
    objs.nodeAdded(addObjectToWorld);

    //in "addObjectToWorld"...
    function addObjectToWorld(node:ObjectNode)
    {
    var skin:SkinComponent = new SkinComponent();

    //just add a SkinComponent to the Entity, but this will make the "nodeAdded" signal dispatched and "addObjectToWorld" was called again.
    node.entity.add(skin);
    }

  13. Hi tamt

    If the SkinComponent is an item in the ObjectNode, adding it would cause the previous instance of SkinComponent to be removed from the entity, thus causing the entity to be removed from the NodeList then added again.

    Alternatively, is adding the SkinComponent causing other code to run which will cause the the entity to be removed and added to the NodeList?

    Try listening for the nodeRemoved signal too and see if the node is removed and re-added, and seek out the cause of the removal.

    If you think this is caused by a bug in Ash, would you post it as an issue in the Github repository – https://github.com/richardlord/Ash/issues – it’s easier to deal with all bug reports there.

    Thanks

  14. Hello I have been using your system for a while now, pretty good!

    Is there a way to support the adding of Interface types
    as components, as ash does not recognise base types.

    For example, I have a specialized Camera object that my engine used however it only exposed an interface ICamera publically.

    Ash does not refer to ICamera and instead treats it as Camera…

    - Thanks

  15. Pingback: Games And Entity Systems | Shaun Smith

  16. Hi Richard,

    Great framework. I’m learning Game Entity with Ash on a game prototype and so far it’s going great.

    One thing I’m curious to know is what, in your opinion, would be the best way to have different update frequencies for the systems? If I want RenderSystem to update on each frame but having other systems updating every half seconds or every seconds?

    Thank you very much

  17. Hey, nice job on your Ash entity framework. I made another port of the framework to haXe. I focused on integrating haXe’s static typing features for signals and nodes and had some success in that area. I also implemented iterators for Ash’s linked lists (like NodeList) for ease of use. I plan to follow the changes made in AS3-version and port them to haXe version, unless it will change at its’ core principles.

    It’s still PRE-ALPHA at the moment, but you guys can check it out at https://github.com/nadako/Ash-HaXe
    I’m still learning haXe (especially macroses) and my code may not be optimal, so if anyone want to contribute – welcome.

  18. Pingback: Box Hacker » Blog Archive » Using an entity component system in AS3

  19. Pingback: Getting started with Ember | Tom Davies

  20. I want to know how can I use a UI framework like windows or buttons in this entity/component framework? ie. if I want to create a window with buttons, labels and images…,what should I do? window as entity?button as entity? how to organize them? Wish your reply!Thanks.

  21. Howdy,
    I’ve been using Entity Frameworks for about a year now working with Ember primarily and Ember2 in my spare time. I love entity frameworks, I can’t imagine using anything else for games now that I’ve made a few using Ent frameworks.

    The one area I always have trouble with coming to a great solution to is interface/HUD. Does anyone else have solutions to how they’ve managed doing HUDs in these frameworks?

    I associate a hud to a System in a semi-MVC pattern to display the data to the player.

  22. Pingback: Flash Ash Entity Systems Programming notes « Flash for the Masses

  23. @Jeff

    There are two main ways to manage a HUD (the in-game UI)

    1. Separate the hud from the game. Dispatch events from the game and allow the hud to listen to them – you may want some form of centralised event bus for this so the hud doesn’t have to listen to specific systems. These events can then inform the hud of changes to state and the hud modifies the data it shows accordingly.

    2. Create the hud as one or more components and systems. Add the textfield in both a display component for rendering and in a hud component for updating. The hud system updates the content of the text field, the render system displays it, just as it displays all the other visual content of the game.

    Either system works. It’s a matter of preference which you use.

    Sorry I haven’t had time to add this to the asteroids example yet.

  24. Pingback: Compulsive Columbus — A Flash Entity System Framework Test Game « Flash for the Masses

  25. Pingback: The London Experience « Geraldo Nascimento

  26. Ash uses a data-oriented-design approach (DoD), but it’s current implementation in As3 doesn’t reap the benefits of DoD design when it comes to arranging similar data-sets in contiguous sections of memory for parallel processing. See https://www.youtube.com/watch?v=16ZF9XqkfRY and http://gamesfromwithin.com/data-oriented-design . A C-Struct is useful for this since one can allocate a predictable section of memory to hold that set of data.

    I’m wondering if implementing something for Ash using some Apparat processor like the one below:
    http://code.google.com/p/apparat/wiki/StructureType . I tried to create something like this in HAxe with an Alchemy memory version (using alchemy memory data structures), but the boiler-plate setters/getters are too hard to make, unless one could devise a macro based on struct metadata declarations.

    Can you guarantee that using NodeLists (doubly-linked lists) is memory effecient and good for performance? I doubt this is the case for Flash without proper struct allocation like in C.

  27. The only benefit I see for DoD design currently within As3/Ash, is a not-so-deep method-execution hierachy, since encapsualtion/virtual-method-calls are minimised except for a few cases which can be deemed beneficial. With less encapsulation, more predictable executions can occur within systems rather than having unknown entities do too much heavy work. I understand a doubly-linked NodeList is versatile for Ash/Flash, but it doesn’t work well when it comes to contigigous memory access that a C-struct and Std Vector provides. I guess, in cases where contigious memory access is required, external subsystems (outside of Ash/pure AS3) can still be used instead. NodeLists is an additional requirements of memory usage for the purpose of fast-retrieval of properties (without relying on Dictinoary/Object hash-lookups) and type-hinting, but they still use some form of “pointing” reference , but it’s impossible to control how these pointer values are laid out in memory anyway.

  28. Hopefully you’ll get this, unfortunately it looks like you’ve been really busy with other things lately…

    I’m new to ecs and trying to implement a simple game in ASH to get my feet wet. I’ve come across a situation (a couple actually) where I am creating a component and using a graphic, but in the graphic it needs to know values from the component…

    What is the proper way of handling that? I could set static variables in the component, but that doesn’t feel right..

    Here’s an rough example:

    components.ball:
    public var radius:Number;
    public function ball(radius:Number = 100){ this.radius = radius); }

    graphics.ball:
    public function ballView(){
    var mesh:Mesh = new Sphere( );
    }

    Called as:
    var ball:Entity = new Entity(“ball”)
    .add(new Ball(125))
    .add(new Display3D(new ballView()));

    Or in an FSM as:
    fsm.createState(“ball”)
    .add(Display3D).withInstance(new Display3D(new ballView()));

    Perhaps I’m not doing it the right way in the first place… :)

  29. Hi Rob

    If the graphic needs to know the values only when it’s created, then I would simply use the same value when creating the mesh and when creating the other component (physics or whatever). If, however, the value changes over time then I would have a system that updates the mesh based on the value in the other component.

    In short, if it’s a fixed value you can handle it once, when creating the components, and there should be no problem since you are creating both components and can pass the same value into each. If it’s a varying value then I would use a system to update the graphic based on the other component.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>