Programming and other useless stuff: August 2008

Sunday, August 31, 2008

My Wedding

Phew... what a day... on august 23rd I married Christelle, the wife of my life. We had a great day and everyone was happy :)

And I was happy, too. I've talked about friendship a couple of days before my wedding and me wondering if I have any friends. I found the answer: I have friends. I have the best friends one can imagine. Those who lend you a shoulder when you need it. Those who made me a surprise when they brought another of my friends with them... I wonder if they remarked that I had to leave the room... I had tears in my eyes and I didn't want to show it...

I have uploaded a couple of photos which I would like to share here. It's just Christelle and me...



I would like to say thank you to all of those who were present at my wedding, to those who send me kind words, and those who thought of us on our special day.

Stefan

Labels: ,

Thursday, August 21, 2008

Character Skills

Yesterday I wrote about the different character values. Today it's the character skills I'll describe.

During the game the characters gain XP. XP then can be used to acquire skills they can use in the game.

Skills are split into to categories: general and exclusive skills. General skills can be used by anyone even those who are not trained. If an untrained character tries to use a skill, he only has a 20% chance to succeed.

When a character learns a skill, a random skill percentage is determined and then modified by the Skill Modifier Table. Using the table, a character who learns a skill would never have a value less than 31. The maximum value for a skill is 99.

On the bottom of the entry you'll find skills that are only used for NPCs. Those skills are necessary to be able to use character skills.

The general skills are:

Shadowing:
  • Ability to follow someone without being noticed.
  • Shadowing check is done when:
    - Character being shadowed makes a move which would put him out of the sight of the follower (running into crowd, jumping on bus, suddenly get into a building). Failing check means character being followed has gotten out of sight.

    - Character being shadowed moves more than 60 feet indoors, two blocks in the city or two miles outdoors in the country. Failing check means the character knows being followed.
  • In the game, the player assigns to one of his characters to shadow another one. The characters movements are then automatically generated by the computer.

Stealth:

  • Ability to move short distances without being seen or heard.
  • Ability to hide in a position where you can observe someone without being seen.
  • Chars with this skill use darkness, shadows, doorways and other natural cover to stay out of sight.
  • Skill check when:
    - Someone is looking for them or trying to see them during the turn.
    - Char has moved 60 feet.
    - Char first comes into someone's Field of Vision.
  • Failing check means that other involved chars get to make an observation check. If they pass the observation check, they have seen or heard the char using stealth.
  • There must be darkness, shadow or cover to use stealth. No one (except the own team) must observe the char who wants to enter stealth.
  • Stealth cannot be used together with shadowing.
  • Characters in a fight cannot use stealth (is dropped at beginning of fight).

Explosives:

  • Ability to use explisives to make bombs, blow up saves, etc.
  • Percent chance that char will set up the explosives correctly and safely.
  • Failure means the char either made a minor or a major mistake.
  • Minor mistake: ie. Fuse didn't work
  • Major mistake: fuse too short; char blew himself up.
  • Determined by difference between chars skill value and rolled value. Small difference -> minor mistake.

Finding smuggled goods:

  • Ability to find smuggled goods hidden in a car, truck, boat, airplane or other vehicle.
  • Char without skill will not find smuggled goods by searching normally. (Make explusive skill?!?)
  • On check chars score is modified by smugglers smuggling score.

The exclusive skills are:

Accounting:

  • Ability to keep financial records, alter them to hide stolen or misused money. (For bad NPCs)
  • Ability to detect altered records. (For the good ones)
  • Detect altered/doctored books:
    - Subtract score of accountant who doctored from the score of the accountant checking the books.
    - Use result as positive or negative modifier to the skill score of accountant checking the books.
    - Use modified score to make skill check. If modified score is negative -> automatic fail.

Ballistics:

  • Ability to determine whether a specific bullet was fired from a specific gun.

Boxing:

  • Char with boxing skill make a boxing skill check instead of agility check in a fist fight.
  • Success means char has hit opponent twice in the same turn. One hit normal injuries, second hit double injuries.
  • Failure means char makes agility check.
  • All modifiers applies to agility score in a fistfight apply to boxing skill.
  • Char with boxing skill rolling 5% or less when making boxing check knocks out opponent.

Counterfeit detection:

  • Ability to detect counterfeit money.

Fingerprinting:

  • Ability to take fingerprints at the scene of a crime, analyze and match sets of prints.

Gunsmithing:

  • Ability to repair any type of firearm.
  • Successful check means the char can repair the item.

Knife throwing:

  • Ability to throw knives accurately in fist- or gunfights.
  • Handled in the same way as gunfire but checks against knife throwing score instead of agility score.

Lockpicking:

  • Ability to open locks using a small set of lockpicking tools.
  • Needs lockpicking tools to use skill.
  • Cannot be used to open a safe.
  • Lockpicking takes some time (up to 3 turns).

