Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Design considerations for temporarily transforming a player into an animal in a role playing game

I am working on a role playing game for fun and to practice design patterns. I would like players to be able to transform themselves into different animals. For example, a Druid might be able to shape shift into a cheetah. Right now I'm planning on using the decorator pattern to do this but my question is - how do I make it so that when a druid is in the cheetah form, they can only access skills for the cheetah? In other words, they should not be able to access their normal Druid skills.

Using the decorator pattern it appears that even in the cheetah form my druid will be able to access their normal druid skills.

class Druid : Character
{
   // many cool druid skills and spells
   void LightHeal(Character target) { }
}

abstract class CharacterDecorator : Character
{
    Character DecoratedCharacter;
}

class CheetahForm : CharacterDecorator
{
    Character DecoratedCharacter;
    public CheetahForm(Character decoratedCharacter)
    {
       DecoratedCharacter= decoratedCharacter;
    }

    // many cool cheetah related skills
    void CheetahRun()
    {
       // let player move very fast
    }
}

now using the classes

Druid myDruid = new Druid();
myDruid.LightHeal(myDruid); // casting light heal here is fine
myDruid = new CheetahForm(myDruid);
myDruid.LightHeal(myDruid); // casting here should not be allowed

Hmmmm...now that I think about it, will myDruid be unable to us the Druid class spells/skills unless the class is down-casted? But even if that's the case, is there a better way to ensure that myDruid at this point is locked out from all Druid related spells/skills until it is cast back to a Druid (since currently it's in CheetahForm)

like image 770
mikedev Avatar asked Feb 08 '10 09:02

mikedev


2 Answers

You should not have your spells and skills as method in the class. They should be a collection of Spell and Skill objects which are accessible through the Character (or possibly Creature) interface. Then your CheetaForm could override the getSkills getSpells methods to return a new modified collection of appropriate skills.

like image 75
willcodejavaforfood Avatar answered Sep 27 '22 16:09

willcodejavaforfood


Maybe rather than placing the skill set for a Druid into the Druid class, you could move this skill set into a decorator itself.

Druid myDruid = new Druid();
myDruid = new StandardDruid(myDruid);

Ignoring the horribly named "StandardDruid" class, I'm hoping you can see where I'm going with this :)

There are upsides to this arrangement, namely that all of your skill based code will be contained consistently inside of decorators, rather than half inside the original Druid class, and the remaining skills in decorators. If you were to have another class that could morph into a Druid, you could easily do this without any code duplication.

like image 23
Adam MacLeod Avatar answered Sep 27 '22 17:09

Adam MacLeod