Artemax: A component based entity system.

Community Forums/Showcase/Artemax: A component based entity system.

Wiebo(Posted 2012) [#1]
Hi there,

I've been busy porting Artemis (http://gamadu.com/artemis/) to Blitzmax. It is a high-performance data oriented, component based entity system.

I think this is the first component based system for blitzmax.

Why use a Data Oriented Design entity system instead of Object Oriented Design? It avoids the pitfalls of game object OOD designs: large, monolith, inflexible game objects. It also makes code (systems) very easy to re-use, as there are minimal relations to other systems.

The module is located in the download section of my google code page: http://code.google.com/p/noisycode/
The download also contains a simple (very simple) asteroids clone to show how to build a game using this system. The game includes a few sample systems for you to look at.

To play: Use arrows left and right to steer, arrow up to thrust, enter to fire, R to restart, ESC to quit the game.


Here is a little snippet from the website explaining the system:

Mini guide/about
So, how does it work? While we cannot explain entity/component paradigm here (there are other better articles out there) we can explain how you use Artemis to accomplish separation of data and logic, including rendering.

The main concepts in Artemis are: Entities, Components and Systems. There are other things in there as well, but they are mainly meant to facilitate those three things and make things "go".

Entities
Entities are very raw and basic, think of them as a identifier for an entity. An instance of Entity is meant to identify that entity throughout the system. The most important aspect of Entity is the entityId, which no other living entity has in the system.

Components
Components are pure data classes, they do not have any logic in them other than that for setting/getting the data. An example component would be Position, containing only X and Y coordinate values, and an allowed set method would be setPosition(x,y).

All components extend Component, which is meant to identify the components in the framework.

Systems
These are really the most important aspect of the framework. Entity systems are meant to process certain aspects of entities. An entity aspect means that a entity possessing certain components that enable it to be processed in a certain manner but one or more systems. One system processes only one aspect.

An example aspect be Movement, which would process an entity aspect consisting of Position and Velocity. The system that would process such an aspect could be called MovementAspect and would contain the logic necessery to move entities around according to their Position and Velocity, setting and getting whatever data it requires.

Entities do not communicate between themselves, but systems can communicate with other systems. Use the SystemManager to retrieve a system within another. Systems can provide whatever API necessery for inter-system communication.

The framework bundles a few EntitySystem implementations that can be extended, depending on the usage, be sure to read the JavaDoc description on all EntitySystem implementations and be sure to understand them, because choosing the right EntitySystem can provide a significant performance boost.


Htbaa(Posted 2012) [#2]
I skimmed through the source code of DemoRocks and I think I've gotten the general idea. It sure does like a clean way of programming. The way you apply components to entities makes me think of roles/traits in certain programming languages (at least in concept). With the added benefit that you can do it dynamically here.

I feel I'm not doing enough with BlitzMax and really should do some game development again, for which this system would be perfect.

Very nice!

Update: One thing I do wonder about is performance. You'll probably be using a lot more objects for a single entity than 'normally'. At least it's going to use a little bit more memory I think.

Last edited 2012


Wiebo(Posted 2012) [#3]
Hi,


Are you wondering about performance or memory usage?

Performance:

The system does not use lists, or enumerate classes to find components. Everything is referenced, and lookup is fast. Processing is also fast, all array based, no linked lists etc.

Of course, there is a bit of overhead. But the flexibility gained is what you are after. What you also gain is great reuse-ability of code, as systems are self contained (if you design them the right way)

And as blitzmax is aimed at desktop gaming, I don't think there is a problem.


Memory:

I agree with you that in small games it would make more sense to just create a gameobject and extend it for each type of gameobject you need. This will surely consume less memory. For larger implementations, and for systems where you need a lot of flexibility in gameobject structure (for instance, an RPG)

I also find that creating large objects with lots of unused code (even though it is only references to code) is messy and reeks of bad design.

This system is insanely flexible. You can create and modify object structure at run-time. Think of a tank which owns a weapon component. You can change the component in the tank at run-time to make it use a different weapon.


Htbaa(Posted 2012) [#4]
I was wondering about both actually. Is there really such a big difference in performance with lists and arrays? When assigning new stuff you will have to resize the array.

I think I'll play with it sometime soon, if I have the time for it :(.

Also, kudos for the unit tests. I still find myself not to do them enough.


Wiebo(Posted 2012) [#5]
Well, there is not much of a difference when iterating through them in a first to last manner. Random access has more overhead though. But this system does not use random access: because of the use of arrays everything must and is referenced. No random access or search through collections required.

Unit testing saves LOTS of time during development. You have basically created a complete test application when you are done, which ensures that your code works when you later implement it in a larger project.
I could never go back to compile-test-bug fix-compile-repeat development. Sure, you are doing essentially the same while making the unit tests, but all tests are contained and bugs are easy to spot: they MUST be in the code you added after the last test.


Guy Fawkes(Posted 2012) [#6]
SWEET system! :)


Htbaa(Posted 2012) [#7]
Oh I totally agree on unit testing. The Maximus webapplication is completely unit tested. Sadly for my BlitzMax stuff I've never got to it. Never too late to start with it, though it does make it a bit harder to get stuff covered that way.


Wiebo(Posted 2012) [#8]
Thanks Tundros :) I hope it will be of use to you.

Htbaa: Yes, I had to really push myself as well. It's weird in the beginning but now I cannot think about development otherwise.


Wiebo(Posted 2012) [#9]
For those interested in this awesome entity system: I am currently creating a set of default systems and components which will be easily extendible. For this I am also creating a little game engine framework to get things up and running really fast. This engine will also be at the core of a new game I am developing right now.

Reading the wiki pages I am setting up might shed some more light upon the proceedings and intentions: http://code.google.com/p/noisycode/wiki/game2d

Feel free to send me feedback or ask if you want to know more...

[edit: lots of typos]

Last edited 2012


Blitzplotter(Posted 2012) [#10]
A very interesting project Wiebo, I wish you well with this and hope to try it out soon, had a quick scan of the wiki pages - looking good!


Wiebo(Posted 2012) [#11]
Thanks Blitzplotter! It will indeed be very interesting to see how this develops, as I am using it for my next game project.


Neuro(Posted 2012) [#12]
Was just reading a little more about this concept today. Looks interesting and looking forward to see how it progress :).


Htbaa(Posted 2012) [#13]
So I just started playing around with this and I think it's pretty cool. Just to make sure, a System will only process entities that have the components that are registered with it, right?

Basically all logic would go into systems. What I was wondering about though was when you have an influence map would that be managed and generated by a system as well? And how can Systems communicate with each other?

It does require a bit of a different mindset to get everything tied up together though. But that's good, keeps you thinking and makes you learn new stuff :-).

Edit: Wiebo, what's the difference between tags and a group in Artemax?

Last edited 2012

Last edited 2012


Wiebo(Posted 2012) [#14]
@Htbaa

Yes, all logic should be within a system. I'm not sure what you mean with an influence map. Can you explain?

The difference between a group and a tag is that you can only one entity with the same tag. Use groups if you need to 'tag' more entities with the same name. Tag is a bit faster though, so preferred when you only intent to label a single entity.
Groups and Tags allow you to quickly locate an entity, while not relying on components.


Htbaa(Posted 2012) [#15]
You could use an influence map in your path finding algorithm. Instead of going to the set target right away you could calculate a path that avoids contact with any enemies. Using the location of all enemies you decide in which part of the grid they belong and add a score to that cell.

More on influence maps: http://gameschoolgems.blogspot.nl/2009/12/influence-maps-i.html.

Thanks for clearing up the difference between tags and groups. Why is it that an entity can only be assigned 1 group? That seems a bit limiting. For example, take units in a RTS game. They can be soldiers, vehicles, and can be subclassed as well; rifleman, grenadier, light tank, heavy tank, etc.. One group doesn't seem to cut it. What would your suggested solution be for this situation? Add components to the entities that describe this?

Edit: I'm also finding http://slick.javaunlimited.net/viewtopic.php?p=20885 an interesting thread to read about Artemis. Very helpful.

Last edited 2012


Wiebo(Posted 2012) [#16]
Hi Htbaa, thanks for asking and using the system.. It's ideal for RTS games, I think. You can easily create awesome unit combinations and such.

As for the grouping limitation you mention: Why would you want to group units that way? In your example of military units, you could use groups to form squads. These squads can consist of different kind of units, as you mention, but you don't need a group for each type of component combination (entities are only in the framework as a way to group components, classes and subclasses are non existent in this framework) You could create a squad system to keep track of these units, though.

So yes, a rifleman would carry the components "soldier" and "rifle." A grenadier would be a combination of "soldier" and "grenade thrower." I would create systems for each combination, to fine-tune behaviour if needed. If a simple 'fire' instruction to the weapon component would be enough then a single soldier system would be enough for all ground troops. The real fun starts when you allow the units to pick up different weapons. You would only need to replace the weapon component and you're off.
Same goes for tanks.

You can create a system for influence maps. The system manages the grid, and entities can carry an 'influence' component. This component can report the grid position of the unit to the system and its weight. The system can find and update the components because they are registered to it.

System communication is not that hard. You can add a reference to another system into your system and add some sort of communication interface. It's not against the framework concepts to add some references.

Last edited 2012


Htbaa(Posted 2012) [#17]
Hmm I see. And how would you for example only select allied or enemy units, that have the 'aircraft' component. I understand you can create a systems for that for every kind of combination. But it seems to me this can get a bit tedious. Take for example a Select Target System. Not every type of unit can attack an airplane for example and it doesn't seem very effective to me to iterate over all units, instead of only the ones that the current unit can actually attack.

Maybe my understanding of the system isn't quite there yet. Mainly thinking out loud. It's a real paradigm shift working like this.


Wiebo(Posted 2012) [#18]
How to select allied or enemy aircraft units: Give each entity a 'allied' or 'enemy' component. you don't need a system for these components, they are to identify the entity. Then, each entity which also has the 'aircraft' component is registered to the aircraft system. The aircraft system can create a list of entities registered to it with either the 'allied' or 'enemy' component.
Identify components are very handy. In the demo game I use the 'player' component to identify the player entity to the playerinput system.

A 'select target' system would indeed be overkill, I would put that logic in the weapon system itself.

But let's be realistic here: You WILL write a lot of systems. This framework will not enable you to write less code. It will enable you to better contained, re-usable code. The logic code is MOVED from the game objects to the systems.


And I agree: it's another way of getting things done. In the end, it will pay of though, I am sure of it. That's why I ported it to blitzmax (and will port it to monkey)


Htbaa(Posted 2012) [#19]
Thanks for the answers. I'll play some more with it. I'll come back if more questions pop-up :-).


Wiebo(Posted 2012) [#20]
No problem! Please do.


Wiebo(Posted 2012) [#21]
These past few days I've been adding systems: Quadtree, Collision, LayeredRendering. Right now I'm working on a LUA system which will eliminate the need to make a system for each game object. I'm using Noel's LuGi module for max/LUA integration. Trying to come up with a decent interface to and from LUA is what I'm doing now.
I think I make a small asteroids game again, using LUA for all logic.

Last edited 2012


RustyKristi(Posted 2016) [#22]
I'm curious about using an entity system and I found this but I have trouble building the test unit with this

"Identifier Export not found", under artemax.mod/test/source/t_entitymanager.bmx

w.Export(s)


all includes works bt except for that one.