Wiretapping:

  • Ability to connect and run wires from someone's phone to another location where the phonecalls can be recorded.
  • Location no more than 50 feet away from telephone pole carrying the wire for the phone to be tapped.
  • Failing means the equipment malfunctions or char made error wiring the tap.
  • Failure will not be remarked instantly. There will be no phone calls recorded. Player has to check this (ie. observation shows the phone is picked up and a call is done but nothing is recorded).

NPC Skills:

Accounting:

  • If a book has been doctored by a NPC, the NPC must have the accounting skill. The NPC who doctored the book will be referenced in the book data.
  • If the NPC who altered the book is not known, a Accounting value is stored in the book. This value is then used as the accounting skill score.

Counterfeiting:

  • Ability to make printing plates, to run a press.

These are the currently planned skills. It's quite possible that one or the other might get dropped while a new one might see the light of day.

On another topic: It's quite possible (almost certain) that I cannot do any new blog entries until the end of the next week. This is due to the fact that I have some preparations to do for my wedding. Afterwards I'll leave for a week to a small honeymoon trip.

Next time I write, there'll be some xml code and talking about code refactoring. In fact, I reduced the character value components to one single component. Talking about that later :)

Have fun,

Stefan

Wednesday, August 20, 2008

Working on the game rules.

Hi,

first of all I would like to say thank you to those who contacted me and send me kind words for my yesterday down. I had a talk with the "three remaining" and I'm happy that they are able to come to my wedding. This gave me enough motivation to work on the game rules and specially on the character values and the character skills.

To not overwelm you with too much text, I'll split the cake in half and will post the character value description today. Tomorrow I'll post the skill list :)

Here we go:

Character Values

Character values represent the character with his strengths and weaknesses. During the game, the player will be able to add gained char value points to the different values to improve the characters. It might be possible that some values can be altered through objects which are used by the characters. Character value modifiers are then added.

This is the mapping and definition of the character values:

Strength:
  • Measures how strong a character is.
  • Character can lift weight 2x his strength.
  • Determines punching score.
  • Percent chance to breakdown a door.
  • On character creation: Helps to determine Health.

Agility:

  • Measures the character's coordination.
  • Indicates accuracy at punching and shooting. (Basic percent chance)
  • Basic percent chance to do unusual things such as walking on ledge or leaping a fence.
  • On character creation: Helps to determine Health.

Vigilance:

  • Measures the character's alertness to things that are concealed, unusual or out of place.
  • Used to determine surprise at start of fight.
  • Character's percent chance to notice hidden objects and clues.

Charisma:

  • Measures how easily the character can influence other people.
  • Represents: personal charm, looks, presuasiveness, how tough the character is.
  • Helps influence NPCs, get answers from prisoners and suspects.

Luck:

  • Measures how lucky a character is.
  • Percent chance to perform uncertain actions and escape certain death.

Health:

  • Injury is measured in points.
  • Health represent the hitpoints and this represent the total number of injury points.
  • Used to determine knock out or death.
  • Calculation: Health = (Strength+Agility)/10 + 5
  • Is calculated when Strength or Agility are altered.

Punch points:

  • Represents the number of injury points when opponent is hit.
  • Calculation: PP = (Strength/20)+1
  • Calculated when Strength is altered.

That's it for today. Have fun,

Stefan

Monday, August 18, 2008

Friendship

Have you ever wondered about your definition of friendship? For me, friendship means (or ment until now) that you're there for your friends when they need you. That you're available for them when something important in their life happens. That you share the good and the bad moments in life.

I don't have much "friends". Even though I have ~80 people on my ICQ list, I can count the number of people who I consider friends on my two hands: 8. I've been working with all of them at one moment or another in my life. With some of them I've been through knee deep shit (i.e. when the company we worked for went down the drains, or when we had to work for several month non stop 20h/24h to finish a product), with some of them I felt a strong common interest, I know some of them since at least 8/9/10 years and one of them is my friend since ~21 years.

At some point my oldest friend helped me when I struggled in my life. And so did I when other were in need: I pulled them into the companies I worked for, got them contracts, talked to my contacts to help my friends find work, kept them with me working even when my contractor asked me to drop them. I listened when they had trouble with their girlfriend, instantly jumped into the car when they asked my help for one of their projects, invited them for BBQs and dinners at my home, made hilarious plans for own projects with them...

That's what's friendship is all about for me...

