8
\$\begingroup\$

The title is a bit confusing, but I couln't think of how to explain my question in a short phrase. So here it is:

Whenever I'm writing game engines, wheter it's physics/tilebased etc, I always get to the point where I'm not sure how I should manage things. Should entities in the world handle on their own, or should there be some global system managing them?

Here's an easy example: Moving things. Should each object see the world around him (check for collisions) and move based on that.

[note, this is a tile based game where object move per tile, so I'm not using physics to move from tile to tile]

public class Actor : GameObject
    {
        private void MoveTo(Vector2 location)
        {
            if (world.getTile(location) != solid && world.objAtTile(location) == null)
            {
                Tweener.addTween(this, location);
            }
          }
        }

Or should the movement of each object be handeled in the world, where the world checks everything?

public class Actor : GameObject
    {
        private void MoveTo(Vector2 location)
        {
            world.moveTo(location);
          }
        }

public class World
{

    public void moveObject(GameObject obj, Vector2 location)
    {
      //called from object

      if (getTile(location) != solid && objAtTile(location) == null)
         {
                Tweener.addTween(obj, location);
         }
    }
}

It doesn't really matter that much for this example I suppose, but I can see myself getting into trouble later on. Thanks in advance.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ More to the question, should Actor know about world at all? \$\endgroup\$ Commented Sep 13, 2011 at 3:04
  • 1
    \$\begingroup\$ I think that you're conflating Objects with Components and that's confusing the issue of who is doing what. It may be semantic problem since Component is a heavily overloaded term. I think that if you clarify what an Object is, what you mean by Component and how you organize the little engines that actually get work done then you may answer your own question. \$\endgroup\$ Commented Sep 13, 2011 at 4:14
  • 1
    \$\begingroup\$ I have to agree with others that you are asking does the game object move itself or does the world move the game object. The code above does not lead me to believe you truly mean a component type system and so might be misleading to have in your question's title. \$\endgroup\$
    – James
    Commented Sep 13, 2011 at 8:03
  • \$\begingroup\$ I did use some misleading terms now that you guys mention it. Going to adjust it now! Edit: See it has already been changed, thanks! \$\endgroup\$
    – omgnoseat
    Commented Sep 13, 2011 at 15:15
  • \$\begingroup\$ @daniel Actors clearly need to be knowledgeable about the world around them in order to move effectively, although I would typically design around a container that encapsulates both but neither knows about. eg. World contains both Actor and Level; Actor knows about Level (or rather is told about Level when needed, but not a permanent reference) but not about World. \$\endgroup\$
    – jhocking
    Commented Sep 14, 2011 at 15:13

7 Answers 7

2
\$\begingroup\$

I see your examples are in Java, but your tags don't specify any language. In C++, the answer is neither - you should not be using a member function for this!

void move_to(actor *a, world *w, vec2 location);
\$\endgroup\$
9
  • 4
    \$\begingroup\$ Have to say huge fan of the books that the author of the article wrote. However the reasoning of the article is, as far as I could tell, good theory but not practical code. By moving methods like these out of the objects they pertain to you are adding more locations to look for functionality pertaining to them which only causes confusion and higher levels of required maintenance. Just my view of it, so no + or -. Just two cents. \$\endgroup\$
    – James
    Commented Sep 13, 2011 at 8:00
  • 1
    \$\begingroup\$ Also, have to say that looks like C# with the inheritance using : ClassName instead of extends ClassName. \$\endgroup\$
    – James
    Commented Sep 13, 2011 at 8:19
  • \$\begingroup\$ It's pseudo code based off C#, but that shouldn't be relevant to my question :) \$\endgroup\$
    – omgnoseat
    Commented Sep 13, 2011 at 15:18
  • 1
    \$\begingroup\$ @omgnoseat: It's relevant because the advice is impossible in a language without bare functions, and its usefulness is reduced in any language without ADL. Good architecture is not independent of language choice. \$\endgroup\$
    – user744
    Commented Sep 13, 2011 at 22:24
  • 2
    \$\begingroup\$ @James: There is nothing non-OO about bare functions, if the functions themselves invoke methods that follow OO design principles. That's the point of the article. (OO is also not synonymous with good design. If a clear or simple design requires you not use OO, ditch OO, not the design.) \$\endgroup\$
    – user744
    Commented Sep 14, 2011 at 3:02
