1

I'm having a 2d world in c++ filled with animal-like entities for a program I'm writing. I have a world class, and and entity class (and a cascade of different kinds of entities inheriting from entity).

I want the entity to "know" which world its in and be able to interact well with the 2d array of entities, but I don't want it to inherit from world (after all, entities aren't worlds). So I'm just trying to get some ideas for a good way to implement this. I could of course have each entity contain a pointer to the world it's in, but it seems rather messy. Is there an easier way for an entity in a 2d array to "know" which world object contains it.

Is there any way in c++ for an object that's a member variable for another object to know the object that contains it?

Thanks!

Nathan
  • 65,860
  • 11
  • 32
  • 47
  • 1
    ...I was about to say "why doesn't each entity have a pointer to the world where he lives?"... :) – Exceptyon May 15 '13 at 16:10
  • 2
    I would go with pointer. – Andrew May 15 '13 at 16:10
  • It seems a bit circular, is there some other way? – Nathan May 15 '13 at 16:11
  • 1
    Is it circular if parent knows his son and son knows his parent? – Andrew May 15 '13 at 16:12
  • 4
    "Circularity" is not a problem in itself. In particular because the relationship is not symmetrical: the world _contains_ entities (_owns_ them), but the entities only _look_ at their world in the same way you look at stars in the dark of night. "Look, don't touch" pointers are a rather useful pattern. – Daniel Daranas May 15 '13 at 16:15
  • That's an excellent way to describe it, Daniel, I think I'll just go with that. – Nathan May 15 '13 at 16:23

4 Answers4

3

Aggregation (supplying each entity with a world pointer) is the simplest solution. Another solution is to have a third mediator object which maintains pointers to worlds and entities, stores their relationship, and mediates (hence the name) the communication between them. This object could be a global singleton (most programmers will shudder but I don't think a few of these are a bad thing), or else every world and entity will need a pointer to it to communicate, which obviously isn't a big improvement on the first solution.

Matt Phillips
  • 8,691
  • 8
  • 41
  • 72
1

I have a world class

Oh dear.


That aside, what is your entity's meaningful interaction with its environment? Should it be able to query arbitrary information, see over the horizon, interrogate the state of other entities?

Or is it supposed to have some limited view, based on its location and attributes?

In the first case it is apparently a godlike entity, and mundane concerns such as encapsulation and separation of concerns don't apply.

In the second case, expose an interface (you can make it abstract to reduce coupling) which allows it to see only what it ought.


OK, so the second case could look something like

class World; // is a dumb container of entities
class Environment; // is an entity's window on the world
class Entity {
public:
    void take_a_turn(Environment&) = 0;
};
class Environment {
public: // control what an entity can do to (see of) the World
    container<const Entity*> visible_entities() const;
    result attempt_to_eat(const Entity*);
    result attempt_to_mate(const Entity*);
    result run_away_from(const Entity*);
};

of course, if your Entity objects are active (ie, they run autonomously and continuously in their own threads), they need to keep a reference or pointer to the world or environment.

However, if you're just invoking them, one at a time, when they have a chance to do something, passing the reference in each time is fine.

Useless
  • 55,472
  • 5
  • 73
  • 117
  • 2
    "Oh dear." How so? The second case is more what I'm going for, how would you go about "exposing an interface"/setting up the interactions with it's environment? – Nathan May 15 '13 at 16:20
  • Ask your favourite search engine about the _god class antipattern_, to see why the phrase _world class_ is instantly worrying. – Useless May 15 '13 at 17:06
1

Assuming I've understood you correctly, an alternative to a world pointer in each entity is to give each world a unique id, then store that id in the entity as it is added to its world.

TheDarkKnight
  • 25,660
  • 4
  • 50
  • 79
  • With a mediator object, e.g WorldManager(WM) singleton class. The WM has a list of worlds, each with a unique id and the WM has accessor functions requiring the world id as a parameter to identify the world you want to access. Each entity then stores the id of the world its in and when it wants access to world data, it grabs the singleton WM and calls the relevant function(s). You can do the same with the Entity objects, again each with their own id and stored in an EntityManager. This is really useful, if you create / destroy lots of objects on the fly; no accidental NULL pointer dereference. – TheDarkKnight May 16 '13 at 07:58
0

For the world maybe you can create some kind of global engine. The engine will have systems and the world could be considered a system inside the engine. You would request from the engine the world system in the constructor of your entity and do what you need to inside there.

class World : public System
{
  // info in here
}


class Engine 
{
  public:
    World * getWorldSystem(); // Not as good
    System * getSystem( std::string name ); // uses lookup, convert to right type

}

The problem with an engine class is "How do I reference it?" In most cases you would include the .h file for the engine which also has an:

extern Engine * ENGINE;

Inside of it, which is horrible I understand but with the engine/system architecture you have to have it somewhere. Or you use a singleton explicitly.

As for your inheritance tree maybe change your design scheme completely. Component based architecture might be a way for you to solve this problem.

While inheritance makes sense in a lot of situations building a component based entity will help you with the huge chain of weird types that each animal must have.

Take:

class Component
{
  public:
    Component();
    virtual ~Component();

}

class WalkComponent : public Component
{
  public:
    Walk(); // Something here allows the entity to walk on the ground
}

class FlightComponent : public Component
{
  public:
    Fly(); // Something in here moves the entity around using flight
}

Right away you can see that you could attach a walk component and a flight component to the entity and it would have both, rather than trying to create an inheritance tree that allows both of those.

Connor Hollis
  • 1,055
  • 1
  • 7
  • 13
  • That's a really interesting idea. Is there a name for this design structure? I'd like to look into it more. Do you have any examples of open-source games that use this? – Nathan May 15 '13 at 16:27
  • System/Component Architecture, http://elephant.codeplex.com/ . Also this answer might shed some light, the answerer mentions not using component design but he has a lot of resources: http://stackoverflow.com/questions/1901251/component-based-game-engine-design – Connor Hollis May 15 '13 at 17:00