As those who read my blog might know, I'll marry the wife of my life next saturday. That's a really special moment for me and therefor I invited my 8 friends to share that moment with me. In first time, everyone told me, they're happy to come to my wedding... and now, not even a week before my wedding, I know that at most three of them might come... and I'm not even sure about them. I haven't had contact with one of them since almost two weeks and the other two might not come if they learn that another one just had told me yesterday evening that he will not come. While one of them has to work that week-end outside of Europe, others suddenly confused dates and are on holidays, some didn't find a way to travel (the 40km) to my wedding or prefer going to their girlfriends home instead of making her come to my wedding (since they're invited, too) or that they prefer not to come since their wife can't be present...

While I can understand some reasoning, I'm totally and absolutely down. I haven't slept this night because I was thinking about what is currently happening to me. I was thinking about my definition of friendship. And I was trying to find occasions where my "friends" actually tried or wanted to be with me. It was this moment which scared me: I suddenly realized that my friends never invite me to their birthdays, they don't invite me when they have a BBQ, they don't invite me when they have a cinema evening, they don't ask me if I want to join them when they play games in the evening... I admit that I would have to drive ~100km (~62 miles) to get there but I don't consider this as a problem. I jump into the car when they ask me to help them...

And this is where I begin to struggle on my definition of friendship. Is this only a one-way drive? Have I done something that pissed off my friends? Or don't they want to be with me because I have a family, wife and kids?

And all of a sudden, a question rised from deep within of me: Do I have friends?

And I couldn't find the answer....

No post yesterday

Ok... I plead guilty. I didn't post yesterday... In fact, I had so much to do, that I didn't have much time for myself. After getting up in the morning, we went swimming with the kids. They had to get out of the house for some hours and swimming is the right activity for them.

Afterwards, we (my future wife and I) worked on some wedding stuff and realized that we forgot to go to the bakery to order our wedding cake. So we had to phone them and go there in the afternoon.

I also had some week-end chats with one of my clients. We pushed our meeting from today into the first week of september. I have too much to do this week... the wedding is eating up my time :)

So... today I spent some time looking for a CMS for the Prohibition Online website. Currently I don't want to do a complete site by myself. I just want to throw a small site together where I can display some info, eventually some screen shots (later on), put some downloads and have (perhaps) a small wiki where I can put some things like the game design document.

Currently the site looks awful...

I've been thinking about the games' framework, the rule integration, the client/server separation etc. There's quite some work before me :) And I have to make a small plan, what has to be done...

And this is, where I would like to invite you: I would like you to give me some hints about what you would like to see in a turn-based strategy game with a setting in the time of Prohibition (United States). Feel free to post in the comments section.

Have fun,
Stefan

Saturday, August 16, 2008

Nothing really new...

No, I didn't forget to post an entry yesterday. I didn't have any time. My wife's computer didn't want to boot normally. It always freezed in the middle of the boot splash screen. I had some trouble making the save mode to work but finally, after almost 10 hours of work, research in the internet, trying and crying, the machine booted normally at 1:20 am.

As you can imagine, I didn't have much time to work on Prohibition. Nevertheless, I did some research for virtual server hostings. In fact, I would like to have a virtual server somewhere to host one or more of Prohibitions Server software in the future. If you tell me, that this is a little bit early, then you're probably right. But if I want to stick to my current plans for the game, I have to be sure that I can implement the client/server structure as I want it. Currently, the server software is programmed under Win32. There are some virtual server plans for Windows, but I have to check, if they fit my needs.

Basically, my games structure should look like this: There's one matchmaking/game server (or main server if you prefer) which holds a list of all public games that are going to start. People can connect to that first server, see the game list, download updates or new maps. Once they have selected a game, the main server connection is dropped to connect to the player hosting the game.

That's the plan... we'll see, if I can get so far :)

And for anyone wondering, if this is a game, one would have to pay for... I don't know... really. In fact, I don't program this game to gain money. I do it, because I want to have fun with it. I have several other contracts which bring in the money I need. And I think that I can afford spending a little bit of money for things like the server etc.

That said... if anyone is interesting in helping out (on a non-paid basis), I'll appreciate any graphic artist willing to make some scribbles for the game style. Either PM me or send me an email to "maton at sidema dot be".

Have fun,
Stefan

Thursday, August 14, 2008

About Prohibition

Today I'll write a little bit about Prohibition, the game I'm currently working on in my spare time. So no source codes today :)

Prohibition is (will be) a turn-based strategy game. Single- and multiplayer games will be possible. In the single player game, the player has to lead a group of special agents, police man and detectives through various missions in a story mode. The multiplayer game will contain PvP (bad vs good and bad vs bad... no good vs good). While it's a TBS game, there will be some role playing aspects in it. The entities (NPCs and player) will have a set of character values such as Strength, Agility, Vigilance or Charisma. Throughout the game, the player will be able to add new abilities to his entities, buy weapons and items and decide, who to take on a mission and who not.

I spend the most day of today working on the base ruleset and implementing the base values of the NPC and player entities. While the base values were quickly implemented (they're based on components), I'm still working out the handling of the ruleset of the game.

Today I've also registered the domain names for my game:

prohibition-online.com
prohibitiononline.com
prohibition-online.net
prohibitiononline.net
prohibition-online.info
prohibitiononline.info
prohibition-online.org
prohibitiononline.org

At least, no one can pick my game's name website :)

Have fun,
Stefan

Wednesday, August 13, 2008

Stressful life...

Gosh... sometimes life can be stressful :) My cousin, who will be my witness (is it called like this?) at my marriage, had some problems with the date. In fact on august 23rd (a saturday) he should have a university exam. Today was the last day I had to confirm the witnesses of my marriage to the major of our town. So... I started asking friends to replace my cousin. Finally, an hour before desk closure at the major hall, my cousin called me to confirm his presence. He managed to move the exam by one week (there are several of those exams and he was pushed into another group). But I can tell you that I had some sleepless nights because of this :)

