Lights as entities...

Started by
6 comments, last by NovaBlack 15 years, 8 months ago
Ok this may be a really silly question... but i felt i needed to post as i just cant shake a horrible 'urrrrgghh' feeling when looking at the structure of some code im writing. Basically im currently in the midst of designing a basic game engine architecture. I currently have an entity manager that is keeping track of all entities in the game using a list of CBaseEntity* (im currently using entities all derived from CBaseEntity using an inheritance tree). My problem comes when i come to add a flexible light management system. Basically, i already have classes CStaticEntity and CMovingEntity derived from the base entity class. Now logically i could derive two classes: CDynamiclight : public CMovingEntity and CStaticlight : public CStaticEntity however, my first issue is, a) is there really a need for a 'dynamic' light? I mean i lose all my Move(val) Rotate(val) etc commands but i can still call setPosition() and SetRotation() from the base class? This seems like it may well be enough. Afaik from thinking about it i dont really see many situations calling for Light->move etc , since in most cases a light has a source, which logically will be an instance of a mesh in my scene and most likely will follow its parents movements through AttachToParent()... secondly.. it seems i dont know... just... odd.. having lights as inheriting in the entity heirachy as typically (mentioned earlier) they dont have a visual model as such to render to the screen (note: debug recognised as exception). Therefore having my lights in the entity manger's list of game entities seems a little out of place. I could always have a seperate list of CBaseEntity*, called Light entities and separate out my lights into their own special list, but as soon as i start separating them out like that i start to feel that is a sign that they dont fit into the enity heirachy anyway. Another suggestion i have seen is to just have a completely new class CLight, and a CLightManager, completely separate from the entity manager. Seeing this has again made me feel a little like perhaps im trying to shoehorn lights into a space they dont fit into in the entity manager... But then of course its more awkward (although totally doable) to render lights on the odd occasion you perhaps want a debug representation. A further complication (or perhaps it completely isnt!) is that im typically using the idea of all entities using templates. (not c++ templates, i mean for example a CBaseEntity and a paired CBaseEntityTemplate. The template defining/containing all common logic of that type e.g. animations/mesh/ai/MaxHp etc and the actual CBaseEntity containing the dynamic data eg currentHp etc unique to each instance). Again lights dont really seem to fit this pattern, i mean yeah i guess i could define a template for point/spot/directional etc, i just feel perhaps its overcomplicating things (although i guess in some ways it would allow the development of many templates defining many different 'presets' of lights suitable for a wide range of scenes). The only reservation i have with this approach is what happens later in development when i come to add Sounds, triggers etc..... I should really follow the same approach with all, either jam them in the entity manager (or a sub manager of entity manager) or completely abstract them from typical entities, rather than mix and match as as they ALL seem to share the common trait that they seem to more represent 'functionality' or ' than the typical 'substance' idea of a 'physical' 'traditional' game entity (e.g. actor, player, obstacle, environment, weapon etc). Probably a REALLY simple question to alot of you! (so apologies in advance) but this is my first attempt ever at architecting a system like this, so id rather sort out alot of problems now than bury my head n plough on full steam ahead only to look back n realise i have a huge untidy unmanageable mess on my hands!
Advertisement
Well, obvious questions first:
  • Are those entities you describe a part of the game model (that is, the parts that describe how the game actually works and reacts to the player's input) or a part of the game view (that is, the parts that describe how the model should be displayed to the screen and speakers) ? Because a light certainly belongs in the game view in most games.

  • It seems to me that a moving entity is just a special case of a non-moving entity (the special thing being that its position remains the same). Why are you doing the effort of defining both types of entities, when you could have defined all entities to be moving, and just not move the static entities?


The simple thing to do here is to create view tools as a variant type that shares a few common properties (such as owning or referencing a transform) and with differing behavior (a mesh, an animated mesh, a light, a sound, a sprite). Then, create your model entities the way you like it (Players, Obstacles, Triggers, and so on) and define a list of view entities for the visible model entities (PlayerView, ObstacleView) that use the view tools to render things to the screen and speakers.

This has the advantage of keeping view and model separate (thereby voiding the typical conundrum of "a light doesn't have health points") as well as allowing a given model entity to be represented with several view tools (such as two models, a light and two sprites).
thanks for the reply!

at the moment i dont really have an entity heirachy for game 'view' and game 'world' .. just one entity heirachy.

At the moment each CEntity has a template that defines a mesh && texture ID, so i guess that is the 'view' part, but the CEntity also has methods for move, rotate, etc. Does this mean im mixing up things i shouldnt be?

So (if i read what your saying right) i should COMPLETELY seperate out game entities from view entities...

so for example should i have an entity heirachy for say CNPC->CSoldier etc with methods like shoot() takecover() etc, and then just give each entity a pointer to a CViewTool. And this can be lots of types in a seperate hierachy e.g. sprite/sound/trigger/mesh&&textures etc?

I guess i am somewhat there thnking about it, since each Entity Template contains the 'meshID' etc for an instance of that type. so what i should do is almost insert a middle layer like CViewTool* Template->getViewTool() that returns the appropriate type e.g. sprite/mesh etc. (or even store a list of differnt view tools for different occasions, e.g. mesh, sprite etc)

Still slightly confused where lights should fit in however! Im using DirectX 9, so i still need say a list of lights to pass into my shaders.

Sorry if i misunderstand you atall its early in the morning and i havent had my coffee yet!
Quote:Original post by NovaBlack
At the moment each CEntity has a template that defines a mesh && texture ID, so i guess that is the 'view' part, but the CEntity also has methods for move, rotate, etc. Does this mean im mixing up things i shouldnt be?
Yes, you are. You are basically forcing every model entity to have a visual representation (even when this does not make sense, for instance for triggers), and every visual representation to be associated to a model entity (even when this does not make sense, for instance for lights). By separating the two, and then connecting them with a layer of "entity display policies" (such as "how to display a player") you can combine each model entity with zero, one or several visual tools.

Quote:so for example should i have an entity heirachy for say CNPC->CSoldier etc with methods like shoot() takecover() etc, and then just give each entity a pointer to a CViewTool. And this can be lots of types in a seperate hierachy e.g. sprite/sound/trigger/mesh&&textures etc?
I would actually do the reverse. The model should not explain how it must be shown. That is a responsibility for the view, which basically knows how the model should be drawn (this is a "Soldier", therefore I must use this 3D mesh), possibly querying the model for additional information (such as position or current action).

So, your Soldier would shoot() and takecover(), and the SoldierView would notice that and draw a mesh that is shooting or taking cover at the right position.

When you create a new Soldier, you create the corresponding SoldierView. When you destroy a Soldier, you also destroy the corresponding SoldierView. The Soldier itself never knows that the SoldierView exists (this also makes the Soldier easier to test).
right i think i understand alot more now and it definitely makes sense.

It always bugged me that things seemed too closely coupled. Its really frustrating because all the textbooks i seem to read couple all entities with the visual data. Additionally all entities i read about seem to have a CEntity::Render() function. Like iterate through all entities and call CEntity::Render().To me this seems kinda backward that the entity renders itself because it then needs to know surely about alot more than it needs to in order to do the rendering..

I havent got the CEntity::render() funtion at least, i have a RenderManager, that iterates through a culled list of entities asking them for info (e.g. position etc) and asking their template for its visual info (e.g. mesh textures etc) and then that does the drawing.

so do u think perhaps it would be a better idea for a template (containing say draw info mesh textures sprites whatever) to keep track of the entities it should render, and then just ask each template to render its entities? (e.g. reverse the current relationship i have between template (containing common entity data) and instances (containing dynamic data).
Quote:Original post by NovaBlack
so do u think perhaps it would be a better idea for a template (containing say draw info mesh textures sprites whatever) to keep track of the entities it should render, and then just ask each template to render its entities? (e.g. reverse the current relationship i have between template (containing common entity data) and instances (containing dynamic data).


Yes, that would be a good starting point.
Quote:Original post by NovaBlack
secondly.. it seems i dont know... just... odd.. having lights as inheriting in the entity heirachy as typically (mentioned earlier) they dont have a visual model as such to render to the screen (note: debug recognised as exception). Therefore having my lights in the entity manger's list of game entities seems a little out of place. I could always have a seperate list of CBaseEntity*, called Light entities and separate out my lights into their own special list, but as soon as i start separating them out like that i start to feel that is a sign that they dont fit into the enity heirachy anyway.
This happens for two reasons. The first is that the ability to render itself isn't a base method but would belong to a 'CRenderable' object.
The second is that when abused, the "big cauldron approach" is just broken. Pretending to not have a distinction between say lights and monsters is just pointless - you're not going to manage them in the same way, no matter what.
Quote:Original post by NovaBlack
Another suggestion i have seen is to just have a completely new class CLight, and a CLightManager, completely separate from the entity manager. Seeing this has again made me feel a little like perhaps im trying to shoehorn lights into a space they dont fit into in the entity manager... But then of course its more awkward (although totally doable) to render lights on the odd occasion you perhaps want a debug representation.
I did something similar, but the whole point is overriding the initial factory method for this.
Quote:Original post by NovaBlack
A further complication (or perhaps it completely isnt!) is that im typically using the idea of all entities using templates. (not c++ templates, i mean for example a CBaseEntity and a paired CBaseEntityTemplate. The template defining/containing all common logic of that type e.g. animations/mesh/ai/MaxHp etc and the actual CBaseEntity containing the dynamic data eg currentHp etc unique to each instance). Again lights dont really seem to fit this pattern, i mean yeah i guess i could define a template for point/spot/directional etc, i just feel perhaps its overcomplicating things (although i guess in some ways it would allow the development of many templates defining many different 'presets' of lights suitable for a wide range of scenes).
What? I don't get what's the point of this but if I understand this right then I don't think it's going to be so smart.
Quote:Original post by NovaBlack
Still slightly confused where lights should fit in however! Im using DirectX 9, so i still need say a list of lights to pass into my shaders.
I have been there. Take care of your feet. It is strongly suggested to check again your ammo and safety net.

EDIT: two new messages while writing this! Looks like this is now late.

Previously "Krohm"

@Krohm

The main reason i opted for an entity instance/template approach was mainly to avoid unneccassary data usage.

For example each 'Orc' entity uses the sme 'orc' animations/attacks/mesh textures etc. THe only thing that differs between instances are unique things like currentHP CurrentMP etc.

say i had 100 Orcs....
So by separating the data out,

we could have

1x COrcTemplate object in memory

class COrcTemplate
{
int meshID // Regular orc mesh id
std::string name // say "REGULAR_ORC"
int MaxHP
int MaxMP
}


100 x COrcInstance objects

class COrcInstance
{
mCurrentHP
mCurrentPosition
mTemplate* // points to "REGULAR_ORC" template object.
}


The nice thing, aside from data usage, is that i read all the templates in from XML, so to make new types of orc it is SO easy..

<template definition, Type = "COrcTemplate" Name = "REGULAR_ORC", MaxHp = 100, maxMP = 50, mesh = "regularOrc.x" ai = FIGHTER_FSM>

<template definition, Type = "COrcTemplate" Name = "TOUGH_ORC", MaxHp = 200, maxMP = 10, mesh = "ToughOrc.x" ai = FIGHTER_FSM>

<template definition, Type = "COrcTemplate" Name = "MAGE_ORC", MaxHp = 50, maxMP = 100, mesh = "MageOrc.x" ai = RANGED_FSM>


Then i can really easily create just 3 template objects from my factory of type COrcTemplate, (names "REGULAR_ORC","TOUGH_ORC","MAGE_ORC") each with maxhp / mp etc set to those defined in the xml.

That way i really easily can add variations of the COrc VERY quickly by changing the EntityTemplates xml file. Additionally, entities can change type with a simple setTemplate() call.




with reference to my 'lights' comment i was saying that perhaps i could do the same, and quickly add new Clight templates to an xml file for lots of light presets, for example a template with name = "DUNGEON_LIGHT1" with Color = "DARK_BLUE", a certain range/attenuation etc. then another say "LAMP_LIGHT" color = "YELLOW" with smaller intensity etc.

Just depends on how the light class is implemented however. If i completely implement an abstract 'Clight' class and steer away from the current entity structure, obvously this wouldnt be used. Hope that makes sense :)

This topic is closed to new replies.

Advertisement