Programming and other useless stuff: Style change and template stuff

Tuesday, August 12, 2008

Style change and template stuff

Hi,

I had some people tell me that the old style in this blog had some tiny font settings. So I increased it a little bit and cleared up the font colors to actually make it more readable. I hope you have a better reading experience now... Please make a comment if you have any suggestion for improvement.

Well... that said, let's dig into some code :) As I mentioned in one of my earlier postings, I have some ideas on how to handle the transition from a template to the actual object. But before I tell you about the decision I made (on how to achieve that transition), let me tell you about the components and entities.

A component, as stated in my earlier posts, represents a piece of code that achieves a given task for an entity. This might be holding the health data, holding the current animation state, holding a list of animations or sounds, holding the current experience points.

Although I use the word "holding" a lot when talking about components, they're not only about data storing. Components must be able to alter the entity. While this might sound strange to some ears, it makes perfectly sense in my case. Since I want to have a component that is able to hold the current state of an animation, the very same component must be able to make an update to that animation (ie. call an update on it using a time interval). Also, there might be a component that is able to manage buffs or debuffs for a character. Those buffs must be updated and (in most cases) removed if ie. they usage time has expired. For the above mentioned reasons, a component not only holds data, but also has an update function which receives a delta time since the last call to that function.

The entities store a set of components. This is the very basis of all components. Now, to make my life a little bit easier, I'll have some specialisation for entities: there'll be static entities (those who wont do anything in the world; one might call them decorators) and dynamic entities. Dynamic entities will be (in most cases) NPCs and PCCs (player controlled characters :) ). There will also be dynamic entities representing gfx and sound effects, bullets and other physics driven objects, etc.

Ok... now that we have a basic sketch about components and entities, I'll write about the templates and how they're going to be "translated" into objects. "Translated" is the right wording at this point. In fact, the templates for ie. a component have to be translated into the class instance of that very component. To achieve this, I decided not to use the template class itself but a seperate class which I call TemplateTranslator. In fact, there are two basis classes: ComponentTemplateTranslator and EntityTemplateTranslator (two since I already made the difference on the template side for the templates). The translator itself on has one basic function: create.

Here are the interfaces for the component and entity template translators:

class ComponentTemplateTranslator
{
public:
virtual Component *create(const ComponentTemplate *_template) const = 0;
};

class EntityTemplateTranslator
{
public:
virtual Entity *create(const EntityTemplate *_template) const = 0;
};

Easy and straight-forward... just as I like it :)

Now, I don't want to have a bunch of translators hanging around... so I have a small manager who holds the different translators. The interface is small:

class TemplateTranslatorManager : public Sidema::Singleton
{
public:
// ----------------------------
// Translator handling.
void registerComponentTranslator(Sidema::String _type, ComponentTemplateTranslator* _translator);
void registerEntityTranslator(Sidema::String _type, EntityTemplateTranslator* _translator);

// ----------------------------
// Translator usage.
Component* useTranslator(const ComponentTemplate *_template) const;
Entity* useTranslator(const EntityTemplate *_template) const;

protected:
// ----------------------------
// Xtructors.
TemplateTranslatorManager();
~TemplateTranslatorManager();

private:
friend class Sidema::Singleton;

// ----------------------------
// Translator handling.
void freeAllTranslators();

typedef std::map COMPONENTTRANSLATOR;
COMPONENTTRANSLATOR m_componentTranslators;

typedef std::map ENTITYTRANSLATOR;
ENTITYTRANSLATOR m_entityTranslators;
};


To register a translator, you simply tell the manager, which type (or in case of the entity template determined the name) is handled by the translator. Opposed to component templates which are identified by the type, entity templates are identified by their name. Thus you cannot have a template named "xyz" creating an dynamic entity while another template having the same name would create a static entity.

To create a component, you simply call the useTranslator() function with the component template, and the according component is created (if a translator has been registered for it).

I sense that you want to ask me: Why the heck don't you just implement the "translator" into the template itself since you already have a specialisation for the template?

The answer ist: because the client and the server behave different. While the translators on the client would transfer all information from the template to the object, the translators on the server might want to drop unnecessary information. You don't need gfx information about door on the server, you only need to know if it's open, closed or locked. Also, you might want to have some AI calculations on the server and thus add an ai component to the template, but only create an instance of it on the server.

If you have any questions, suggestions or if you simply want to discuss about this topic, don't hesitate to post a comment :)

Have fun,
Stefan

Labels: , , , ,

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home