Phew... back to work. I had some problems concentrating today (missing sleep) and only managed to get some work done in the afternoon. I've been taking a step back from my source code and the overall layout of the Logic implementation. I'm pleased with most of it. Those who carefully ( :) ) read my blog know that I wasn't pleased with the template stuff in the EntityManager. Also, I didn't like the idea of having the components and entities that might be created by a simple new anywhere in the code. I finally decided to use factories for template, entity and component creation.

The factory approach also allowed me to reconsider the create functions for the templates. Remember that I had 2 different create functions? One for the entity template and one for the component template. The factory approach led me to the conclusion that only one function is needed for both. Basically I kept the create function for the entity template which uses a type and a name string. Component templates do have those two strings, too, since they're derived from the template class. Component templates just set the type string into the name string (Currently I think that component templates don't have to be named).

Ok... now I have 2 factories: the template factory and the component factory:

typedef Template* (*templateCreator)(Sidema::String _name);

class TemplateFactory : public Sidema::Singleton
{
public:
// ----------------------------
// Template management.
void registerTemplate( const Sidema::String &_type, templateCreator _func);
void unregisterTemplate( const Sidema::String &_type );
void clearAllTemplates();

Template* createTemplate(const Sidema::String &_type, const Sidema::String &_name );

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

private:
friend class Sidema::Singleton;

typedef std::map TEMPLATECREATORS;
TEMPLATECREATORS m_templateCreateFunctions;
};

typedef Component* (*componentCreator)(ComponentTemplate *_template);

class ComponentFactory : public Sidema::Singleton
{
public:
// ----------------------------
// Component creator management.
void registerComponent( const Sidema::String &_type, componentCreator _func);
void unregisterComponent( const Sidema::String &_type );
void clearAllComponents();

Component* createComponent(const Sidema::String &_type, ComponentTemplate *_template);

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

private:
friend class Sidema::Singleton;

typedef std::map COMPONENTCREATORS;
COMPONENTCREATORS m_componentCreateFunctions;
};


The fact that I didn't like the management of the templates within the entity manager led me to implement a template manager. There wasn't much to do since I only had to move some functions from the entity manager to the template manager.

class TemplateManager : public Sidema::Singleton
{
public:
// ----------------------------
// Template management.
bool loadTemplates(Sidema::String _filename);
void unloadTemplates();
EntityTemplate *getTemplate(Sidema::String _name);

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

// ----------------------------
// Template management.
bool addTemplate(const Sidema::String &_name, Template *_template);
void removeTemplate(const Sidema::String &_name);
void releaseAllTemplates();

private:
friend class Sidema::Singleton;

typedef std::map TEMPLATEMAP;
TEMPLATEMAP m_templates;
};


As you can see, the template manager returns a pointer to a entity template. The component templates aren't stored in the template manager. In fact, since the component templates are stored within the enitity template (remember: each component template is unique to the entity template it belongs to), there was no need to do so. I could have simply returned a pointer to a template instance, but this would lead to confusion about the basic type of the template. One could think that it might be a component template he just got...

With all this information (in this blog entry and the previous one), I've implemented a translator for the health component. There's only a constructor, a destructor and the create function of the translator (I'm think of renaming the create function to translate or something else because I normally use create to name static functions which create an instance of that very class; nevertheless, the function really creates something: the translated object).

class HealthTemplateTranslator : public ComponentTemplateTranslator
{
public:
HealthTemplateTranslator() {}
~HealthTemplateTranslator() {}

virtual Component *create(ComponentTemplate *_template) const;
};

Component*
HealthTemplateTranslator::create(ComponentTemplate *_template) const
{
HealthComponent *component = NULL;

// Check for valid template.
if ( _template && !_template->getType().compare(HealthComponentTemplate::TEMPLATE_NAME) )
{
// Get the health and create the component.
float maxHealth = 0.0f;
if ( static_cast(_template)->getMaxHealth( maxHealth ) )
{
component = static_cast(ComponentFactory::Instance().createComponent(HealthComponent::COMPONENT_NAME, _template));
if ( component )
{
// Set the health values.
// Note: The current health should be set to the maximum health
// to have at least living entities, when they startup :)
component->setMaxHealth(maxHealth);
component->setCurrentHealth(maxHealth);
}
}
}

return component;
}


Et voila... the returned component is a translated instance of the health component, filled with the data of the health component template.

The next step is to create an entity from an entity template. While this might sound strange, I still have some problems to pinpoint the differences between a static and a dynamic object. Every difference I can think of can be implemented by components... is it possible that I don't need different specializations of entities?!?

Have fun,
Stefan

PS: I once again changed a little bit the css of the blog... I still got comments that the font was a) too bright and b) the letters were not far apart enough... Fixed this with another font :)