1
\$\begingroup\$

There is no simple answer.

As with most things in programming, it's a trade off. Giving more power to individual objects makes them larger-and therefore slower-but makes the engine easier to understand and extend. Having a mega-class that can handle everything together might be faster, but at the cost of having a mega-class; that is, it's generally considered bad form to make supermassive classes.

I've read some articles about component and data driven design, where you have a single class which represents all objects of a certain type, storing their data in lists, and passing around only indexes to get properties of an individual object. Though I can see this as a viable type of architecture, I feel it rather screws with the whole point of object orientation, which has gotten its fair share of criticism too.

I personally recommend giving more power to the objects. It makes more sense in an object oriented language, and (I would imagine) easier to understand and maintain over time.

\$\endgroup\$
9
  • \$\begingroup\$ You somewhat understate things by saying that the style of component and data-driven design you described "screws with the whole point of OO" - it's not OO at all. At least as described in "Entity Systems are the future of MMOG development" (linked in pek's answer), entity systems are a completely different programming paradigm and if you find yourself trying to make your components or entities OO beyond simple packaging convenience, You're Doing It Wrong. \$\endgroup\$ Commented Sep 13, 2011 at 9:21
  • 6
    \$\begingroup\$ They are perfectly object oriented. It's just not the OO that most people are used to, but that's fine. Object orientation is about coupling state with the methods that operate on that state, that's all. It doesn't require that each object has to be a real-life object or anything like that. \$\endgroup\$
    – Kylotan
    Commented Sep 13, 2011 at 15:33
  • \$\begingroup\$ @Kylotan: Again, I'm speaking specifically of models such as described in "Entity Systems are the future of MMOG development", where components are dumb data operated on by external "systems". They are not objects as they have no behavior/methods; they are relations (think database rows or C structs). A mistaken equivalence between OOP and everyday use of "object" has nothing to do with it. From Part 3: "I’m vigourously against using OOP anywhere in an ES implementation; it’s too easy to sneak some OOP back in where it’s inappropriate and delude yourself into thinking this is a Good Idea." \$\endgroup\$ Commented Sep 14, 2011 at 9:54
  • \$\begingroup\$ I am aware of the article, but it is just one person's opinion about how these things should be done - it is not the standard way, or necessarily the best way, so it's not correct to say that component-driven design is a completely different programming paradigm. It is perfectly possible - and far more common - to implement a component-based architecture with OO code, and using OO code does not in any way damage the "componentness" of it any more than using stored procedures damages the relational aspect of a database. \$\endgroup\$
    – Kylotan
    Commented Sep 14, 2011 at 10:50
  • \$\begingroup\$ @Dave, this question is by no means about entity-component systems. Neither is ES nor data-driven design not OO, that's a common, but big mistake to assume so. if you google for it you will find some good articles uncovering this myth. However, this question is about general OO principles of how to design your objects, higher level design patterns don't answer that question at all. \$\endgroup\$ Commented Sep 14, 2011 at 11:39
0
\$\begingroup\$

I'm updating my answer because a lot of things weren't clear before the comments. Please bare with me while I explain my thoughts.

In general, two key aspects to consider in any design is cohesion and coupling. We all know that we need high cohesion and low coupling to be able to make a more reusable and extensible design.

So, if the world has to manage everything, that means that it has low cohesion and tight coupling (because it needs to know and do everything). However, this is also the case when a game entity has to do everything. Update his location, render his texture, etc. etc.

What you are really interested in is to create systems that focus on one aspect of the entity. For example, a game entity could have a Texture, but a Renderer would be responsible to render that texture on screen. The Renderer doesn't care what other properties the entity has.

Taking it a little further, a game entity is simply a bag of properties. These properties are manipulated by systems that are focused on specific properties. And this is where Component-based Entity Systems (CBES) come in, where properties = components.

Specifically, CBES with Systems (or SubSystems). This design tends to have a few Systems that are focused on specific components of an entity while not caring about what other components the entity has. Also, the Systems are coupled only with the information they need to process these components.

