In my previous post, Entity/Component Game Design: A Primer », I reviewed some of the main differences between traditional object-oriented game design and the emerging paradigm of entity/component game design. I deliberately avoided talking about Artemis, and focused instead on the weaknesses of the alternative approaches, because I believe Artemis is able to resolve many of those problems.
Here I want to talk about the Artemis framework for a while. I keep saying I’ll write about it, but I wanted to get a little more familiar with it first. Well, I’ve been playing with it pretty solidly for about three weeks now, and I feel like I’ve got enough experience to form some kind of an opinion. Although there’s a brief overview on it’s homepage, I want to present my own perspective of it, and talk about some of my reasons for falling in love with it.
Big thanks to the authors Arni Arent (appel) and Tiago Costa (Spiegel) for all their hard work and support!
The Artemis approach
The Artemis framework inherits the concept of Entities representing bags of Components, but it does away with the OO concept of encapsulating behaviour within the components. Instead, it adopts a data-driven design involving the separation of the data and logic of each component.
In essence, the Components serve as little more than bags of data. They have no update function, no internal logic, just getter and setter functions to expose their current values.
The logic is instead encapsulated in the Systems that accompany the entities and components. A ‘System’ is simply an object that reads and updates the data in any relevant components. You could say it’s simply the update function of the relevant components refactored into its own object.
I say “relevant components” because of how the systems do their processing. Instead of the game iterating imperatively through all of the entities and updating each in turn, the systems take more of a functional programming approach. Each system specifies a set of components that it’s interested in, and then in each frame it processes only those entities that contain all specified components.
Furthermore, each system exists to perform a specific role, updating all instances of the relevant components before passing control to the next system. You could say that the components are processed in cross-sections across all entities at once, rather than entities (and all of their child components) being processed in chunks.
Advantages
That’s more or less how Artemis goes about its business, but without having used it, it may not be immediately obvious why this is a Good Thing. Following are a few reasons why I believe it’s a Very Good Thing. Of course, you can only truly appreciate the details after working with it, so I’ll try to keep the discussion at a high level.
Communication
The magic of systems is that they have no reservations in accessing multiple types of component at a time. The systems compose the communication between related components so that the components themselves don’t need to. Systems typically process one entity of interest at a time, and for the period in which they’re processing, they can combine any of the components within each entity however they like, with no structural side-effects.
For example, a MovementSystem could process all entities with Position and Velocity components, and each frame it would update the values of each Position component given the associated Velocity component. A RenderSystem could process all entities with Position and RenderableMesh components, and it would draw each mesh to the screen given the values from the updated Position component. In neither case do the components require any knowledge of each other.
Reusability
Refactoring the logic this way essentially gives you two layers of components – data components (Components) and logic components (Systems) which read/write the data components. Since the Components are pure data, they should never need to change. A 3D Velocity vector will always have X, Y and Z components, and so will be perfectly reusable in any 3D scenario.
The logic in the systems will depend on the rules of the game world, and they can be interchanged as needed. Since each system is typically self-sufficient enough to be autonomous, changing the behaviour of a system will not necessitate a change in the behaviour of any other system.
Say you want/have to change your game from a 3D free-roaming game to a 3D side-scroller. For side-scrolling movement, all you need to do is plug in a side-scrolling MovementSystem (it could be exactly the same, but simply discard the X component of the velocity), and it will automatically apply to all entities with Position and Velocity components. No components or other systems need to change as a result of the change of MovementSystem, since no components or systems even know it exists. (You may then need to update the CameraSystem and ControlSystem as well in this example, but the same process applies.)
Not prescriptive
Because the entities are simple bags of components, and the components are simple bags of data, as a developer you really only need to concern yourself with crafting the systems. The systems can easily take care of composing the relevant components within each entity, and beyond that they have no restrictions in how they process things. This means you can focus on constructing effective systems to solve problems in creative ways.
For example, I have a single CollisionSystem which detects and records all collisions in a single pass, after which I have an OO hierarchy of collision handling classes down which collisions are passed to be handled appropriately. I have an asynchronous TimerSystem which, together with a Timer component and external handler class, lets me attach and listen for delayed events with registered callbacks on individual entities with a single static function call. This may not be the “right” way to do it (and there often is no “right” way), but that’s up to me as the developer. I have the freedom to experiment, and to choose what works best, without sacrificing any part of the framework.
Convenience
All Artemis processing occurs within a managed World object. For convenience, the world object contains four managers that make your job almost too easy:
- EntityManager manages the creation and removal of entities and their components, and allows components to be retrieved from entities by type.
- GroupManager allows entities to be assigned to unique groups (string IDs, such as “ENEMIES”) and retrieved as a group at any time in any system.
- TagManager allows individual entities to be assigned uniquely identifying tags (again, string IDs, such as “PLAYER”) and retrieved individually, similarly to groups.
- SystemManager stores all of your systems, allowing them to be retrieved individually by type if necessary (for instance, the RenderSystem may need to communicate with the CameraSystem).
Performance
The Artemis library itself is very lightweight (for some sense of comparison, Artemis is 30KB compared to the ~1.5MB of Slick + LWJGL), and the internals are built for performance at larger scales. I haven’t yet reached the point where performance becomes and issue, so I can’t comment on quite how far that is, but that alone is an endorsement. Author testing has managed to create/remove a few thousand rendered entities per second, a number which goes up to millions without rendering.
On top of that, the functional programming approach to component processing has inherent potential for performance gains, if taken advantage of. I haven’t read too much into this yet as it hasn’t been necessary, but I’ll talk about it at a later date.
Conclusion
Despite appearances, this is just a static outline of how the Artemis framework fits together and some of the things it does well by itself. I’m not going to dive into all the different things Artemis allows you to do; I’ll try to cover some of those in separate posts in the near future.
I will however say that when using Artemis, the development process changes radically (for the better). You can tackle the implementation of one aspect of your game at a time in isolation. You have a clear implementation path to follow. As your library of components grows, adding new entity types to the game is as simple as creating a new Entity object and adding a different set of Components (or just modifying parameters), and they are automatically handled by the relevant Systems that you already have in place. At that point, it’s almost trivial to read in all your entities from a text file and be truly data-driven.
It’s a pleasure to work with, and every day I’m thinking of new ways to do things that make it even easier. If this article piqued any curiosity or excitement in your inquisitive mind, then I strongly encourage you to investigate using Artemis with Slick. Start by downloading the demo game, StarWarrior, and browsing through the source code. Then try making some small changes to transform it into a different game; perhaps something like Artemoids? Where you take it next is up to you and your imagination.
Just remember to keep an open mind, and have fun! I’m no expert, but I’m more than happy to give whatever advice I can, and the Slick forums are always friendly.
Resources
- Artemis Entity System Framework – The official homepage of the Artemis project. It’s quite new (about a month old), and rather small as I mentioned. From the homepage you can get the compiled JAR, source (JAR, SVN, Git), JavaDoc, and the demo StarWarrior game (inspired by Space Invaders). There’s also an unofficial C# port going on.
-
Artemis thread in the Slick forums – Artemis was originally developed for Slick, and so that’s where most of the discussion is so far. I should mention however that it’s not dependent on Slick, and appel is already using it with libgdx.
- For those of you interested in what I’ve been discussing, I joined in on page 12.
- Entity Systems are the future of MMOG development (T=Machine) – A very thorough application to MMOs, and a primary inspiration for Artemis.
- Anything on this site with the “artemis” tag – The count of this content will be increasing consistently in the future, because Artemis is a lot of fun to talk about.
Pingback: Entity/Component Game Design: A Primer
Pingback: Developers Diary – Developing Methodology | Ploobs
Pingback: Developers Diary – Using Artemis as Entity System | Ploobs
Pingback: Scripting with Artemis Entity System Framework « Gemserk
You were one step ahead of me!
I have been tackling inter-component-dependencies for my latest game and never really considered a sub-system solution as such as yours!
…but I was close!
One thing that I found really handy but yours is lacking is the ability to enable/disable any component, this has saved me lots of time with more than 12 components and you should consider using it too :D.
I am going to keep checking this site out, it is shocking how few comments there are for such a decent start-up blog!
G’day James, thanks for your comment!
I should just be clear that Artemis is not my system in any way, I’m just talking about it and praising it’s two authors whose work solved that same problem for me. That said, what benefits do you get from disabling components? I was discussing with the authors a while ago whether it’s more ‘correct’ to simply remove/add a component as it becomes relevant or not, or to have an ‘enabled’ flag like you describe. There was no clear answer, so it’s always interesting to hear arguments.
Anyway, hopefully you can find something useful on the site! It’s not reeeally a start-up blog unless I have a product to start up with, and it’s a bit slow atm as I’ve been taking a bit of time off over summer to pursue a few other new hobbies and rest my programmer’s hat for a bit. My current obsession is aquaponics, which I hope to write a bit about and eventually write some code for, whatever it may be. I will be back though! Couple of weeks tops.
One of the benefits for enabling/disabling a component is that the component system is decoupled from being able to modify the existing repository of components, this has proved to reduce complexity of games I make as I have no way of screwing stuff up the repository per system ^^.
Another benefit is that I can write “modules” of code responsible for activating/deactivating a group of components.
This makes life easier, for example a module “Go2D” could be written to disable all components required to render and move a 3d model and then activate everything to do with 2D.
… Allowing me to switch between 2d and 3d displays without having to integrate new/old components into the component repository!
I am currently working on such as system and will be writing some (well needed) articles on my site soon hopefully.
Looking forward for the next post!
Ah, I see. Modular usually equals good, so that sounds promising. Personally, my goal for a system like Artemis is to break down every behaviour into an atomic, ‘perfect’ component, similar to the way one might implement an algorithm, where there is exactly one correct set of parameters and functionality, and the same code can be used anywhere the algorithm is relevant.
My hope is that eventually you could build up a repository of such ‘prototypical’ components, and any character could be created simply by dragging and dropping individual behaviours into the entity-bag. For instance, no entity should know whether it’s in a 2D or 3D display, it should just have an X, Y and Z coordinate. The ability to move does exactly one thing: update those values, subject to a ‘full’ set of parameters (such as physics, maximum values, etc.). In theory, to go 3D all you change is the camera system, like MVC to the extreme. You could also change collisions for instance (since 2D detection can be done more efficiently), but it wouldn’t be necessary. Then really the only major custom code would be collision handling, which there are various ways of modularising (such as a recently released online game creator whose name I forget).
Of course, it’s great in theory, but as soon as you start implementing certain dependencies start to crop up. But of course that’s just where the fun starts!
When I first started developing component systems that was one of my initial aims to make each component completely self reliant and *atomic*.
This concept still remains stronger than ever, which sounds like Artemis also understands and makes me feel like I am on the right track at least.
One problem that is constant with component system development is how to get the components to communicate.
This is where your idea of just using x,y,z ect comes into play, by having such feature it is somewhat attempting to combat component communication conflict-ions (such as a 2D movement interacting with a 3d vector).
I advocated not to follow such style as it makes each component try harder to fit a generic set of behaviour.
If it remained that way every component that works in world/local space will end up working in 3d. Every thing else will be translated, which on some of the frameworks including XNA 4 would be a major issue, as rotating a 2D image via the x,y,z planes is fiddly…
Not to mention many 2D games are purely 2D and visa versa for 3D.
The end result for me would be to have 2D and 3D components, which at first would sound like lots of duplication of code until at a closer look, most of the 2d/3d differences are fairly large. Meshes VS Textures, rotations via radians vs quaternions and matrices ect.
Saying all of this, its early days for me and I have a long way to go. I will probably write my dissertation on this stuff one day…
I know what you mean with the large differences, and yeah, I think it is certainly reasonable to lock the used into 2D or 3D, since it’s unlikely to change and especially since many game engines put those kinds of restrictions on you. The only potential problem really is the slippery slope, by which you might choose to ‘unpivot’ other elements (such as physics engine v.s. basic movement animations, single entity v.s. composite entity, etc.). I’m sure it’s a problem that can be solved somehow however, and I probably won’t be the one to do it, so best of luck to you! It would be an awesome research topic if ever there was one.
Hi Pie!
Thanks a lot for your introduction to Artemis. This is very helpful
My pleasure! The more the merrier. It’s a pretty great framework; hopefully you can do some pretty great things with it.
I received an email today about accessing entities in entity systems other than those that explicitly specify their components? I wrote more than I expected to so I thought I’d copy it here in case it was useful.
___________________________________________
“What you said sounds right: if you extend an EntitySystem, your constructor should call the superclass constructor with a list of Component classes (such as
super(ColorComponent.class, PositionComponent.class);
). This means that a Bag (unordered collection) of Entities is passed to the processEntities method, and in that bag is every entity containing ALL of the component classes mentioned in the constructor.If you’d like to access entities in other contexts (i.e. if their components are not specified by the EntitySystem), you have a couple of options. One is to add the entities of interest to a group, and access them via the GroupManager (anywhere in the application). For example, in my Artemoids code, see the EntityFactory (creating a bullet has
missile.setGroup("BULLETS");
) and the CollisionSystem (ignores the entity bag, and directly retrieves the entities of the groups “BULLETS” and “ASTEROIDS” viaworld.getGroupManager().getEntities("BULLETS");
).Alternatively, you can do a similar thing using the TagManager. The (only, afaik) difference is each entity can only have one group, but many tags. I don’t think there is a (simple) way to manually retrieve the set of all entities containing some given component types, since these sets are pre-calculated by the entity systems behind the scenes. If you really want to know, I’d recommend you dig into the EntitySystem source or ask the Artemis developers at Gamadu.
Hope that helps!”
Pingback: Artemis: the Greek goddess of software architecture | star-fu.tv
Pingback: The Entity-Component Model « StrikerX3's Adventures
Pingback: Universe: Heads Up
One word: Awesome.
I never heard of Artemis and the Component vs System approach, and it sounds awesome. Thank you for this article !
Pingback: A hybrid Entity-System-Component architecture | Game Dev Rubber Duck
Pingback: ES Architecture. | Seed Of Awesome
Hi Pie21!
Thank you very much! Article is really very helpful!