Labels: , , ,

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: , , , ,

Monday, August 11, 2008

Data Inheritance made easy.

Yesterday I wrote that the basics for the templates seem to be finished. 'Seemed' is the right word :) In fact, while implementing the inheritance today, I figured out several things:

1. the ComponentTemplates don't need to know their owner. That information is only interesting for the component that actually wants to alter something to its owner.

2. Moving the ReferenceCounted Interface from the ComponentTemplates to the Templates is good :) In fact, the templates itself need the interface in order to be able to be referenced to within other interfaces. Some years ago I used reference counting all over the place for my projects. I dropped them when I was working for some clients and I thought that reference counting on my projects might be some kind of overkill. Nevertheless, the way the templates are used in my game make it necessary to ensure that any object is still available as long as another object is referencing to it. While smartpointers might sound interesting here, I did that my own small interface (just 2 functions) is enough for me.

3. Not cloning... initially I wanted to just hold a pointer to the source template (from which a template inherits), clone the component template and add those clones to the current template. But I decided to not handle the inheritance this way. Why would I want to clone some data that is available and that would not be altered at this point? Inheritance of data only means replacing a component of a given type with a component of the same type (but holding different data). Therefor the only point in the source code to alter would be the point where the new component is added.

Inheriting from a parent is as simple as this:

// The basic information about the template has been loaded by the above layer.
// That information has been used to actually create this object.
const TiXmlNode *srctemplate = _pElement->FirstChild("inherited");
if (srctemplate && ( TiXmlNode::ELEMENT == srctemplate->Type() ))
{
const TiXmlElement *element = static_cast(srctemplate);
const char* tempType = element->Attribute("name");
if ( NULL != tempType )
{
// We have to request the source template from the entitymanager.
m_inheritedFrom = EntityManager::Instance().getTemplate( tempType );
if ( NULL == m_inheritedFrom )
{
return false;
}

// We got the source template, we have to add the source components to the current template.
COMPONENTARRAY::iterator it = m_inheritedFrom->m_components.begin();
while ( it != m_inheritedFrom->m_components.end() )
{
addComponent( *it );
++it;
}
}
}


The addComponent code looks like this:

bool
EntityTemplate::addComponent(ComponentTemplate *_component)
{
if ( std::find(m_components.begin(), m_components.end(), _component ) != m_components.end() )
return false;

// Try to find a component of the same type.
COMPONENTARRAY::iterator it = m_components.begin();
while ( it != m_components.end() )
{
// It's the same type.
if ( (*it)->getType() == _component->getType() )
{
// Set the new one.
m_components.insert(it, _component);
_component->addRef();

// Release the old one.
(*it)->release();
m_components.erase(it);

return true;
}
++it;
}

m_components.push_back(_component);
_component->addRef();
return true;
}


Nothing more is needed for inheritance from one parent to another. In the XML code, it looks like this:







Inheritance is always resolved before the actual component template loading. Thus the overloading magically happens without any problems :)

As I said: Data Inheritance made easy.

Have fun,
Stefan

Sunday, August 10, 2008

Basis of templates and componenttemplates finished.

After a day "off" at my futre mother-in-law's home, and my son getting sick this night, I managed to find some time to work on the template and component template implementation.

