Designing Bomberman with an Entity System: Which Components?

Today I found a new article on implementing a Bomberman clone using an Entity System (in C#) – but I feel it doesn’t quite work.

It’s a well-written article, with some great illustrations. But the authors “Components” struck me as over-complicated and too behaviour-focussed. If you’re designing a game based on an ES, this isn’t a great way to do it – it feels too much towards old-style OOP gameobjects.

This is an opportunity to talk about good and bad directions in Component design. I really like the author’s idea of using Bomberman as a reference – it’s simple, it’s a well-known game, but it’s got a lot of depth. Read the original article to refresh your memory on Bomberman and how it works. Then come back here, and we’ll do a worked example on choosing components for a game. I’ll completely ignore the programming issues, and only look at the design issues.

Choosing your Components

Design rules for Components (rules of thumb):

  1. Components are data, not code
    • …game-state, not functionality
  2. Components are as small as possible
    • …atoms: the smallest set of data possible, for a particular aspect of the entity
  3. Components never share data
    • …in Database terms: everything is Normalized (Google it)
    • …if data should be in two components, but you can’t decide which: create a third component for it

Looking at Bomberman

List the behaviours, list the data

This is an iterative process. I start with two lists written at the same time. Writing items in one list often makes you think of something that’s needed in the other list, so you keep jumping back and forth.

Here’s a first draft (probably incomplete, but it’s a good start):

Behaviours: Bomberman

  1. move a player up/down/left/right
  2. drop a bomb
  3. detonate a radio-controlled bomb
  4. kick a bomb
  5. jump one space (some versions)
  6. teleport a player (environmental)
  7. kill a player (environmental)
  8. upgrade a player’s FUTURE bombs (don’t affect the ones already on floor)
  9. dissolve a block
  10. spread/block the explosion according to several possible rules (depends upon multiple factors)

Data: Bomberman

  1. Position of each player in pixels (for visual representation)
  2. Cell that each player is standing in (for the game logic)
  3. bombs in play
  4. fuse-time left on each bomb
  5. explosion logic for each bomb (tiles covered)
  6. explosion logic for each bomb (tiles affected)
  7. explosion logic for each bomb (tiles that block / shadow the coverage)
  8. score for each player (number of kills, number of deaths)
  9. positions of all solid blocks
  10. positions of all soft blocks
  11. positions of all powerups
  12. positions of all special features of environment (e.g. teleporters)

Convert Data into Components

(remember: stick to the rules for designing a component)

My preferred way to do this is convert ALL the data into primitive data types (i.e.: int, float, string, boolean, enum, list, map).

For a simple game, you should never need “list” and “map”

The ones I tend to use most often: enum, float, int, boolean, string

This list often contains duplicates; that’s fine, we’ll come back to it in a sec.

All data, converted into primitives

  1. Position of each player in pixels (for visual representation)
    • position.xpixels (int)
    • position.ypixels (int)
  2. Cell that each player is standing in (for the game logic)
    • position.xcell (int)
    • position.ycell (int)
  3. bombs in play
    • position.xcell for each
    • position.ycell for each
  4. fuse-time left on each bomb
    • fuse.secondsLeft (float)
  5. explosion logic for each bomb (tiles covered)
  6. explosion logic for each bomb (tiles affected)
  7. explosion logic for each bomb (tiles that block / shadow the coverage)
    • this is where it gets tricky: the data you store is heavily dependent on how you intend to write the “behaviour” code later on. Let’s skip it for now
  8. score for each player (number of kills, number of deaths)
    • score.kills (int)
    • score.deaths (int)
  9. positions of all solid blocks
    • position.xcell
    • position.ycell
    • we could assume that “default” squares are solid, or empty. Let’s assume “solid”, so that anything off the edge of the playing area is inaccessible by default
  10. positions of all soft blocks
    • position.xcell
    • position.ycell
    • solid.isSolid (boolean)
    • material.hitpointsRemaining (int)
  11. positions of all powerups
    • position.xcell
    • position.ycell
    • powerup.type (enum)
  12. positions of all special features of environment (e.g. teleporters)
    • position.xcell
    • position.ycell
    • solid.collisionEffect (enum)

Components, after some wrangling

Now … spend some time looking at that list and thinking about it. Think about duplicates: all those “position.xcell” items – ARE THEY REALLY THE SAME THING?

(if they’re not, if some of them are “sort of the same, but actually different – and might change in future”, then you need to have two types of Position component. This already happened right at the start when I realised that the “on screen” position of the sprites is similar-but-different from the cells in which each bomb sits. One is finer granularity than the other. A very simple implementation of Bomberman could have them the same component – but it’s obvious that you’d want to “upgrade” this after only a few builds, and add pixel-perfect positions, because it looks so much better)

  1. CellPosition
    • x (int)
    • y (int)
  2. ScreenPosition
    • x (int)
    • y (int)
  3. TimedEffect
    • timeRemaining (float)
    • effectType (enum: EXPLODE1, EXPLODE2, VANISH)
  4. Explosion
    • distance (int)
    • affectsSolids (boolean)
    • affectsSofts (boolean)
    • affectsPlayers (boolean)
    • penetratesSolids (boolean)
    • penetratesSofts (boolean)
    • penetratesPlayers (boolean)
    • damage (int)
  5. PlayerBombs
    • …everything from Explosion?
  6. Score
    • kills (int)
    • deaths (int)
  7. Destroyable
    • hitPoints (int)
  8. Collideable
    • blocksPlayers (boolean)
    • blocksFlameDamage (int)
    • addsFeature (enum: FLAME_LENGTH, BOMB_AMOUNT)
    • triggersEffect (enum: DEATH, SELF_BOMBS, TELEPORT)

That was my first attempt. It is poor: by the time I got to the end, I’d changed the way I was thinking about concepts compared to the beginning. The list above is self-contradictory, it has to be re-done

By the end, I’d realised a couple of things. Firstly, the “data” of explosions can be used to model most of the flame Behaviours, so long as we treat each “flame” square like a depth of water that “flows” to either side, getting weaker by one point each time it moves an extra square.

Secondly, I noticed that my “Explosion” component was getting very large – remember: Components should be as small as possible.

Thirdly, the enums inside my Collideable were very non-homogenous. i.e. they seemed to be serving a lot of purposes at once. This is a warning sign with ES design: “heterogeneous data” is what your Components are for: heterogeneous enums suggest you need to split your Component

So, we have two big changes to make on a second draft. We’re going to re-define everything to do with explosions in terms of “water that flows”, and we’re going to split two of the components into smaller pieces (one because it’s “too big”, the other because it’s “too heterogeneous”).

Components, Attempt 2

  1. Explosion
    • power (int) — decreases by 1 each square it spreads. At 0, it runs out.

I got this far, and realised: “power” suggests “damage” — but what I really mean here is “spreading power”. I thought for a moment: could I ever want to use this spreading effect for something other than damage?

Yes! What about a powerup that “explodes” in a radius? Cool. It would be EXACTLY THE SAME thing, but it proves the name I’d chosen at first was a bad one.

So, I hastily renamed both the Component and that attribute:

  1. CellPosition
    • x (int)
    • y (int)
  2. ScreenPosition
    • x (int)
    • y (int)
  3. TimedEffect
    • timeRemaining (float)
    • effectType (enum: SPREAD, VANISH) — simplified now: spreading is neatly contained inside Spreadable below.
  4. Spreadable
    • depth (int) — decreases by 1 each square it spreads. At 0, it runs out.
    • spreadPattern (enum: FLOW_AROUND_OBSTACLES, FLOW_CARTESIAN, FLOW_IGNORE_OBSTACLES ) — the Behaviour will interpret these
  5. Score
    • kills (int)
    • deaths (int)
  6. Destroyable
    • hitPoints (int)
  7. Collideable
    • height (int) — if height > Spreadable.depth, we flow AROUND instead of OVER. Also, we can give players a “height” they can move over. This also lets us implement “jumping” in terms of increasing (for a single step) the height you can move over (makes it easy for us to have “jumpable” and “non-jumpable” squares).
  8. Damager
    • inflictDamage (int)
  9. BombLayer — (something that lays bombs … not a rendering “layer”)
    • spread (int)
    • depth (int)
    • damage (int)
  10. Teleporter
    • cellsDeltaX (int) — +1 = right one square, -1 = left one square
    • cellsDeltaY (int) — +1 = down one square, -1 = up one square
  11. PowerupPlayer
    • addsFeature (enum: FLAME_LENGTH, BOMB_AMOUNT)
    • amount (int) — +2 has double the effect, +3 has triple, etc

Exercises for the reader…

There’s a bunch of holes in what I’ve written above; this post is meant to be indicative of what I’d be doing, rather than a complete game-design document. At this point, I think you have enough to fill in the blanks easily – if not, post in the commments and I’ll add some more info and guidance.

In particular, I look at this and ask the following questions:

  1. Without changing anything, can you implement powerups that disappear if not collected quickly enough? (easy)
  2. …what about: powerups that disappear when the player walks on them? (less easy)
  3. How do make a powerup that’s very powerful, but has a risk of doing something nasty to the player – e.g. teleporting them when they collect it?
  4. Or a powerup that has a chance to kill the player outright?

Consider the possibilities of your new Components

I like to do this as a sanity-check that my Components are as flexible as they should be. But … it’s also inspirational to look at your system and see what emergent features it’s already created.

We look at our components and take odd pairings we didn’t intentionally design, and ask what would happen if we put them together.

e.g.: “TimedEffect { timeRemaining = 2, effectType = SPREAD }” + “TimedEffect { timeRemaining = 4, effectType = VANISH }” + “Spreadable { depth = 3, spreadPattern = FLOW_CARTESIAN }” + “PowerupPlayer { addsFeature = FLAME_LENGTH, amount = 2 }”

  • Armageddon!
  • Drop one of these when the level reaches a timeout (e.g. 5 minutes), and it will spread through the level, powering-up every player it hits, and fading away as it passes, like a wave rippling outwards
    • This behaviour/feature is entirely automatic, requires zero additional code!
  • I set the VANISH to take two more ticks than SPREAD, on the assumption that my “spread” behaviour will only spread into tiles where the effect doesn’t already exist. That’s a sensible implementation.
    • …this way, the spread is always outwards, because the inner ring of “about to fade” blocks prevent the spread going backwards into the middle again
    • If you tweaked that Behaviour (maybe add an extra flag to Spreadable, e.g. “(boolean) spreadsIntoTilesAlreadyPresent”), you could make this into a reverberating wave, that bounces back and forth forever across the level.
    • You could make a whole level around this: have a couple of waves that bounce back and forth giving powerups, and have no other powerups in the level. Players get powered up rapidly by the waves washing over them…

Did this post help you?

You can say “thank you” by giving me your email address, and letting me contact you next time I make a game of my own:

78 thoughts on “Designing Bomberman with an Entity System: Which Components?

  1. Tomas Sedovic

    Thanks, this made things a lot clearer. It’s always great to see concrete examples. You’ve mentioned that for simple games, the components needn’t use lists, maps, etc. Where would you find them acceptable, then?

    For example a character’s inventory in an RPG seems like a good fit for a list to me. Ditto for characters’ abilities.

    What about game areas (much) larger than a screen? It seems all right to just give all the rendered entities a Position component in the bomberman example. Would you do that in case of Fallout (1, 2) or Baldur’s Gate? There you have a lot of independently acting NPCs and a lot more clickable items.

    To detect what entity the user just clicked on or to handle collisions, you’d have to iterate over all the clickable entities, wouldn’t you? Or have to keep a position->entity index of some sorts — e.g. by having the positions of all the entities stored in a single component belonging to the Game Board entity.

  2. adam Post author

    @Tomas

    “components needn’t use lists, maps, etc. Where would you find them acceptable, then?”

    That depends on your implementation. With a basic ES, you could simulate them using other components (e.g. a list is “all components that have the magic variable LIST_ID with the same value”). With a more advanced ES, you may have support for them directly.

    HOWEVER … anything of variable size makes it harder when you come to do generic data-manipulation (e.g. performance optimization, e.g. serializing to disk, e.g. sending over the network), so it’s not something to use until/unless you need it.

    On a large project, I’d expect to need it, and would try to build it in from the start – but small projects are probably way out of their depth / off course if they’re already using lists/maps.

    ” character’s inventory in an RPG seems like a good fit for a list to me”

    I’d say that’s a good example of why you should avoid lists.

    Inventory is naturally a fit for e.g. an “InventoryItem” component, which stores info like: when it was added to the inventory, which inventory slot it occupies, whether it has an active curse (can be removed – or needs a remove-curse casting first), etc.

    Since you need to record all that data anyway, and you need to do it in components … your list is a waste of space: “anything that has the InventoryItem” component is a much clearer (and less error-prone!) definition of the inventory contents…

  3. adam Post author

    @Tomas

    “What about game areas (much) larger than a screen?”

    You’re over-thinking this.

    In every game the problem here is the same and the solution is the same.

    Storing your positions in entity/components changes nothing here.

    If you’re going to have – say – 100,000 enemy AI on your world map, then you’re going to partition the world map, and probably have a two-level co-ord system (regional + local, where 1.0 in regional = 1,000,000 in local units, or similar)

    “It seems all right to just give all the rendered entities a Position component in the bomberman example. Would you do that in case of Fallout (1, 2) or Baldur’s Gate? There you have a lot of independently acting NPCs and a lot more clickable items.”

    Yes, why wouldn’t you?

  4. Mike Leahy

    @Tomas / Adam

    Really the “relational mindset” so to speak only applies to one type of basic ES implementation. It’s not a gold standard per se; an interesting thought experiment put forth by Adam, but it needs a full fledged and complex use case / game to prove it.

    If you had to query or write some some algorithm to walk over all sub-entities attached to a parent entity and check for the “InventoryItem” component in every single sub-entity attached to collate or iterate over entities that are considered an inventory item that is extremely inefficient. It could work if this is a function that is not called all the time and not in a real time use case. At a certain low entity count this operation will take far longer time than it should. If your game has 100 entities max… Fine… 500? 1000? 20000? 1MM? Yeah.. Not so much for the latter use cases.

    If this mechanism is duplicated and used for a query that is used in a frame by frame basis over many entities… forget about it…

    But as Adam mentioned more advanced ES implementations make handling lists and in particular storing components implicitly in lists fundamental operations. Without lists / iteration being a central point of a component architecture / ES then one misses out on a fundamental and really useful and respectably fast design pattern which is “extension by iteration”.

    If someone was rolling their own ES from scratch, then yeah, starting without lists for trivial use cases is a good recommendation and interesting thought experiment. Lists and other fundamental collections should not be excluded in more than basic ES frameworks / implementations. The complex matters of serialization for lists and other collections use cases should be well worked out by the ES implementers such that end developers / users of the framework are not burdened by the underlying complexity. IE it’s not a complete reason to eschew lists with ES frameworks. However, if one wants to get something up quick and dirty rolling their own ES then sure avoiding lists is a good suggestion.

    There are many ways to make quick sorting in lists happen _automatically_ even when implicitly adding / removing sub-entities (potentially items, etc.) to parent entities. I’d also argue on introspection of an entity that this auto-sorting provides much better introspection capabilities especially when the queries and components necessary to recreate a collection of “X type of” entities is unknown.

  5. Andrew

    Hi Adam,
    I’ve faced with race condition problem, when some systems was never executed, because other systems broke conditions of execution (change or delete components or entities – change game-state in short). Quick fix for this is to register systems with engine in specific order.
    To resolve this I’ve split execution into two steps: read and write. On Read – systems don’t change game-state and just read it and make decisions for future changes, on Write – systems apply this decisions. As a bonus I now able to run systems on each step in parallel.
    What do you think about this race condition problem ?

  6. Tom H.

    Andrew, what’s the architecture that you’ve got that is creating this “race condition”?

    Every entity system I’ve worked with or looked into deeply always registers all systems in a specific order, and gives them a chance to execute in that order every frame. Getting that order right is pretty critical for controlling your game’s input latency.

  7. adam Post author

    @Andrew

    That’s a common approach. Ideally you want copy-on-write, so that all systems see the same data, and writes don’t appear in the data / components until the next frame.

    Depending on your language, this can be relatively easy to setup using indirection on the components: reads are a straight read, direct from a struct (perhaps) – but writes are captured and diverted to a copy of the component, and your overall game loop looks at all the “written-to copies” when the frame is over, and splats the changes onto the master data.

    …this is also useful for (some) networking implementations: your networking is invoked on the “set of components that were written to”.

  8. Andrew

    @Adam

    My first thought was something like this, but I didn’t want to add extra code to components, so I came up with “steps” solution. I don’t like this, so I’m going to work out “copy-on-write” solution.

    I have one more question.

    Events.
    Consider this situation. I have few entities with ColliderComponent. CollisionSystem processes these entities and attaches CollidedEvent component to entities, that have collision. Other systems can now process entities with CollidedEvent, and change them (reset Velocity, change Position, do Damage etc.).

    This raises few problems:
    – who should remove CollidedEvent after all systems finished processing (I think CollisionSystem on next update should remove “old” CollidedEvent, but what if one event come from different systems);

    – on first frame CollisionSystem finds all collisions and attach CollidedEvent, other systems make other changes; after first frame I apply all changes (copy-on-write); so second-frame game-state is different from game-state when CollisionSystem is working (I think this is OK);

    – on first frame CollisionSystem finds all collisions and attach CollidedEvent; on second frame CollisionToDamageSystem grabs all CollidedEvent entities and attach DamageEvent to them, and only on third frame DamageEvent will be processed; so it takes two frames to do damage on collision. if we want more “event transformations” it will take more frames to react on this events. Is there a way to make it all happen in one frame ? (I think components and events should be split and processed differently somehow)

    Ideally, I want something like: to add new behavior I just need to create new System, grab needed Events and process them somehow (change entities, create new events etc.)

    P.S.: just realized, that “events” looks very similar to components, hm … , but I think they are not the same. Components is a data, from which entities is constructed, but events is a rules for system to process entities. I’m totally confused.

  9. adam Post author

    As TomH put it … you could just make setup your systems to execute in a hand-configured order, so that:

    FRAME1: collision system goes first, finds all collisions, moves objects backwards (if needed) to un-collide things that are solid, attaches “collided” components
    FRAME 1: … all other systems (in whatever order, collision system don’t care) process the info

    FRAME2: collision system deletes all “collided” components.
    … and carry on as per FRAME 1…

    The key here is that you don’t remove components DURING a frame, and that every system always fires in the SAME order.

    That way, even the system that fires “last” gets a consistent set of data:

    FRAME 1: 5 x systems add new components
    FRAME 1: last system sees the new components and acts. Adds its own components

    FRAME 2: 5 x systems “see” the “new” components from “last system”.

    — in reality, we’re now on frame 2 – but so what? who cares? “2” is a meaningless number. What MATTERS is that each system sees: “1 x frame has happened since I was last called”

    FRAME 2: last system deletes its old components, and adds the new set for “next” frame…

  10. adam Post author

    NB: this is really nothing to do with components / entity systems – your questions are really about:

    “how do I write code / game logic for a game that runs with a single global Game Loop?”

    If you google for resources on game loops, and central event loops, and scheduling “game ticks” and “game update”, you should find some good resources.

  11. Matt

    @Adam

    I have another question around the inventory items. How would you link inventory items to a player vs an npc? Would each “InventoryItem” component contain an OwnerId? So let’s say the player was buying something in a shop or retrieving an item from a chest, would you just change the ownerId?

  12. adam Post author

    @Matt It all depends what kind of inventory you want to have – which is a game-design choice. Your approach works fine.

  13. Toboi

    Hi.

    How do you exchange information between two systems?
    In your example you have

    CellPosition
    x (int)
    y (int)

    ScreenPosition
    x (int)
    y (int)

    ScreenPosition depends of CellPosition I think. So maybe you implement an MovementSystem that moves the CellPosition, but how does your rendering system get the changed CellPosition to calculate the new ScreenPosition? ATM I think I understood the overall concept of ES, but this is the point at which I fail. How do I exchange Information (Position is my most important data for this problem) between systems and components?

  14. adam Post author

    Firstly, in a typical setup, the renderingsystem NEVER writes to a position. It’s a renderer, not logic. Some other system is going to setup the screenpositions so that the rendering system can Do Its Thing.

    Secondly, you would normally calculate “the higher resolution number first”, and either ignore the low-res number (calc it later), or *only* use it in a limited sense where it makes it easier to calculate things. e.g. when going around a corner, it is sometimes easiest to write your algorithm to keep using the (updated-on-the-spot) value of “current, latest cell position” to check “have we rounded the corner yet?”.

    …but overall: in this post, I only talked about choice of Components, not choice of Systems (it would be good to have a followup post on choice of Systems – but I wanted to focus on Component choices first)

    So, in practice, your programmer would ask something like:

    1. how do I work out the screen position at all times?
    2. how/when/where do I allow inputs to affect this?
    3. what do I want to render at each moment?
    4. what logical value do I want the rest of the game to use at each moment? (cell position, used for positioning a dropped bomb)

    i.e. choose Systems something like:

    a. movement system samples the keyboard inputs, checks the cellposition from last frame, and decides which inputs to ignore, which to accept. It then applies some (or none) of that as small screenposition changes, and updates BOTH the screenposition AND the cellposition.
    b. renderer uses whatever the screenposition is
    c. bomb-laying system uses whatever the cellposition is
    d. collision detection / explosion system uses … probably the screenposition (although some versions/clones of Bomberman use cellposition for collision too).

  15. Toboi

    There is a one to one relationship between Systems and AVAILABLE aspects (i.e. types of Component). A System essentially provides the method-implementation for Components of a given aspect, but it does it back-to-front compared to OOP.
    Ok, so maybe I misunderstood this part of your ES-Tutorial.
    So this doesn’t mean that a system isn’t necessarily necessarily the implementation of just one component(in OOP-Terms)? I thought so, but as you describe the movement system in your example. I think I was wrong.
    But that brings to me another question:
    How does a system know which entities to handle, when there are more than one Component which gets processed by the system? What happens if it occurs that an entity has just one of maybe two Components which are changed by the system?
    So in your example, what would happen if an entity had just a ScreenPosition or just a CellPosition? How would the movement system choose which to handle and which not?

    However, if you are going to write a post about system choice, then I would really appreciate that!

  16. adam Post author

    Sadly, my wording on that was poor. Lots of people misunderstand it. I’m thinking of re-writing it to make it clearer.

    (it was only a guideline/starting-point/rule-of-thumb – and in practice you’d end up breaking it a lot once you were comfortable with ES design)

    “So in your example, what would happen if an entity had just a ScreenPosition or just a CellPosition? How would the movement system choose which to handle and which not?”

    Systems work on COMPONENTS, not on ENTITIES.

    ENTITIES do not exist!

    The nearest you get to having an entity is that you often say:

    “get me the component “SCREEN POSITION” that is on the same entity as this component I’m already looking at (“HITPOINTS”)”

  17. Toboi

    Ok, thank you for emphasizing this.

    But now I have another question: Is there a good solution when you have to access different components at the same time, i.e. at a collision detection system? In OOP I would just keep an array of Collidables or something like this, but is there a good solution the ES-way?

  18. adam Post author

    You should be passing a big list of data to your systems, with all the components pre-filtered into that list.

    (for efficiency, you should have generic code that lays-out that list as an efficient array or other data structure, in advance, so that your system can iterate over it quickly – but this depends a lot on your hardware and you need to read up on how/what data strcutres / memory access patterns your hardware wants/needs)

  19. Wellsy

    How would you approach a scenario where an entity requires multiple attacks where each attack has different settings?

    I would create an AttackComponent that stores a list of IAttack instances, is this a good way to go about it?

  20. adam Post author

    “attack has different settings” – by definition that either means you want a separate component-type per attack, or (if the “different settings” are all parameters – e.g. “strength” is always there, but it sometimes 1, sometimes 2) then the same type but separate instances.

    Which comes on to the “does your ES implementation allow multiple instances of the same Component-type per Entity?”. I generally advise: say “no” if you can; it makes a lot of coding easier. But if you’re happy with the implementation issues, go for it.

    If you’re limited to 1 component of each type / entity … you can of course create sub entities to hold the different components.

  21. Mike Leahy

    @Wellsy
    >I would create an AttackComponent that stores a list of IAttack instances, is this a good way to go about it

    This is kind of the only way to do it if your ES only supports storing one component per type. I haven’t seen many ES implementations in the wild that go beyond storing one instance per type.

    As a juxtaposition I generally advocate if rolling ones own ES (or searching to use one) to investigate being able to store multiple components by type in a list. I kind of mentioned the same sentiment already above. At minimum you need an “add” / “remove” / “getAsIterator” / “unsetCollection” methods. The implementation should not expose the collection which should be protected internally to the entity / component manager and is the reason for returning an iterator instead of the collection itself.

    In my efforts it looks like:
    entity.add(DATA, IAttack.class, new AttackData(etc, etc))
    entity.getAsIterator(DATA, IAttack.class);

    DATA is a static include for “IData.class” / a little syntactic sugar.

    Another possibility is to “componentize” your collections. IE make the collections components that can be stored directly if one wants to directly access the list on retrieval. There are some advanced generics gymnastic tricks (Java) which are a bit more difficult to work out than storing components by a collection internally. It’s quite possible to store parameterized components too which plays quite nicely with a component oriented collections API. IE in my efforts you can do this.

    entity.getAs(DATA, ATTACK_QUEUE);

    and retrieve a typed (IAttack, etc.) collection directly. That’s what the code looks like without going into the implementation details on how to make it happen.

    It seems a design waste and unclean code to me to have to create a data component whose sole purpose is to store a list of other things which really is just a way to get around the one instance per type limitation and lack of being able store parametrized types in most ES implementations presently in the wild. It’s more of a stop gap and not the proper solution and is more clutter in the class hierarchy particularly if one is using this workaround to store typed components in a collection. In any sufficiently large app / game the amount of holder data components would be too large if not unwieldy.

  22. Maximusya

    We are at early stage of prototyping our new game and decided to try Artemis Entity System(for C#).
    I have read your series of blog posts about ES and since this – the Bomberman – post contains an example of iterative design I’ll ask the question here.

    Game objects may have some resources attached to them (gold, mana):
    – in case of field units it is just the amount that drops off them when they die;
    – in case of a player it is the amount that he/she posesses;

    So GoldComponent and ManaComponent appeared (with a Value data property) and they are attached to various game entities. When a unit dies, it’s GoldComponent.Value and ManaComponent.Value are added to player’s GoldComponent.Value and ManaComponent.Value.

    But both Gold and Mana are Resources. And other types of resources may appear later. So I started to generalize. And since Artemis forces “one component per type” and does not support entity-to-entity relationship, Gold and Mana became separate Entities with ResourceComponent (with a single data property – Value) and an OwnerComponent to relate them with their parent entity.

    As the design document evolved, players’ resources started to regenerate.

    So I created a RegeneratingComponent holding ValueDelta and TimeDelta properties (i.e. resource regenerates at a rate ValueDelta-per-TimeDelta).
    Unit’s Gold and Mana entities now have a ResourceComponent,
    Player’s Gold and Mana entities now have ResourceComponent, RegeneratingComponent.

    Then we (expectedly) decided that player’s mana is actualy going to be a Mana Pool: i.e. a resource with a cap.

    So I created a CappedComponent with a MaxValue property.
    Unit’s Gold and Mana entities now have a ResourceComponent,
    Player’s Gold entity now have ResourceComponent, RegeneratingComponent.
    Player’s Mana entity now have ResourceComponent, RegeneratingComponent, CappedComponent.
    ResourceRegeneratingSystem operates on enities with {ResourceComponent, RegeneratingComponent}, and has a switch in the code whether the entity has a CappedComponent.

    Then I realised that this way things may get “overnormalized” i.e. I am heading the path of separating every single data property into a component.
    And there would be very smart Systems (or too many dumb System) that would know how to operate with all this data.

    The game is about players commanding armies of fighting units – and not about resources, not about Weapon-entities damaging Health-entities!
    I want unit-entity to hurt unit-entity as determined by their Weapon-component and Health-, Defense-components! I do not want the code to become a relational hell!

    How would you suggest to cope with components becoming too “entitive”?

  23. adam Post author

    “unit-entity to hurt unit-entity”: this will never work.

    I made a big point in my original articles to say:

    “The Entity DOES NOT EXIST”

    …which confused a lot of people, but this is partly why I said it: you avoid thinking of “entities doing things” – entities do nothing; components “do” everything.

    …but components have no methods, so *in code* it is the Systems that “implement components doing things to other components”.

    Also, because you’re dealing with components – not entities! – in practice, it’s rarely “component does something to component”, usually it’s:

    “(a group of components on one entity) does something to (a group of components on a different entity)”

  24. adam Post author

    That sounds sensible, until you get to the “CappedComponent”.

    Should components be tracking how much they’re capped?

    That *could be* a role that the System should be performing *POSSIBLY* by using some meta-data stored in another entity – it’s not data internal to the component itself, it’s metadata that the rest of the game-logic enforces upon that component. A rule of thumb when you’re adding values to a Component”

    “Is this value something that a game-designer would KNOW and GIVE A VALUE TO at the time when they designed/created the initial Component?”

    …if the answer is “no”, then it probably shouldn’t be there.

    e.g. if you look at the ultra-common “position” component, you say:

    1. It has an “x” value (yes!)
    2. Should it have a “y” value?

    <-- We think: if you're going to give something an "x" position, you're obviously ALWAYS going to simultaneously give it a "y" position. 3. Should it have a "velocity-x" value? (maybe; depends on your game) ... 4. If the player has collected an "attractor" powerup, all positions should be 50% closer to the player. Should it have a "effective-X-for-attractor" and "effective-Y-for-attractor" ? <-- No, because this "attractor" stuff is nothing to do with a normal, ordinary "position". Sometimes, while the game is running, it is relevant. But most of the time you have no idea if there's an "attractor" in play or not.

  25. adam Post author

    In your case, I’d have been tempted instead to go for:

    Player (entity)
    – gold { value } (component)
    – mana { value } (component)
    – gold-regenerator { amount-per-turn } (component)
    – mana-regenerator { amount-per-turn } (component)

    …because the “regenerates gold” seems to me something intrinsic to the PLAYER, not to the RESOURCE.

  26. Maximusya

    Thanks a lot for your prompt response!

    I want unit-entity to hurt unit-entity as determined by their Weapon-component and Health-, Defense-components
    Sorry, I am not used to ES way of speaking)
    What I said was a shortcut for “some FightSystem would take a Weapon-component of some applicable entity and change the state of another applicable entity’s Health-component, also taking into account it’s Defense-component”.

    Speaking particulary about your Player entity example:
    I was under the impression that components must be independent from each other.
    But in your Player’s entity the “gold-regenerator” component implies that there is a “gold” component inside the entity.
    One would have to create a System per regenerator:
    – GoldRegenerationSystem (take gold-regenerator, update gold)
    – ManaRegenerationSystem (take mana-regenerator, update mana)

    – HealthRegenerationSystem (take health-regenerator, update health)
    – DefenseRegenerationSystem (take defense-regenerator, update defense)
    etc.

    Speaking about the CappedComponent
    Should components be tracking how much they’re capped?
    No component is tracking a cap. CappedComponent is just a value. A System would look for this value if it decides to change a ResourceComponent.

    Anyway how would you propose to extend your Player example to implement a capped mana?

  27. Maximusya

    What I’d like to also emphasize in my doubts: what is the point of separate “gold” and “gold-regenerator” components? What is the entity with “gold-regenerator” and no “gold”?

  28. adam Post author

    “I was under the impression that components must be independent from each other.”

    — independent at the *code* level, but not at the *semantic* level.

    For instance, a “renderable” component that contains the texture/sprite, and the mesh … is implicitly reliant upon the “game-position” component. But it has no source-code link — only the *System* that uses it has that connection.

  29. adam Post author

    “No component is tracking a cap. CappedComponent is just a value. A System would look for this value if it decides to change a ResourceComponent.”

    That’s a contradiction. If the System were tracking the cap, the number would live inside the system, in its private internal variables.

    Instead, the number (in your design) lives in the component, which means the component is tracking its own cap.

  30. adam Post author

    “What is the entity with “gold-regenerator” and no “gold”?”

    That’s a meaningless question, since there is no such thing as an Entity (it is an implementation detail, nothing more).

    You need to think of “sets of components” as your “things” that you reason about.

  31. adam Post author

    “One would have to create a System per regenerator:”

    Yes. Or you could have one system that handled all of them. If they are very similar, that would work fine.

    It *all* depends on YOUR game design, though. If I were making a game as you described, I’d only expect to have 3-5 of these resources ever — but maybe you plan to have 100 different resources.

    If you plan to have 100 different resources, I’d expect to have “a few systems” for them. I would assume that “most” of the resource work the same way (perhaps: 70 of the 100) and can be implemented by one System.

    …that “some” would work a different way (perhaps: 20 of the 100), and need another system. Even inside that system, there might be small differences between the components, so you might have 2-3 Systems that were very similar but slightly different, to handle the variations.

    …that “very few” would work in a COMPLETELY different way, no similarity at all — these ones would require a whole unique System *each*, because they’re so wildly different.

    ——-

    And then I’d point out: if you start by having many components (one per resource) then you can start with ONE system, and add those others ONLY when you find you need / want them — and it requires practically zero source-code changes to achieve (you simply stop sending some of the components to the “old” system, and divert them to the “new” system. … the “old” system doesn’t even change its source code! It still *thinks* it can handle the components that are now gone to the new system – but since you never allow it to have them, it never notices they are missing)

  32. Maximusya

    “No component is tracking a cap. CappedComponent is just a value. A System would look for this value if it decides to change a ResourceComponent.”

    That’s a contradiction. If the System were tracking the cap, the number would live inside the system, in its private internal variables.

    Instead, the number (in your design) lives in the component, which means the component is tracking its own cap.

    Why Regeneration rate is allowed to be contained in a component while Cap is not? Both are just values that a System would use
    newValue = min(oldValue + delta, maxValue).

    The simplest RegenerationSystem’s code may look like:

    ResourceComponent resource = entity.GetComponent();
    RegeneratingComponent regen = entity.GetComponent();
    CappedComponent cap = entity.GetComponent();

    var valueDelta = regen.ValueDelta;

    if (cap == null)
    resource.Value += valueDelta;
    else
    resource.Value = Math.Min(resource.Value + valueDelta, cap.MaxValue);

    Where would You place Cap? Why does it have to be treated differently than RegenRate?

  33. Maximusya

    Sorry, formatting ate some text, but hope you saw the intent: get components, then operate components.

  34. Tom H.

    >> And since Artemis forces “one component per type”

    Full stop: this sounds to me like a side effect of a dubious design decision, rather than a real feature. “We discovered a thing that looks like it might be an optimization, so we’re going to throw out our framework’s high-level semantics in order to support it!”

  35. Adam

    @TomH:

    I recommended it for anyone starting out because it helps you avoid bad habits.

    With many-per-entity its way too easy to fallback on OOP thinking when designing your components.

    Find a good example + counter example that illustrates the difference, and if it works we can all point people to that in future.

    But in general its an issue of naming: the only name that exists in an entity system is te entity; with muktiple identical components per entity you have no way to say “which” one of them you’re referring to.

    That is usually dangerous and nearly always the wrong way to design your game. Even though its very covenient when writing simple games and examples.

  36. Tom H.

    @Adam: Agreed that you should never have two PositionComponents on the same entity. Maybe I’m being led astray by experiences where types & systems were pretty heavyweight. Would you help me understand how you’d implement the kind of design Maximusya is describing? We have a bunch of different resource quantities, which can regenerate, and are perhaps capped; some or all might be attached to any particular entity.

    There are several approaches I can think of that are more-or-less consistent with entity systems:

    1. ResourceSet Component: has goldQuantity, goldRegenRate, goldCap, manaQuantity, manaRegenRate , manaCap, … ResourceRegeneration System updates each of them. Expand the component + the system for each new resource type. Meh; data bloat and bundling unrelated things together, inflexible scheduling, …

    2. GoldPool Component: has goldQuantity, goldRegenRate, goldCap; GoldRegeneration System updates it. Add new component type and new system for each new resource type. Meh; type proliferation and code duplication.

    3. GoldQuantity Component: has goldQuantity. GoldRegeneration Component: has goldRegenRate. (Either or both of these might have your goldCap). GoldRegeneration System updates GoldQuantity on entities that have GoldRegeneration, ignores the others. Add one or two new component types and a new system for each new resource type. Purer and more expressive than #2, but I’m personally not fond of the type proliferation and code duplication.

    4. Resource Component: has resourceQuantity, resourceType. ResourceRegeneration Component: has regenRate, resourceType. (resourceCap might be part of either or both components.) RegenerationSystem updates all Resource components on entities that have a ResourceRegenerator component with the same resourceType. Requires entity system support for multiple components of the same type. Defaults to regenerating all resource types similarly, but by adding multiple variant RegenerationSystems (or adding complexity to the one system) you can add some variety.

    4b. ResourceCap component: has resourceType, resourceCap. GlobalSettings entity has a bunch of these, RegenerationSystem can look up per-type caps. Probably not flexible enough if you want to have different caps for the same resource on different entities.

    … ?

    #4 is the approach I was first thinking of, but on reflection you’re probably right, I should just live with the type proliferation and use something more like #3.

  37. Mike Leahy

    @TomH / Adam
    ** Tom – Full stop: this sounds to me like a side effect of a dubious design decision, rather than a real feature.

    Indeed… To stop short at this point makes no sense whatsoever. For more fuxored design in Artemis check out the “aspect” implementation (not much documentation; look at the code and how it works). But to be fair Artemis is just an experimental attempt with initial focus on Adam’s blog posts then some meandering down paths that encroach vs provide more freedom from an architectural direction. I believe Appel jettisoned most work on Artemis and went on to write another ES, but I still had some reservations on that effort too from what I saw. No harm in trying out ideas though unfortunately it’s one of the few Java ES implementations out there right now.

    I mean and I say this in the most positive way possible, because I’m glad to see discussion on ES and what constitutes high level data oriented design especially in Java, but often (Adam) it seems like your replies are theoretical in nature and not based on reduction to practice. The reduction that you have done is just a basic skeleton ES example and nothing overly complex. The core implementation is also one approach and should not define what _the_ ES architecture is per se. An interesting thought experiment for sure.. :)

    ** (Adam) – I recommended it for anyone starting out because it helps you avoid bad habits.

    I disagree. On day 2 I advocate you should add the ability to store lists of components by type as I outlined in previous posts above and in other blog threads.

    **With many-per-entity its way too easy to fallback on OOP thinking when designing your components.

    Huh? Please explain in detail.

    **Find a good example + counter example that illustrates the difference, and if it works we can all point people to that in future.

    I’ve outlined the approach of “extension by iteration” many times through your various blog posts including mentioning and describing it above. Sometimes it feels like discussion falls into the echo chamber here..
    Admittedly I can understand some reluctance because I have yet to release my work, but such is life.

    Instead of extending from a base class one can add multiple systems of the same type and iterate over each one calling the same method. Each successive system allows further specialization that previously was accomplished by inheritance. This is an extremely powerful technique and the impetus why on “day 2” you add storing components in collections by type to ones ES / component architecture.

    It might be noted in my ES efforts one can store a single component by type or components in a collection by type or even a parameterized collection directly since I’ve got a custom collections API where the collections are data components. There is also the ability to store specific named components by extensible enum as a single component or in a list by extensible enum (more below)…

    ** But in general its an issue of naming: the only name that exists in an entity system is te entity; with muktiple identical components per entity you have no way to say “which” one of them you’re referring to.

    In your basic ES implementation that is the case. There is a solution albeit very tricky that no other Java ES implementation has exposed to my knowledge.

    ** That is usually dangerous and nearly always the wrong way to design your game. Even though its very covenient when writing simple games and examples.

    I disagree that built in support of storing components in collections is just a convenience for writing “simple games and examples”… I do have lots of code backing an actual high performance reduced to practice implementation (IE not theory / thought experiment) and the technique is exploited widely. You got to prove the above statement in a more substantial manner. Sure there are implementation difficulties that arise which I’ll comment on below.

    The extension by iteration approach solves many problems elegantly. A real benefit as I have mentioned before is having the component architecture being a superset of an ES. IE the techniques are applicable well beyond defining entities and game design in this manner. A concrete example: grafting onto any OO framework API (lets say the Android Activity / Application lifecycle) becomes generically easy as the Android lifecycle methods simply dispatch by extension by iteration vs creating nasty inheritance hierarchies of specialized Activity instances. IE in my efforts There is an Activity that is a component manager and one can slot whatever you want into it from data to system components. The onStart method looks like this:


    public void onStart()
    {
    super.onStart();
    for (Iterator iter = getAsIterator(SYSTEM, IAndroidLifecycle.class); iter.hasNext();)
    {
    iter.next().onStart();
    }
    }

    One can slot in as many “IAndroidLifecycle” systems as desired into the ActivityManager which allows data driven configuration of all Activities vs hard coding via OO.

    Consider a typical OO “MVC” pattern in relation to an Android Activity. The Model becomes a data component to slot into the ActivityManager and View and Control are system components that respectively handle rendering (via a “ViewManager w/ IViewLifecycle systems again using extension by iteration) and input control.

    Technically you can, not that you should, apply the same thing to entities in a game.


    for (Iterator iter = entity.getAsIterator(SYSTEM, IRuntimeSystem.class); iter.hasNext();)
    {
    iter.next().update(); // or whatever your "runtime method is"
    }

    I don’t necessarily advocate doing the above BTW.. Just an example… There are more data oriented design approaches to handling entities and entity management for traversing all relevant data / system components of all entities at once.

    In addition one can store the components / systems multiple times. IE lets say we are talking about resources with an IResource interface. Store all data components in the IResource type collection, but one could also store each individual resource by specific class type or as I’ve describe below again an extensible enum that can be exchanged for Class type while still encoding the all the type info.

    As mentioned in a previous post above in a Java ES / component architecture it’s also quite possible with some generics gymnastics to use an extensible enum that encodes type information and use it instead of the bare Class as type. One can even accomplish storage of generic parameters with the same technique overcoming the weakness in all other Java ES implementations of not being able to store / retrieve parametrized types / components.

    Thus it looks like this in my efforts…


    IEngine rightEngine = new Engine();
    IEngine leftEngine = new Engine();

    // extensible enums instead of class type
    entity.set(RIGHT_ENGINE, rightEngine);
    entity.set(LEFT_ENGINE, leftEngine);

    entity.add(SYSTEM, IEngine.class, rightEngine);
    entity.add(SYSTEM, IEngine.class, leftEngine);

    for (Iterator iter = entity.getAsIterator(SYSTEM, IEngine.class); iter.hasNext();)
    {
    iter.next().vroom();
    }

    entity.getAs(LEFT_ENGINE);
    entity.getAs(RIGHT_ENGINE);

    //One could store a single engine too by class type or an interface:
    entity.set(SYSTEM, Engine.class, leftEngine);
    // of course doing this overwrites it:
    entity.set(SYSTEM, Engine.class, rightEngine);

    Note: “SYSTEM” is a static include convenience for ISystem.class.

    There is also a “getAsList” method in my efforts where you can retrieve a component by index from the collection; though it really isn’t used in practice with tons of code and I’m debating taking it out of the API.

    As you can see above there are caveats that storing the same component by multiple types or extensible enum opens up. Mainly recycling or reclaiming an entity or component manager is slightly more laborious in that this process has to track if a data / system component has already been seen when traversing / reclaiming. Sure that makes things more difficult, but that is the burden of the ES architect. There are a lot of difficult things to overcome in building a powerful, fast, yet generic ES / component architecture.

    Well, I hope this doesn’t mean you’d skip grabbing beers when you’re in town.. ;P

  38. Adam

    @Mike: too many academic words (collections, interface, inplementation, iteration), too much conceptual conplexity.

    If its simple, work out how to explain it in two paragepahs of non technical language, and a paragraph of specific game examples ahowing how it benefits the “game” (not the architectural elegance).

    Game comes first; shipping is what matters; everything else is nice theory but uktimately not as valuable

  39. Mike Leahy

    @Tom H…. You snuck a comment in before my diatribe…

    Here is how I’d solve it given a modification of your #4 approach, but with my Java ES API.

    Create an IResourceType interface which is used to create an extensible enum.

    IE:

    public interface IResourceType extends (tricky generics gymnastics) {}

    public enum BasicResource implements IResourceType
    {
    MANA,
    GOLD;

    // perhaps some other boiler plate for component architecture requirements and generics gymnastics implementation
    }

    // after "extends" is boilerplate for my ES API
    public final class Resource extends AbstractData
    {
    public IResourceType resType;
    public float value, min, max, regenRate;

    public Resource(IResourceType resType, float value, float min, float max, float regenRate)
    {
    this.resType = resType;
    this.value = value;
    this.min = min;
    this.max = max;
    this.regenRate = regenRate;
    }
    }

    // Lets say we statically included GameResource so we don't have to prepend the enums with "GameResource."

    Resource manaResource = new Resource(MANA, 100, 0, 100, 0.5)
    Resource goldResource = new Resource(GOLD, 1000, 0, 10000, 0.0)

    // Store resources by named extensible enum
    entity.set(MANA, manaResource);
    entity.set(GOLD, goldResource);

    // Store resources in a collection
    entity.add(DATA, Resource.class, manaResource);
    entity.add(DATA, Resource.class, goldResource);

    // One can at any time get the gold or mana Resource.class data component
    entity.getAs(GOLD).value;

    // In the update method of the "entity manager" runtime system / clock callback / each frame, etc. This is naive, but lets say we have a way to iterate over all the entities; how about they are just stored in a bare collection.

    // ~ indicate brackets which are scrubbed by the blog.

    public void update(float timeMS)
    {
    for (Iterator~Entity~ iter = entityList.iterator(); iter.hasNext();
    {
    Entity entity = iter.next();
    for (Iterator~Resource~ resIter = entity.getAsIterator(DATA, Resource.class); resIter.hasNext();)
    {
    Resource resource = resIter.next();
    resource.value = Math.max(resource.min, Math.min(resource.max, resource.value + resource.regenRate * timeMS));
    }
    }
    }

    The above code outlines how to generically store multiple resources and _not_ have to provide a system for each data component nor specialize each resource by it’s own class. One can add new resource types by simply creating a new IResourceType extensible enum (say a FOOD resource, etc.)… In general depending on the complexity of the game a single Resource class is needed and the distinguishing feature of the ES / component architecture is that one can store / retrieve these data components by specific extensible enum and also put them into a collection which can be iterated over. By storing IResourceType in the Resource one can also determine the type of resource when iterating over all of them. In general one wants to group all the data for a given sub-area of a game. In this case a single generic Resource class with all parameters that a resource will ever need is good. Not all resources will regenerate, but some or most will, etc.

    Type proliferation is _very unclean_ code. The basic Java ES implementations in the wild presently force unclean code practices.

  40. Mike Leahy

    @Adam… Hah.. and you snuck in a comment too.. :)

    I guess I answered your query on a concrete example with working code before seeing your request… ;P

    ** (Adam) @Mike: too many academic words (collections, interface, inplementation, iteration), too much conceptual conplexity.

    I really don’t know how to reply to this… Uh.. “Collections” as in the Java collections API, “interface” as in the interface keyword for Java, “implementation” as a concrete implementation of an interface (you know a “class”), “iteration” as in last millennium’s Java Iterator interface of the collections API; you know Java 101.. :P Sorry, but if this is “conceptual complexity” then well.. Ahh.. The rabbit hole goes quite deep ;P

    ** If its simple, work out how to explain it in two paragepahs of non technical language, and a paragraph of specific game examples ahowing how it benefits the “game” (not the architectural elegance).

    Dang.. did that before you asked or at least I didn’t see this query before I posted the solution above.

    ** Game comes first; shipping is what matters; everything else is nice theory but uktimately not as valuable

    Technically you are slinging “theory” not based on reduction to practice or even basic game implementations, but just based on your very basic boiler plate ES implementation. You haven’t even created a or many games with it.

    While my efforts are unreleased I have an extensive middleware runtime / SDK with a Quake3 class demo engine (which I’ve been using for 9 years now).. What can I say.. It’s my MVD; minimum viable demo… Games are just one part of what my efforts accomplish.

    While I can be accused of being an architecture astronaut in reality I really just like coding tools and thinking about better ways of writing software. In my case without creating a new JVM language, but pushing stock Java further. While game dev is certainly a niche where my efforts will excel at I have been and am working on a longer play.

    Another example of “theory not reduced to practice” that I didn’t jump into is your July 2nd correspondence above with Toboi when you mentioned with marshaling components in a collection / list to send between systems. IE this is kind of an example of a “theory” stab vs reduction to practice moment. Systems should implicitly be able to retrieve the data required without explicit marshaling during runtime (frame by frame context) in a single thread. In fact the only time marshaling in a runtime context is really pertinent is passing data between threads.

    Some of the more exotic work that I’m doing now is working out a way to safely and quickly pass component data between threads, IPC, and the network. I’m currently experimenting with the Disruptor (look up “Java Disruptor Fowler” for an article). If the above stuff was “complex” then dealing with an ES in a multi-threaded context is really crazy. I’m orienting everything towards lock free event based asynchronous I/O hence the move toward the EventBus pattern for intra-thread messaging, the Disruptor for inter-thread messaging, and ZeroMQ for any network serialization / inter-process messaging. This is the kind of complex stuff I’m trying to wrangle all into a coherent API and if possible not hard coding dependencies on the Disruptor / ZeroMQ before launch in addition to having an extensive set of runtime / SDK components broken down with very granular modularization (700 modules / 175k SLOC presently). As things go too a focus is also to work on developer experience and tooling before releasing the beast. It might be 2015 because bills still need to be paid here, but ASAP…

    Things can get complex to build a next-gen ES / component architecture that is generic yet fully capable and suited for highly modular / multi-threaded development.

    We should get those beers sometime though… It takes the edge off. ;P

  41. Dusan Benasic

    I can think of an alternate approach for resource example that can work for ‘single component type per entity’ ES, and doesn’t cause type proliferation. Say that you have following component types:

    resource (resource_type , int amount )
    resource_regeneration (int delta, int cap )
    owner (entity_id)

    Any time you want your player (or NPC or whatever) to have another resource type, just create new entity that contains only components pertaining to that resource, and owner component pointing back to the player. The new entity would contain* following components for non regenerative resource (id of player entity is 5):

    resource (resource_type= gold, amount = 40)
    owner (entity_id=5)

    For regenerative resources it would look like this

    resource (resource_type= mana, amount = 8)
    resource_regeneration (delta = 5, cap = 240)
    owner (entity_id=5)

    Just think of each resource as an inventory item, like axe or shield. You want items to be entities, why do you want each resource to be mere component.

    *Yeah I know that entities don’t literally contain components, but that’s a good way of thinking about this.

  42. Mike Leahy

    @Dusan

    There is more than one way to skin a cat or so I hear and not all of them are efficient. What you mentioned above works in some of the ES implementations in the wild, but it is not efficient. Another limitation presently is that the implementations in the wild don’t support compound entities well let alone multiple components of the same type. Hence the awkward need to have entity ID references to establish ownership.

    1. There are no direct links from a given entity to its “resource entities”
    2. The ES implementation then requires walking over all entities searching for any with the “Resource” component. This could be done per frame for all entities, but there will be an explosion of entity containers for each actual game based player / enemy / entity of this nature. The only other solution in the wild is the direction embodied in Artemis in the “Aspect” API is explicitly sorting entities in entirety based on combinations of components; this direction would only benefit iteration over all “resource entities”.
    3. Finding the “resource entities” for a particular entity is very costly because it requires walking over all entities searching for ones with resource components and then checking the entity ID if it matches the ID being searched for… Not ideal for frame to frame access if it’s useful to reference a particular entities “resource entities”.
    4. A resource really is just data and is more suitable to be modeled as such compared to a separate entity / component manager / container.

    The code I listed previously works in my ES, but as noted the section that iterates over all entities updating resource components is naive. It is not how my efforts actually work. There are several other ways in my ES implementation that speed up iterating over just particular types of components in bulk vs traversing each entity separately. This comes down to an intelligent entity manager vs just a list of entities in a normal list / collection.

    In simple cases I mentioned create one resource component with all data required for all resources. This can work, but there are ways to specialize resources in my ES work and separate them automatically into different collections based on type along with referencing all of them in bulk. The way this happens is also different than Artemis and is a downstream implementation and not the only / core way the architecture works. IE what I presented was the shortest code example possible.

    @Dusan
    >*Yeah I know that entities don’t literally contain components, but that’s a good way of thinking about this.

    Well, this is one the interesting points of the larger ES discussions on Adam’s blog. The above idea I’d argue is not theory reduced to practice. It’s an implementation concern based around a particular theory and not a maxim of ES architecture design.

    For instance I come from the camp that stores all components local to a container / component manager / entity. Having a global store of components imposes many limitations. One big one is partitioning (IE spatial, etc.) in addition to difficulty sharing entities & associated components between threads. IMHO the global component store approach is more aligned with single threading and small games in mind.

    @Adam
    Hah, now I know I may have thrown a little attitude or got a little agro with your last response. I just didn’t think you’d throw out what I call the “indie game dev luddite” response / defense. It’s not the line of thought the b^3 I remember from yesteryear having.. ;P

  43. Dusan Benasic

    –Part of my comment got lost. Admin, please delete my previous comment.–

    @Mike Leahy

    Thanks for your replay but I have to respectfully disagree.

    1. There are no direct links from a given entity to its “resource entities”

    Why not? There should be links. Not as a part of an entity, but there should be some sort of query system that keeps track of all components that link to foreign (i.e. non-parent) entities.

    Think about homing missiles. You want them to have a target component (similar to owner component) with an ID of an entity they track. What if you want to keep track of how many missiles are targeting some particular entity (for debugging or because that entity has a missile defense system) ?

    The solution, I think, is to have a query system that triggers any time you create, modify or delete any Linking component (Owner or Target in our case). It updates a list of linked entities. Here’s how is looks like from missile entities point of view:

    entity_5
    -target (entity_id=12)

    entity_14
    -target (entity_id=27)

    entity_16
    -target (entity_id=12)

    entity_82
    -target (entity_id=3)

    This is from a ‘Targets’ query point of view:

    entity_3
    -targeted_by (82)

    entity_12
    -targeted_by (5, 16)

    entity_27
    -targeted_by(14)

    IMHO, You should never have to iterate over all entities, except when you load or save game or for debugging. Sometimes you could iterate over all components of one type, but I think that everything should be ‘queried’ for quick access. For example you may want physics components to be queried in a quad three for physics system. You may also want physics query to link to components directly (using pointers or references) instead of entities (via ID) for speed. It all requires adding some kind of triggering mechanism to component manager.

    3. Finding the “resource entities” for a particular entity is very costly

    Agreed. But ‘multiple components of the same type per entity’ ES solves little. Because you still have to implement the inventory. You want players and NPCs to carry stuff. Stuff they are carrying must be entities. Your generic system might work for resources since they are often simple but inventory items are more complex. And I think it is a bad idea to have two completely different solutions for two similar problems

    4. A resource really is just data and is more suitable to be modeled as such compared to a separate entity / component manager / container.

    Not really. I agree that resources are usually simpler than, say, inventory items but their behavior isn’t *always* simple. Some are self replenishing. Some are capped. Some kill the owner if they reach zero (health). They may be flammable (e.g. oil) and damage the owner if the owner is attacked by fire. You might not be able to predict in advance what components you want each resource entity to have and having 100 resource components in your main entity is not tenable.

    @Adam what you think about this? How should one best implement query system?

  44. Adam

    WordPress strips html tags.

    Dumb, but efficient, and they havent felt the need to fix this in their many year so far.

    I can access the pre stripped comment, so ill try to restore later – but meanwhile: dont use html in comments.

  45. Dusan Benasic

    Don’t worry. I always type comment in text editor before posting, so I reposed my comment as #46. You need to delete comment #45 as it is incomplete. (For some reason I screwed cite tags in #46 also).

    I am more interested on your thoughts about my idea for ‘querying’ components.

  46. Mike Leahy

    @Dusan

    >Thanks for your replay but I have to respectfully disagree.

    Perhaps you misunderstood my comment. I was writing in respect to the current ES implementations in the wild and the limitations they impose on efficient design. IE Adam’s initial efforts, Artemis, etc. IE you can’t have compound entities in most of the publicly available ES implementations. Therefore implementing simple value based “resources” as entities is very inefficient for certain kinds of relationships.

    In my efforts an entity is a component manager and one can implicitly store child entities directly. Beyond system and data components there is a third component type of “manager” which is neither system or data. An entity is a “manager” component. Actually there is any number of component types which can be stored since my API deals with meta-type / type for storage. The “meta-type” is the component type, IE data, system, manager, *fill in the blank future useful component type unknown to me presently*, etc. So, far I’ve been happy with “data”, “systems”, “managers”. If a dev really wanted to implement a simple value based attribute / “resource” as a container / entity vs just a data component one is free to do so. One can also store directly a collection of child entities in my efforts.

    >Think about homing missiles.

    Homing missiles justify having a separate composed entity implementation. They are separated by spatial / temporal aspects from a source or target entity. A mere simple value based attribute / “resource” as described and discussed previously does not justify such an implementation as it is not a separate construct from the containing entity.

    >IMHO, You should never have to iterate over all entities

    Yes, my efforts do not. As mentioned current ES implementations in the wild would force this constraint on your idea.

    **It all requires adding some kind of triggering mechanism to component manager.

    Very astute, this is actually one of the mechanisms in my efforts that accomplishes more complex and dynamic behavior / specialization for component managers / entities / etc. I mentioned it before somewhere in the maze of ES posts on Adam’s blog. In my work there is an “AbstractComponentManagerControl” system that potentially can be executed for each method of the component manager API which can provide specialization for a component manager. If you search for the ACMC or the verbose version in quotes and you may find the post where I yap about this in a little more detail. I couldn’t immediately find search functionality on Adam’s blog.

    For a separate post about this direction you can check out a G+ post I made:
    https://plus.google.com/117904596907381647757/posts/1Mv94QeFCU3

    **Agreed. But ‘multiple components of the same type per entity’ ES solves little. Because you still have to implement the inventory. You want players and NPCs to carry stuff. Stuff they are carrying must be entities. Your generic system might work for resources since they are often simple but inventory items are more complex.

    The pseudo-code which is essentially in line with my efforts I listed solves the problem proposed in previous posts in less than a 100 lines of code.

    No one was ever talking about an inventory and more complex items. You are adding additional requirements to the discussion! I presented a very basic bare bones implementation that showed how one could approach variation for a basic single value based attribute / “resource” data component without type proliferation.

    >And I think it is a bad idea to have two completely different solutions for two similar problems

    As an ES architect I wholeheartedly disagree. Choosing one solution as the only path for how relationships can be formed is what is getting Artemis and other ES implementations into trouble IMHO for instance. IE Artemis’ “Aspect” implementation. I’ll keep pointing to that until I’m blue in the face. ;P I’ve seen something similar adopted for a core implementation of another ES architecture / Dust:
    https://github.com/alecmce/dust
    In creating a truly generic architecture that can “do everything” there will be multiple ways to skin the cat. Some will be more efficient and will be codified by design patterns and conceivably additional tooling built into design tools or other developer aids will enforce or guide devs toward the patterns while the underlying architecture remains open ended.

    Me:
    ****4. A resource really is just data and is more suitable to be modeled as such compared to a separate entity / component manager / container.

    Dusan:
    **Not really. I agree that resources are usually simpler than, say, inventory items but their behavior isn’t *always* simple. Some are self replenishing. Some are capped. Some kill the owner if they reach zero (health).

    You are really mixing up the data vs logic separation concepts. Data is data is data. How that data is manipulated and side effects which alter other data occurs by systems. Behavior is not encoded with the data. As I mentioned if your game design is simple you can take some liberties and create one “resource” data component with all parameters necessary. As discussed previously a “resource” in the context of the prior discussion is a basic attribute that has a value and may have a min / max cap and / or may regenerate; nothing more / nothing less. I didn’t make up these “requirements” as they were mentioned by previous posters. You are adding more complexity into the discussion. Which is fine, but it changes the discussion. For instance:

    **They may be flammable (e.g. oil) and damage the owner if the owner is attacked by fire.

    This has nothing to do with a basic “resource” or single value based attributes. This has a lot more to do with additional complexity of “inventory items” which could benefit from being implemented as entities.

    Break… I’ll now address your concern, so consider the following. Is it reasonable if a player character is holding a bottle of oil in their inventory to have to check each inventory item every time the player is attacked by fire to figure out implicitly if a given inventory item causes fire damage… Nope.. Not at all.. The pre-sorting / logic that your spark of intuition alluded to and I mentioned as the “ACMC” aspect of my efforts could come into play…

    // Adds a child entity
    playerEntity.add(INVENTORY_ITEM, oilEntity);

    Behind the scenes an ACMC system can run on this component addition and examine the “oilEntity” to determine if there are damage modifiers to change in the playerEntity. Perhaps there is an enum map or even fancier an extensible enum map collection which in my efforts can be stored as a data component that can be accessed by the following; perhaps a damage dealing system could do a simple check like this:

    if (playerEntity.getAs(DAMAGE_MODIFIERS).contains(CRISPY_BITS))
    {
    // burn burn burn
    }

    The enum map passed back by “damage modifiers” now indicates susceptibility to fire damage. If the “oilEntity” is removed the same ACMC control behind the scene potentially modifies the damage modifiers data component thereby removing the potential for additional fire damage.

    **You might not be able to predict in advance what components you want each resource entity to have and having 100 resource components in your main entity is not tenable.

    Uh, so having 100 sub / child entities which are composed of even more finite data components is tenable versus simple single value data components? ;P It really depends on the complexity of the game design. The answer I posted was not for a MMORPG and in reality can still cover a great deal of small to medium game design concerns.

    The concept of a “resource entity” is not a good mapping for a simple value based attribute. Recall you originally brought it up as a hack for working around limitations in ES implementations that don’t allow multiple components to be stored by type.

    —-

    I think any discussion is good because the more awareness out there the better. It is easy to predict a lot of confusion in the coming years surrounding ES architecture concepts especially as folks new to the scene come across older posts / discussions online. Very little if anything has been codified through best practices yet.

  47. adam Post author

    @Dusan I don’t have time to go into this at the moment, sorry.

    So long as you stick to the core ES principles, then to some extent … all approaches are OK approaches. Mike’s gone a long way in several directions of his own – I suspect he’s gone so far it’s no longer an ES as I’d see it, but there’s plenty of good stuff in there.

    On the other hand … there are definite advantages to working out approaches that are the simplest possible in terms of source-level changes. The data-is-everything aspect of ES’s is one of their greatest strengths, and I’ve spoken to a lot of commercial developers on AAA titles where things started going wrong (in hindsight!) when they forgot that. It was easy to tack-on functionality and richness, but it added more and more complexity to the core ES usage patterns. From what I’ve heard, usually every small feature seemed trivial at the time, but they gradually built up to be too much weight.

    But it takes some serious careful thinking and time to work out “simple” solutions. I don’t have that time right now, so I’m not able to add much useful I’m afraid.

  48. Dusan Benasic

    @adam


    The data-is-everything aspect of ES’s is one of their greatest strengths, and I’ve spoken to a lot of commercial developers on AAA titles where things started going wrong (in hindsight!) when they forgot that.

    Data is everything mantra is what I live by as well. However I believe that one crucial thing that you left out are something I call queries, i.e. various pre-sorted lists that remove wasteful iteration and pre-calculated values based on components. You say Systems, Entities and Components, I say Systems, Entities, Components and Queries.

    But it takes some serious careful thinking and time to work out “simple” solutions. I don’t have that time right now, so I’m not able to add much useful I’m afraid.

    I respect that. However I would really appreciate if you could write something up later. You seem to have caused quite a stir with yours first ES post and a lot of people started looking SERIOUSLY at ES concept. However you have never really followed up with anything concrete since then which caused a lot of well meaning but incomplete solutions (like Artemis) or people going in weird directions. Bomberman example is finally something concrete and I really appreciate it but I hope you will be able to follow up with more detailed system description as well.

    Thanks for reading.

Leave a Reply

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