Page 2 of 2

Re: The "perfect" Entity Class

Posted: Sat Feb 20, 2010 9:30 pm
by GroundUpEngine
K-Bal wrote:Just integrated boost::any in about one minute. Here is the most generic entity class I've seen so far ;)

http://pastebin.org/94537

I would not derive from it unless you need additional functionality. Just rewrite the Update/Draw/Constructor functions to suit your needs.

Also consider using a (std::/boost::)unordered_map instead of std::map if you are saving a lot of attributes.

Marius
The boost implementation is sweet, Nice Work man! :)

Re: The "perfect" Entity Class

Posted: Sun Feb 21, 2010 3:13 am
by K-Bal
Thanks ;) In case you are going to use it I would be thankful for feedback.

Re: The "perfect" Entity Class

Posted: Tue Feb 23, 2010 1:45 am
by CC Ricers
My feedback on it is, for an Entity I am not sure if it's supposed be more about storing information about a game object, or functions to draw that object. To me it seems like you're doing both with the class.

The draw() function looks out of place here. Does this function have a set of commands from whatever API or library is used to draw graphics on the screen? A game object should not concern itself with how it should be drawn, only about its properties. A separate component should be responsible for drawing it onto the screen.

Say you have a Renderer class that draws sprites on the screen. You would pass along the Entity to a function in the Renderer class, telling it, the Entity has these attributes that are relevant to the Renderer (such as position for example), use them to draw the sprite. This makes the base Entity class more versatile because the Renderer can take any derived class from Entity and draw it since all its attributes are a protected member of the base.

Put it this way, DVDs do not have functions to play, pause, rewind, etc. DVD players do. You load a DVD into a DVD player and the DVD's data is exposed to the player which it then uses to put a picture on the screen. Taking the object-oriented approach, it makes more sense to treat them as separate components.

Re: The "perfect" Entity Class

Posted: Tue Feb 23, 2010 4:51 am
by K-Bal
The Draw function is just an example. There are two general positions on handling drawables and yours is one of them. One could argue that an object is responsible for its appearance.

However, decide for yourself what suits your needs ;) I'm more curious about what people like/dislike about this attribute interface.

Re: The "perfect" Entity Class

Posted: Tue Feb 23, 2010 11:56 am
by qpHalcy0n
The render class being responsible for rendering objects usually only works in the most trivial cases. Given that you're rendering absolutely nothing but textured quads or tiles all over the place or with minimal material properties, then yes this usually works out well. However, when things start getting a little more complex or for objects involving several passes and complex render state management to draw correctly this method falls flat on it's face.

So what usually ends up happening and working out really well is that you have entity objects and we'll say these are "CEntity" objects. In a general sense, you'd say CEntity really doesn't know too much about itself. Much less how to render itself. It usually just serves as a top level interface to the client, only representing vital information about the entity. Perhaps things like position, hits, life, things...whatever.

However, a CRenderable object DOES know a few things about drawing. Perhaps it stores material properties, handles to textures, render state stacks, a few draw function templates. So we might say that a CRenderableEntity is "a type of" CEntity as well as "a type of" CRenderable. See where I'm going with this?

So then essentially the renderer only needs pointers to CRenderables. Given any frame they can be pushed onto the renderer where it will then perform culling and misc. other mundane tasks. It might sort them front to back for opaque passes, back to front for transparency and what have you. It may re-order the draw queue and command buffers. This provides a simplistic but robust framework by which to follow that allows for flexibility on part of the entity to be able to instruct the renderer as to how it's to be drawn but generic enough to be exceptionally easily expanded.

The renderer is concerned about the device and the pipeline. This is all it should ever be concerned with (When filling the renderer with too much object specificity, it destroys alot of the renderer's inherent responsibilities). By providing callbacks to the renderer or queues of renderable objects you keep the renderer's tasks separate from the task of the entity which is to specify to the renderer what is to happen and in what order.

People get confused as to the real responsibility of a well designed renderer. Just bear in mind, it's responsibility is NOT to draw crap. The renderer provides tools FOR rendering. Ultimately, however, it's responsibility is to order and optimize draw calls, manage the pipeline (keep it moving), an keep the device running.