While there might still remain some polishing (I don't yet like the embedding of the factory functions for the templates within my entity manager), the basis seems to be finished. This means that I can load templates and refer to component templates. The code itself is straight forward since I relied on some classes I already used some years ago.

First of all, I decided to use XML. For the XML loading I embedded tinyXML into my source code. tinyXML usage is easy and since I already use it for the SSCXML lib, I didn't see any reason to switch to another reader.

Second I use some classes I created some years ago: Parameter, ParameterList and Parameterized. Basically those 3 classes allow embedding of parameters of any depth to an object. The interfaces are slim and it was easy to alter the loading code to use tinyXML. Here's a preview of the interfaces:


class Parameter : public Parameterized
{
public:
// ---------------
// Xtructors.
Parameter();
Parameter( String &_rsName, const String &_rsValue );
Parameter( const Parameter *_pParam );
virtual ~Parameter();

// ---------------
// Data access.
void setName(const String &_rsName);
String getName() const;
String getValue() const;
void setValue(const String &_rsValue);
void setValue(const char* _pValue);

// ---------------
// I/O
virtual bool load( const TiXmlElement *_pElement );
virtual bool save( TiXmlElement *_pElement );

Parameter& operator =(const Parameter& _pParam);

private:
// ---------------
// Data.
String m_sName;
String m_sValue;
};

class Parameterized
{
public:
// ---------------
// Xtructors.
Parameterized();
Parameterized(const Parameterized *_pElement );
virtual ~Parameterized();

// ---------------
// Parameter access.
ParameterList* getParamList() const;
void clear();
void createParamList();

// ---------------
// I/O
virtual bool load( const TiXmlElement *_pElement );
virtual bool save( TiXmlElement *_pElement );

Parameterized& operator =(const Parameterized& _pParameterized);

protected:
// ---------------
// Data.
ParameterList* m_pParamList;
};

class ParameterList
{
public:
// ---------------
// Xtructors.
ParameterList();
ParameterList(const ParameterList *_pList );
virtual ~ParameterList();

// ---------------
// Parameter management.
void addParam( const Parameter* _pElement );
void removeParam( Parameter* _pElement, bool _bDelete = false );
void clear();
unlong getNrParams() const;
Parameter* getParam( unlong _uIndex ) const;
bool findParam( const String &_rsName, Parameter **_rpParam ) const;

ParameterList& operator =(const ParameterList& _pParamList);

private:
// ---------------
// Data.
TDynArray m_apParams;
};

As you can see, the interfaces are quite clear.

Now, I have three base classes: Template, EntityTemplate and ComponentTemplate. While EntityTemplate and ComponentTemplate are derivations of Template, I felt it was necessary to make a difference between a simple templates, an entity template and templates for the components.


class Template
{
public:
// ----------------------------
// Xtructors.
Template() {}
Template(Sidema::String _type, Sidema::String _name) : m_type(_type), m_name(_name) {}
Template(const Template &_temp) : m_type(_temp.m_type), m_name(_temp.m_name) {}
Template(const Template *_temp) : m_type(_temp->m_type), m_name(_temp->m_name) {}
virtual ~Template() {}

// ----------------------------
// Identify the template.
Sidema::String getType() const { return m_type; }
void setType(Sidema::String _type) { m_type = _type; }

Sidema::String getName() const { return m_name; }
void setName(Sidema::String _name) { m_name = _name; }

// ---------------
// I/O
virtual bool load( const TiXmlElement *_pElement ) { return true; }
virtual bool save( TiXmlElement *_pElement ) { return true; }

private:
Sidema::String m_type;
Sidema::String m_name;
};

// An entity template holds the basic components of an entity.
// This can be all elements that are placed within the gaming world, from
// trees and bushes to the NPCs.
class EntityTemplate : public Template
{
public:
static Sidema::String TEMPLATE_NAME;

// ----------------------------
// Creator/Destroyer
static Template* create(Sidema::String _name);
static void destroy(Template *_template);

// ----------------------------
// I/O
bool load( const TiXmlElement *_pElement );
bool save( TiXmlElement *_pElement );

// ----------------------------
// An entity has components that define its "look".
// Components are ie. health, inventory, experience points, gfx, sound, ...
bool addComponent(ComponentTemplate *_component);
void removeComponent(ComponentTemplate *_component);

protected:
// ----------------------------
// Xtructors.
EntityTemplate();
EntityTemplate(const Sidema::String &_name);
virtual ~EntityTemplate();

private:
// Components of this entity.
typedef std::list COMPONENTARRAY;
COMPONENTARRAY m_components;
};

// A component template contains only basic information about the component itself.
// Basically, it holds the initial values. Templates cannot be "updated".
//
class ComponentTemplate : public Template, public Sidema::Parameterized, public Sidema::IReferenceCounted
{
public:
// ----------------------------
// Xtructors.
virtual ~ComponentTemplate();

// ----------------------------
// I/O
virtual bool load( const TiXmlElement *_pElement );
virtual bool save( TiXmlElement *_pElement );

// ----------------------------
// Owner access.
Template *getOwner() const;
void setOwner(Template *_owner);

// ----------------------------
// Reference counted interface.
unlong addRef(void);
unlong release(void);

protected:
// ----------------------------
// Xtructors.
ComponentTemplate(Sidema::String _type, Sidema::String _name);

private:
unlong m_refCount;
Template *m_owner;
};


IReferenceCounted is a reference counter interface. Once the reference drops to 0 (due to release) the object is deleted.

The loading code is easy, too:

// Load the templates.
const TiXmlNode *node = root->FirstChild("template");
while ( node )
{
if ( TiXmlNode::ELEMENT == node->Type() )
{
const TiXmlElement *element = static_cast(node);

// Read the name and the type.
const char* tempName = element->Attribute("name");
const char* tempType = element->Attribute("type");
if ( NULL != tempType && NULL != tempName )
{
Template *theTemplate = createTemplate( tempType, tempName );
if ( NULL == theTemplate )
break;

if ( theTemplate->load(element) )
{
if (!addTemplate(tempName, theTemplate))
{
destroyTemplate( theTemplate );
break;
}
}
}
}
node = node->NextSibling("template");
}

You might have remarked the createTemplate function. Basically this function looks like this:

// Create a template of a given type.
Template*
EntityManager::createTemplate( const Sidema::String &_type, const Sidema::String &_name )
{
TEMPLATECREATORS::iterator it = m_templateCreateFunctions.find(_type);
if ( it != m_templateCreateFunctions.end() )
{
return it->second(_name);
}

return NULL;
}


The different templates are registered on class construction:

EntityManager::EntityManager()
{
registerTemplate(EntityTemplate::TEMPLATE_NAME, &EntityTemplate::create, &EntityTemplate::destroy );
registerComponentTemplate(HealthComponentTemplate::TEMPLATE_NAME, &HealthComponentTemplate::create, &HealthComponentTemplate::destroy);
}

Ok... this is what is basically needed for the templates of the entities and components. I still have to implement the inheritance for the entity templates. But that's quite easy to do, too.

An XML to create an entity templates looks like this:







Ah yes.. I forgot :) The loading code for the health component template looks like this:

