-
Enemy classes
In proffesional game programming, is an enemy class derived from say a base
class?
I mean. all the data members of the base class would be protected, so the different enemys, eg: slug, spider can use the functions of the base class?
Am I right in this assumsion?
Thanks in advance for any reply
-
I can't speak for professional game programmers, but it makes sense to me.
-
It seems as though you're suggesting that every enemy has it's own class and I wouldn't expect that to be the case. An enemy is an enemy... each specific enemy is just another instance of the enemy class with it's own settings for each variable. Whether or not it's derived from a base character class is up to the designer.
I've written a few RPG implementations and in almost all of them, the "enemy" class did derive from a base character class. This is because my PC and NPC class derived from the same base class and my "zone" class could now contain a vector of base character class pointers which could now hold enemies, players, and NPCs... get it?
-
well, yes, usually an enemy-class will be derived from some base class.
the point of that is, that non-player-characters, player-characters, and e.g. trees can be treated all the same way if they all have a common interface.
the point of the base class is providing an interface.
>> so the different enemys, eg: slug, spider can use the functions of the base class?
yes
>> all the data members of the base class would be protected
you can also define classes only with pure virtual functions - in that case the base class' only purpose is to provide the interace - without any implementation.
of course deriving from a base class is used to extend the functionality of the base class.
-
I agree and think it's a good idea to derive from a base enemy class. Then you can tailor each enemy as you see fit in derived classes. The more functionality you put in the base, the more you gain in the derived. But keep the base class functions and members very generic and not tailored to any one type of enemy.
For instance all enemies must move and all of them prob follow a vector. All enemies must be able to go to waypoints, etc, etc.
I would keep my derivations to a maximum of 1 or possible 2 levels of inheritance (derive from base only once and once from derived) as multiple derivations will probably just serve to confuse and obfuscate the code.
This also allows you to specify an enemy manager class that contains a vector or list of enemies. Since you are deriving all enemies from a common base, if you make the list or vector that contains the base type you can add any object that has been derived from base. This makes managing the objects quite simple.
Code:
class CEnemy
{
};
class CSpider:public CEnemy
{
};
class EnemyMgr
{
protected:
std::vector<CEnemy *> m_vEnemies;
...
public:
...
DWORD Add(CEnemy *pEnemy)
{
m_vEnemies.push_back(pEnemy);
return static_cast<DWORD>(m_vEnemies.size()-1);
}
};
Now you can do this:
Code:
Spider *pBadDude=new Spider();
DWORD dwSpiderIndex=m_pObjectMgr->Add(pBadDude);
-
another good point about interfaces is: if you have a generic interface, you can then either hard code your enemy (so make a class that is derived from the interface) or script your enemy (and make a class that is derived from the interface and communicates with e.g. a virtual machine the script is run on).
that way your engine doen't have to bother how your object is implemented - it just cares for the interface.
(ok, but thats advanced stuff)
(the engine then must also provides a generic interface for e.g. requesting objects registered with it (e.g. all monsters, trees, items) - so the scripts also need to operate on an interface)