Design considerations for temporarily transforming a player into an animal in a role playing game
我正在做一个角色扮演游戏,以获得乐趣并练习设计模式。我希望玩家能够将自己变成不同的动物。例如,德鲁伊可能会变形成猎豹。现在我正计划使用装饰图案来完成这项工作,但我的问题是-我该怎么做才能让德鲁伊以猎豹的形式出现时,他们只能访问猎豹的技能?换句话说,他们不应该能够获得他们正常的德鲁伊技能。
使用装饰图案,看起来即使是猎豹形态,我的德鲁伊也能获得他们正常的德鲁伊技能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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 } } |
现在使用类
1 2 3 4 |
号
嗯……现在我想起来了,我的德鲁伊会不会不能让我们使用
你不应该把你的咒语和技能作为课堂上的方法。它们应该是可以通过角色(或者可能是生物)界面访问的咒语和技能对象的集合。然后,您的cheetaform可以覆盖getskills getspells方法,以返回一个新的修改过的适当技能集合。
很抱歉通知你们,但你们都错了,试图在不是钉子的东西上使用锤子。
为了解决你的问题,Mikedev你需要超越OOP,因为OOP不能正确解决这个问题。看看实体系统/组件系统。
你首先应该阅读的是http://www.devmaster.net/articles/oo-game-design/
然后你的游戏设计之旅将开始。
不要让druid成为从字符派生的类,而是考虑使用类型对象模式。首先,将角色类特定的技能分为自己的对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | abstract class Skill { void Perform(); } class LightHeal : Skill { public void Perform() { // stuff... } } class CheetahRun : Skill { public void Perform() { // stuff... } } // other skill classes... |
现在,通过这样做来摆脱派生的字符类:
1 2 3 4 5 6 7 8 9 10 11 | class CharacterType { public readonly List<Skill> Skills = new List<Skill>(); } class Character { public IEnumerable<Skill> Skills { get { return mType.Skills; } } private CharacterType mType; } |
。
现在可以将角色"类"创建为对象:
1 2 3 4 5 |
。
现在,通过将
也许你不需要将德鲁伊的技能集放到德鲁伊类中,而是可以将这个技能集移动到装饰器中。
忽略了这个名字很可怕的"StandardDruid"类,我希望你能看到我要做的是什么:)
这种安排有好处,即所有基于技能的代码都将一致地包含在decorator中,而不是一半包含在原始的druid类中,其余的技能则包含在decorator中。如果您要有另一个可以变形为druid的类,您可以很容易地做到这一点而不需要任何代码重复。
这个怎么样?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | interface ISkillState { ... } interface ISkill { ... } interface IForm { Collection<ISkill> skills { get; set; } Dictionary<ISkill,ISkillState> skillStates { get; set; } } class Character { private IForm actualForm; private Collection<IForm> currentForms; ... } |
例如:
1 2 3 | class Spell : ISkill {} class SpellState : ISkillState {} |
。
我只需要在德鲁伊类"form"中创建一个属性,并在施法时做一个if检查,看德鲁伊是否被转化。
我将通过将
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | class Druid : Character { // many cool druid skills and spells virtual void LightHeal(Character target) { } } abstract class CharacterDecorator : Character { Character DecoratedCharacter; } class CheetahForm : CharacterDecorator { Character DecoratedCharacter; public CheetahDecorator(Character decoratedCharacter) { DecoratedCharacter= decoratedCharacter; } // many cool cheetah related skills void CheetahRun() { // let player move very fast } override void LightHeal(Character target) { ShowPlayerMessage("You cannot do that while shape shifted."); } } |
号
每当我玩一个涉及这类场景(如魔兽世界)的游戏时,用户界面都会改变以防止这些法术被施法,但用户仍然可以尝试通过宏来施法,因此以这种方式处理它有助于阻止这种情况。
我认为没有一种方法可以"隐藏"方法而不使用