bool
HealthComponentTemplate::load( const TiXmlElement *_pElement )
{
if ( ComponentTemplate::load(_pElement) )
{
if ( !getParamList() )
return false;

// Make sure the template vars have been loaded.
if ( getParamList()->findParam( "maxhealth", NULL) )
return true;
}

return false;
}

EDIT NOTE: I had to change the param tag to prm in order to display the xml and the rest of the text correctly. I didn't see this problem with IE. I encountered this with FF3.0.

The ComponentTemplate::load function just contains "return Parameterized::load(_pElement);" and thus loads the param-tags.

"getParamList()->findParam( "maxhealth", NULL)" makes sure that the maxhealth param has been loaded (actually the line says: find the maxheath parameter but don't actually return me it's pointer... I just want to know if it exists...).

Phew... that was a lot of code in this blog today. As you can see, most things are quite simple to implement. The ComponentTemplate class allows for a very flexible parameter definitions. Any derived class "only" has to check, if the parameters it needs are available.

Entity template composition is made easy by just sticking together several component templates.

There a three next steps:

a) implement inheritance for the entity templates.
b) implement the actual classes for the Entities and Components (those which you actually can alter).
c) implement the template to instance code. I have several ideas how to approach this...

Have fun,
Stefan

Labels: , , , ,

Friday, August 08, 2008

I want to show source code from time to time...

So this is just a test to see if the code highlighting works.


class ComponentTemplate : public Template, public Sidema::Parameterized, public Sidema::IReferenceCounted
{
public:
// ----------------------------
// Xtructors.
ComponentTemplate();
virtual ~ComponentTemplate();

// ---------------
// I/O
bool load( const TiXmlElement *_pElement );
bool save( TiXmlElement *_pElement );

// ----------------------------
// Owner access.
Template *getOwner() const;
void setOwner(Template *_owner);

// ----------------------------
// Reference counted interface.
unlong addRef(void);
unlong release(void);

private:
unlong m_refCount;
Template *m_owner;
};


I also have adjusted a little bit the css for the page so that it fits to you actual browser window size :)

Have fun,
Stefan

PS: The code is a glimpse at my ComponentTemplate code... I'm working on that right now.

Thursday, August 07, 2008

Objects, Entities and other things

Well... I now spent almost two days on researching which way I possibly could use to a) make most (all) of my game objects entirely data driven and b) keep it in a simple way to use.

Let's develop the two points:

When I say "Entirely data-driven", I'm not just talking about having some key values defined within a human-readable file format. I'm more into: how to handle data and object configuration. This includes the way specific tasks are handled.

Example: You have to implement 2 different things in your game: a tree and an enemy. While the tree can more or less be interpreted as being a static object, the enemy definitely is not. The enemy move, has to search for you, attacks you, etc.

Both have some information such as graphical representation, sound information, etc. In most cases, one would implement two different classes to handle those two types of game objects: a static game object and an entity game object. Each of those two game objects would have distinct functions and distinct variables. You would implement those functions and variables specifically for each class.

My target was/is to be able to define from within a human-readable text file the composition of the different game objects. After some skipping through the books on my shelves I stumbled upon two interesting articles: "Component Based Object Management" by Bjarne Rene (Game Programming Gems 5) and "Flexible Object-Composition Architecture" by Sergio Garces (AI Game Programming Wisdom 3).

Both articles take almost the same approach: Instead of implementing the different capabilities of the game objects directly into some kind of specialized class, they use the component based approach. In this approach, the different capabilities are components which can be added to a game object dynamically. The health of an entity is one of those components (interestingly both articles just pick up this example, too :) ).

Rene introduces a (IMO) rather complicated way to handle and maintain the components. Via additional interfaces between the component interface and the final implementation of the component, the access to different parts of the component itself are "hidden". IE. the interface for the health component only has one function called "GetHealth()". There's nothing else. This implies that the interface itself keeps things easy.

Now, the component interface introduces another idea: messaging. If one wants to alter the content of the health component (IE. increase/decrease the health), one must inject a message into the component. The idea is tempting: Define a new message and only the component which is really interesting by the message, will receive and handle it. Unfortunately, this means, that you have to create, update and maintain an ever growing list of messages.

Garces on the other side (in addition to the component based idea) uses the idea of archetypes. I would call this "Templates", but whatever :) Basically, you can define a template for a game object containing some component templates. Only if a game entity of a specific template type is needed, the template is "transformed" into a real entity. I like this idea because it let's you define and maintain a rather small list of templates to which any entity which is placed in the world might reference to for creation. Garces uses the fact, that this approach easily enables the developer to "overload" any component. IE. you can use three times the same template for IE. an archer and specify for one of those three archers that his firing rate is twice as high as the normal one.

