Reputation: 621
I'm writing a game and would like an opinion on my class hierarchy.
Currently I have an Character class, an AICharacter class and a KnightCharacter class.
Character holds things like Death() which all characters must facilitate, AICharacter overrides Death() with extra details for AI driven characters. KnightCharacter overrides Character stuff like handling of Shields(Only for Knights).
How can I elegantly allow my player to possess a KnightCharacter : Character and my AI to posses a KnightCharacter : AICharacter : Character?
I bascically want to only implement the AICharacter when its being controlled by an AI.
Thanks
Upvotes: 0
Views: 162
Reputation: 52250
What you're asking isn't possible with ordinary c# inheritance. Your brother can't have a different grandfather from you.
Since you seem to be looking for ideas, here's one that uses generics:
abstract class BaseController
{
virtual GameEvent ReadNextEvent();
}
class PlayerController : BaseController
{
override GameEvent ReadNextEvent
{
return userInterface.ReadNextEvent();
}
}
class NonPlayerController : BaseController
{
override GameEvent ReadNextEvent
{
artificialIntelligenceEngine.Think();
return artificialIntelligenceEngine.ReadNextEvent();
}
}
abstract class Character<T> where T : BaseController
{
protected T controller;
abstract ProcessEvents();
}
class KnightCharacter<T> : Character<T>
{
override ProcessEvents()
{
var e = controller.ReadNextEvent();
switch (e.Action)
{
1 : SwingSword(); break;
2 : LiftShield(); break;
3 : Yell("None shall pass!"); break;
}
}
}
class Program
{
void Example()
{
var playerKnight = new KnightCharacter<PlayerController>();
var aiKnight = new KnightCharacter<NonPlayerController>();
}
}
Upvotes: 1
Reputation: 2211
One approach that gives a lot of flexibility is to break your characters and objects down into various aspects, where each aspect is its own class. Some examples of aspects that an action or RPG character might have are Health, Mana, WearsEquipment, UsesItems, MobileObject, PhysicalRigidbody, MeleeAttackPerformer, RangedAttackPerformer, MagicAttackPerformer, PlayerControlledMobile, AIControlledMobile, and even things like AudioSource, etc, etc... Each of these classes would derive from a common base, e.g. AspectMixin or something like that.
If you treat each of these classes as Mix-ins, then you gain a lot of flexibility in creating new archetypes that have the aspects that make sense for that type of actor. This will allow, for example, monsters and players to share the fact that they have health, but have different classes for controlling them (AI-controls vs player-controls). Further, the Health aspect can be added to a stationary object (e.g. a barrel), to allow it to be affected by damage.
To achieve this, your archetype objects store a list of aspects mixins for that archetype. Further, the aspects need to be able to query the main object for other aspects by type (or interface). It's a bit of work to set up, but that's the price of flexibility.
FWIW, this is the approach that the Unity Engine tries to encourage (consider they call them MonoBehavior: behavior..aspect...different words for the same concept), though many developers don't "get it" until they've made several failed prototypes in which classes quickly become monolithic.
To go back to your original question, it sort of depends on how many playable classes you have, and whether AI can control characters of the same classes. If so, it would best to abstract the Controls out of the characters, then have AIControls and PlayerControls derive from Controls, either of which is able to interface with your character class.
On the other hand if AI types can be broken into just a few various behaviors (aggressive monsters, peaceful NPCs), I would make each one an aspect.
Upvotes: 2