Let's take your example. Since the input of where to move the entity is based on the player's controller, you would probably have a PlayerControllerSystem. This system, would control, apart from many other things, the entity's PositionComponent. In this case, the PlayerControllerSystem would need to know about the Level and the PositionComponent. If later on you decide to add collision detection, you would create a CollisionSystem that would again use the position of the entities, but this time to calculate bounding boxes (or you could have a BoundingBoxComponent, your call). The fact is, you can easily switch on or off behavior (even on the fly) by simply adding/removing components. So, more behavior means more systems are manipulating the components of an entity, but they are all in a well defined class with low coupling. Want scripting? Add a ScriptComponent. BAM! You just added scripting capabilities with 2 classes. Physics? Sound? Same again.

So, the reason I am advocating CBES with SubSystems is that it is perfectly OO and an overall easy maintainable/extensible system. Adding a behavior to an entity is as simple as deciding what data that behavior needs and which entities need it.

For more information about Component-based Entity Systems with SubSystems, there is an excellent series of blog posts by T=Machine at Entity Systems are the future of MMOG development. The author even went as far as creating a wiki for collecting various implementations named Entity Systems Project

A general (and well-known) post about Component-based Entity Systems in general is the Evolve your hierarchy who created the system for Tony Hawk Pro.

Finally, if you are looking for a library with example code, don't go any further than the Artemis library. Artemis is primarily in Java but here is a port in C# (which I am currently using in my XNA project).

\$\endgroup\$
12
  • 2
    \$\begingroup\$ -1, as this doesn't solve the problem, just moves it. He still won't have a clear answer as to which object makes the decision, whether it's comprised of components or not. \$\endgroup\$
    – Kylotan
    Commented Sep 13, 2011 at 15:32
  • 1
    \$\begingroup\$ The second link provides an extensive tutorial of why the behavior of game entities should be externalized to Entity Systems. Artemis follows the exact same architecture. \$\endgroup\$
    – pek
    Commented Sep 13, 2011 at 15:49
  • \$\begingroup\$ The second link is an opinion piece. Components are preferred by many but they are not a solution to all problems, and they definitely don't have an intrinsic solution to this one. \$\endgroup\$
    – Kylotan
    Commented Sep 13, 2011 at 22:33
  • \$\begingroup\$ The most voted answer in this question starts "There is no simple answer. As with most things in programming, it's a trade off." The second link provides one of many solutions. In fact, it advocates the exact opposite of that answer. Maybe I should edit my answer to make it more clear. But then again, maybe this won't change the negative votes :P \$\endgroup\$
    – pek
    Commented Sep 13, 2011 at 22:43
  • \$\begingroup\$ @pek: My downvote is because "use components" is not an answer to this question. I do use components, and I recommend the component pattern, but "use a component-based entity system" is not an answer to every problem in game development, or even in game software architecture - this question arises just the same with components or inheritance hierarchies or totally unrelated static entity types! \$\endgroup\$
    – user744
    Commented Sep 13, 2011 at 22:50
0
\$\begingroup\$