What I like in the Sergio Garces' approach is the way he handles the interaction between the components. Instead of having a messaging system to alter data within the components, he implicitly states that some components "know" how to handle other ones. IE. a component of a weapon knows about the health component implementation and thus directly can use the functions of that health component. This makes the usage of the component approach slightly easier.

Now, for my implementation I was shuffling around a bit the two approaches. Remember: I like easy to use interfaces. I finally came up with a system that is template based as Sergio Garces introduced it. I also used the Rene's idea of components (I consider Rene as the originator since the GPG5 first ed. has been printed in 2004 while AI GPW3 has been printed in 2006). Specific templates know about other specific templates but still can handle the lack of those (means, they're doing nothing or reporting/logging an error). Templates hold basic information thus pure data in text form and can transform them into "real" instances once it's needed. This kept the templates themselves quite slim (and stupid) while still holding all data they should hold.

The component system as I currently have it in mind is able to define everything from simple properties such as health, xp points distribution, gfx information, sound information etc. But also is able to define components which can hold AI information (my game ai is based upon my SCXML implementation).

What's also interesting is the fact that you easily can hold 2 sets of data: one for the game client and one for the game server. In most cases the game server doesn't need to know about the gfx or sound stuff, so you simple "export" your data from whichever DB you have without exporting the data the server doesn't need.

Well... I'll talk more deeply about my implementation (with some examples) another time.

Have fun,
Stefan

Labels: , ,

Wednesday, August 06, 2008

I had to...

print this to a sheet of paper and stick it above my desk. It's a sentence John Carmack said in this years Quakecon8: "[...] there's a very finite amount of time, and you just can't do everything, so you really have to prioritize and pick the things that you want to do, that you're going to be good at, where you're going to make a difference."

This resume quite effectively my current state: SO much things I would like to do, so little time to actually realize them.

I have so much different ideas of projects and what I would like to do that it's true that I have to make a choice between all this. I think I know what I'm good at (does one really know what he's good at?) and what my business partners appreciate. I like to think of myself being a very good all round-programmer. At least, that's what I've been told and that's where people are seeking my expertize. In a recent (game development) project the lead programmer pushed me from one area of expertize to another one: core development, AI, network, logic, ... Mostly I've done preparation work; making things usable for the other programmers. I was quite astonished when I was assigned being the lead for a group of 5 AI programmers. It's quite an unusual position for a freelance programmer on a project.

Along the above mentioned statement by John Carmack I like this phrase (I can't remember who originally said it): "Nothing is impossible, it's just a matter of time and money." That's what I mostly stick to. There's always a solution or a compromise for a problem. I like to dig into development problems (of whatever kind) and to try to find the "right" solution to the problem. I like easy-to-use solutions. Those, where only a few lines of code empower you to achieve a lot of things. I also like the idea of plug-in technology and working with interfaces. But this is not always the right solution, especially if your project is on a tight schedule and it's more important to finish things (and make them work) rather than make them reusable.

Well... we'll see what life brings on :)

Have fun,
Stefan

PS: Ah yes... I almost forgot: I'll marry the woman I'm with since 16 years now on august the 23rd...

Tuesday, August 05, 2008

Restart

Hi,

although I have this account since 2006, I did not really post any entries. Hopefully this will change since I would like to share some of my experiences I make during the development of my spare time applications and games.

To give you some backstory: I've been in games business since 12 years now. Throughout this time span I was a simple programmer, translator (german->french), senior developer, lead developer, project manager, head of technology and freelance developer. I had the fortune to work with some of the best German game developers and some of the most talented German graphic and sound artists you might encounter. It was (mostly) a pleasure working with them although I managed to upset one person to a point he won't even talk with me anymore (at least one of whom I know).

The game genres I worked on were wide spread: from turn based strategy games through sports games up to casual games. The only thing I never programmed was an FPS.

In the recent years I sometimes turned away from game development to jump into the area which is called "serious applications" by the game developers. In fact, I made some quite interesting experiences there. I had the chance to contribute to the research and development of embedded hardware, wrote (mostly as a sole developer) the voice recognition, client-server based picking solution for one of the biggest spare part warehouses of Europe and contributed and still contribute to the development of a business application for a German music label and the planning and maintenance of an industrial CAD software.

Some month ago I published my own lib called SSCXML which is the first publicly available implementation of the SCXML draft (state chart XML) by the W3C.

In my spare time I started working on a small game called "Prohibition". It'll be a turn-based strategy game where the player must lead a police squad in it's fight against organized crime in the early 20th century. Since I'm working all alone on this project, progress is slow. I also tend to research and experience some programming ideas I have with this project. The game itself will be fully multiplayer targeted. Currently I'm working on the very base of the game: network layer, client-server structure, object management, ...

I think I'll post some of the things I do in this project in this blog :)

Have fun,
Stefan

Labels: , ,