Creating an Entity Hierarchy

Started by
15 comments, last by Darkor 20 years, 4 months ago
Staying true to an object oriented design, I believe that anything that can be represented in the game world should be an entity right? So in my game, that includes creatures, fireballs and items etc. Thus I have a hierarchy like this: Entity |-Creature |-Projectile |-Items By doing this, I am allowed to select, draw, process all entities like they were all the same. So it''s good yes? However, I also want to use a Flyweight kind of concept by seperating the intrinsic and extrinsic states. So perhaps the GoblinFlyweightClass would contain total hitpoints, but GoblinContext would contain current hitpoints. But if I go this route, we''d end up with a lot of classes, because each type of creature, projectile and item will require two classes. What would be a good way going about this that would require just one class per concrete entity?
Advertisement
Hi;

Are you sure you want all of these entities to inherit from one base? If so, what should this base represent? What common facilities should it offer the entities?

I see you mention selecting and drawing the entities as part of the interface of the class. In my opinion this should be handled by other classes, as it allows you to seperate game logic from representation (The part that contains most platfrom dependent code) and therefor ease portability and customization.

As for having multiple objects representing the same entity, it can be quite useful in keeping your architecture clean. For example, You can have one class define ''Creature'' as an entity to handle interaction with the system (e.g. Location on the map, inventory...etc not to mention memory management and low level system details). and another Creature class that handles interaction with the game mechanisms (Being hit by a sword, casting spells...etc)

Another thing to consider is that you don''t have to have every race be a seperate class, as in:

Creature:
|-Goblin
|-Human

Is there anything inherently different in the implementation of Goblin and Human? Can you represent these differences as differences in values between similar objects? If so, you''ll find that your heirarchy won''t necessarily explode out of proportion and it would be much easier to expand the game (with more monsters, objects and terrain types)

Peace Out!
Hmm yes, but remember that I''m still using a Flyweight sort of pattern and that the extrinsic state might have to store different values. For example, a gargoyle might have a Stone state, while a phoenix might have an extra life. All these will be represented for in the Flyweight (which stores intrinsic state). But how do I cater for this extra variables that not all other classes will have?

I have thought storing everything using a char pointer and access everything using offsets. I can store as much or as little as I want. But this could be dangerous and has inherent design flaws.

The base class also provides transparency for the functionality of drawing, processing selections, detecting collisions etc. My graphics manager does a good job of seperating game logic from representation. But wouldn''t it be a good idea to draw all entities in a single pass?

Currently the project is in 2D, though we are switching to 3D later. So while in 2D mode, there''s the thing about z orders and graphics will have to be drawn in order. This is one benefit of having all entities inherit from a base class and managed in a sinle manager.
If you''re just storing data in the concrete portion of the flyweight, and you don''t require methods in the flyweight, why not just use static member variables which are constant(or not I suppose...)? That will allow them to be shared among all instantiations of a particular class, while not being duplicated for each one, I think that''s what you''re after.

Ravyne, NYN Interactive Entertainment
[My Site][My School][My Group]

throw table_exception("(? ???)? ? ???");

Well there are functions in the Flyweight''s but your idea could work too, if I put those functions in the client classes. I''m not sure how that would result in?

Actually if what you said was true, why would anyone ever need Flyweights? *raises eyebrow*
first things first. An entity should never know how to explicitly render itself. Your code will be far more easier to follow if you have something like

CBaseEntity    protected:        int ModelIndex        int SkinIndex        vector3 Position        vector3 Angle        vector3 BoxMin        vector3 BoxMax        int Frame


Then, when you want to change the model or the skin, you can do

ModelIndex = Graphics->ModelMgr->Load (Name)
SkinIndex = Graphics->SkinMgr->Load (Name)

Finally, declare your rendering class (which should be inside the graphics class) as a friend of CBaseEntity, and voilla - You''ve taken the rendering code out of the game code.

If you don''t want to use friends, then just provide a Get () method for each of the variables required for rendering.

Regarding selection: I am currently working on an AI Editor that allows new entities to be added via loading of DLLs. Each entity is inherited from CBaseEntity, meaning I can put all the selection code in the UI and it''ll work for any type of entity. However, each entity can export a menu that allows the user to set it''s properties.

Then again, maybe not. Up to you.
I dunno, I''ve never come across a good use for them myself. I prefer using static member variables, it keeps everything in the class, and has less indirection to the intrinsic data. If you needed flyweight functions, and you had 2 or more similar classes that shared those functions and/or variables, then they would make sense I suppose, but I think the method I stated is cleaner and far easier to follow. No wasted memory, no confusion, no extra inheritances or class pointers... and, IMHO, those flyweight functions are better off as member functions of the class anyhow.

flyweights were probably conceived for more complex situations than tracking MaxSTATs and the like, and what I suggested sounds like enough for what you want. Decide for yourself though.

Ravyne, NYN Interactive Entertainment
[My Site][My School][My Group]

throw table_exception("(? ???)? ? ???");

MENTAL: My entities don''t know how to render themselves explicitly. Instead they use a Renderable object which accepts a graphic ID. And they control how the Renderable is drawn using frames and whatever.

Also my question is on how to structure the classes such that introducing one class will give you a new concrete entity. =p

Ravyne: I''ll consider it and ask around a while more. =p
Make a single base class called "WorldObject" or something similar, and have everything derive from that. Override only two pure virtual functions, Update and TouchFuncion. I *guarantee* you won't get around to implementing any of these entities if your class hierarchy is too complex. If you think about it, everything you could possibly want to do can be contained in Update and TouchFunc.

[edited by - Shadow12345 on November 28, 2003 2:57:13 PM]
Why don't alcoholics make good calculus teachers?Because they don't know their limits!Oh come on, Newton wasn't THAT smart...
shadow12345: So everything should just directly inherit from that? I don''t think adding one layer that determines if they are creatures, buildings and items will make it that more complex.

And I''ve thought about it and have decided to do away with Projectiles. So right now, we have Creatures, Buildings and Items. Pathfinding will also avoid creatures and buildings.

Also, you didn''t say if using static functions like Ravyne suggested was a good solution. I imagine, that it would be quite obscure to other programmers who''ll read the code.

This topic is closed to new replies.

Advertisement