I usually go with a design where objects handle themselves (that's what methods are for, after all) but the base World has lists of all the objects and it uses those lists to coordinate them. So something like:

class World {
  var walls = [];
  var actors = [];
  function update() {
    for each (actor in actors) {
      actor.update(walls);
    }
  }
}

class Actor {
  function update(walls) {
    this.move();
    for each (wall in walls) {
      this.collide(wall);
    }
  }
}
\$\endgroup\$
0
\$\begingroup\$

Keep it DRY, shy and tell the other guy.

It's better to ask the world to move your actor than it is to ask the world if you can move to where you want to go. This way you can change pathfinding algorithm easily in the world class and such. Of course, you could just leave this up to a baseclass for the actor, but that's the direction I would take and the reason why.

\$\endgroup\$
-1
\$\begingroup\$

EDIT: Rewritten due to feedback stating I had not drawn the line clear enough for this answer to the original question.

I would like to clarify the question a bit more if possible. Should the logic that acts upon an object be internal or external to that object. The last part of the post specifically mentions about the longevity of the design as the basis for asking the question, to avoid trouble later on.

My simple high level answer is to keep all logic that acts upon an object within that object.

You do not need the world to move an object, all you need is the object to be moved and the vector representing the location to move to it. The world may come into play when a destination is being chosen or when a reaction to the environment is required due to collision, but those are outside of the example given to work upon.

To address the underlying part of the question and achieve longevity of the design I would suggest a component oriented architecture. Component architectures break down an object into discrete sets of data and functionality (assuming you go with my answer above which states to keep the logic with the data). If your structure looks like CEntity->CHuman->CSoldier->CPlayerCharacter then you will invariably get into issues where you need to alter some logic and depending where it goes in that tree (How many other types of humans are there for instance?) it can have sweeping affects on multiple object types.

A component system would instead have a set of interfaces that define what the CEntity object is made up of like ICompRenderable, ICompMoveable, ICompHealth, ICompInventory and so on. Where you would have CCompMoveableHuman and possibly a CCompMoveableSoldier and CCompMoveablePlayer to keep their individual movement patterns separate. So say the Soldier is altered to run in formations. This change will only affect entities built using that component.

So, to sum up I suggest you contain the logic with the data the logic applies to. I also recommend breaking up objects into discrete components to cut down the 'Where do I put this?' questions and provide stability into the future with ease of maintenance and its extensible.

Hope this helps.

\$\endgroup\$
6
  • \$\begingroup\$ I have been looking into the component pattern last couple of hours. (pek's links are very nice).But it still is not clear where the actual "behaviour" should take place. It's clear that an entity has different components for input,rendering,physics.But if I understood correctly, the components only contain the data needed to be able to function, but don't actually contain the implementation. Let's move back to the moving again;How should I make an entity move using the components?Should I extend the inputcomponent and code the implementation there?Or something else manage the implementation? \$\endgroup\$
    – omgnoseat
    Commented Sep 13, 2011 at 17:25
  • \$\begingroup\$ For me I keep the logic in the objects, but I am actually doing a component system on top of Data Oriented Design meaning most of my objects are actually just the logic anyways that are mapped to locations inside of data for contiguous fast processing.... And at the end of the day, learn one design pattern at a time :D As for the -1, would appreciate knowing why that was tagged like that, even if its just 'I like my answer better' I would still like to know why. \$\endgroup\$
    – James
    Commented Sep 13, 2011 at 18:24
  • 1
    \$\begingroup\$ @James, fair enough. I downvoted because entity-component systems do not answer the original question. A position component can still move itself or the world could iterate over all position components and move them. The same reason Kylotan down-voted pek's answer, so I thought the -1 reason was obvious. And even if it would be mandatory for a component system to move itsself (which is not the case) it would still not be an answer, just a use-case for 1 of the options. But the question was about the reasons to use one or the other, their pros and cons. The answer doesnn't cover that. \$\endgroup\$ Commented Sep 13, 2011 at 18:57
  • \$\begingroup\$ @Maik Semder. Thanks for the feedback. I have rewritten the answer to try and draw the lines more clearly to the initial question and the overall drive for it in the first place as given at the end of the question. \$\endgroup\$
    – James
    Commented Sep 14, 2011 at 0:18
  • \$\begingroup\$ @James, thanks for taking the time to edit the answer in response to my comment, very much appreciated. The proposed answer to "keep all logic that acts upon an object within that object" defeats a core feature of OO, namely encapsulation. As Joe's link shows, using non-friend non-member functions increases the level of encapsulation of an object. Moreover, it introduces a clear method as how to actually measure encapsulation. Putting the move-function into either world or actor decreases the encapsulation of the design, resulting in less flexible and harder to maintain code. \$\endgroup\$ Commented Sep 14, 2011 at 11:21
-1
\$\begingroup\$

I recommend you try to read up on component based architectures. There are quite a few blog posts, presentations and write ups out there about them that can do a better job than I ever could.

AltDevBlogADay has quite a few posts about it, a very good one being this series about game entities: http://altdevblogaday.com/2011/07/10/the-game-entity-–-part-i-a-retrospect/ There are multiple parts that focus on the issue you're trying to solve.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .