为角色扮演游戏中的"角色"设计一个干净/灵活的方式来施放不同的法术

mik*_*dev 9 c# design-patterns

我正在创建一个角色扮演游戏,以获得乐趣和学习体验.我正处于我的角色(巫师)施放法术的地步.我正在使用战略模式来设置他们在施放法术之前施放的法术.我采用这种方法的原因是因为我希望以后能够添加不同的拼写类型,而不必弄乱角色/向导类.

我的问题 - 这是一个糟糕的设计吗?对此有更好/更清洁/更简单的方法吗?

我试图远离那个试图让一切都融入设计模式的"那个人".但在这种情况下,我觉得这是一个不错的选择.

这是我的代码到目前为止使用2个法术的样子

public class Wizard : Creature
{
   public List<Spell> Spells { get; set; }

   public void Cast(Spell spell, Creature targetCreature)
   {
      spell.Cast(this, targetCreature);
   }
}

public abstract class Spell
{
   public string Name { get; set; }
   public int ManaCost { get; set; }
   public Spell(string name, int manaCost)
   {
      Name = name;
      ManaCost = manaCost;
   }
   public void Cast(Creature caster, Creature targetCreature)
   {
      caster.SubtractMana(ManaCost);
      ApplySpell(caster, targetCreature);
   }
   public abstract void ApplySpell(Creature caster, Creature targetCreature);
}

// increases the target's armor by 4
public class MageArmor : Spell
{
   public MageArmor() : base("Mage Armor", 4);
   public override void ApplySpell(caster, targetCreature)
   {
      targetCreature.AddAC(4);
   }
}

// target takes 7 damage
public class FireBall : Spell
{
   public FireBall() : base("Fire Ball", 5);
   public override void ApplySpell(caster, targetCreature)
   {
      targetCreature.SubtractHealth(7);
   }
}
Run Code Online (Sandbox Code Playgroud)

现在施放一个咒语,我们做这样的事情:

Wizard wizard = new Wizard();
wizard.Cast(new Spell.MageArmor(), wizard); // i am buffing myself 
Run Code Online (Sandbox Code Playgroud)

更新:更新的代码与以下答案中的一些建议

Ben*_*gan 6

按照Willcodejavaforfood的说法,你可以设计一个SpellEffect描述你的咒语可能产生的单一效果的类.您可以创建一个"词汇表"来用来描述:

法术属性:

  • 名称
  • 法力消耗
  • 整个法术的目标限制(玩家,npc,怪物......)
  • 法术总持续时间(法术效果持续时间最高)(10秒,5个刻度,......)
  • 施法时间
  • 法术范围(5米,65个单位......)
  • 失败率(5%,90%)
  • 在此法术可以再次施放之前等待的时间(重建时间)
  • 在任何法术可以再次施放之前等待的时间(恢复时间)
  • 等等...

SpellEffect的属性:

  • 效果类型(防守,进攻,buff,debuff ......)
  • 效果的目标(自我,党,目标,目标周围区域,目标线,......)
  • 属性或属性作用于(马力,法力,最大马力,力量,攻击速度......)
  • 效果改变了多少(+ 10,-500,5%,...)
  • 效果持续多长时间(10秒,5个刻度,...)
  • 等等

我想你的词汇(上面括号中的单词)将在一组枚举中定义.也可能建议创建一个类层次结构来表示SpellEffect类型,而不是使用该特定属性的枚举,因为可能存在不需要所有这些属性的SpellEffect类型,或者可能存在某种自定义逻辑每个基本的SpellEffect类型,我没有想到.但这也可能使事情变得太复杂.KISS原则=).

无论如何,关键是你要将关于法术效果的特定信息提取到一个单独的数据结构中.这样Spell做的好处是你可以创建一个类并使其保持一个SpellEffects列表以在激活时应用.然后该法术可以一次执行多种功能(伤害敌人和治疗玩家,又名生命攻击).您为每个法术创建一个新的法术实例.当然,在某些时候,你就会有实际创造的法术.您可以轻松地将拼写编辑器实用程序放在一起以使其更容易.

此外,通过使用System.Xml.Serialization的XmlSerializer类,可以非常轻松地将您定义的每个SpellEffect 写入XML并从XML加载.在SpellEffect这样的简单数据类上使用它是一件轻而易举的事.您甚至可以将最终的拼写列表序列化为xml.例如:

<?xml header-blah-blah?>
<Spells>
  <Spell Name="Light Healing" Restriction="Player" Cost="100" Duration="0s"
         CastTime="2s" Range="0" FailRate="5%" Recast="10s" Recovery="5s">
    <SpellEffect Type="Heal" Target="Self" Stat="Hp" Degree="500" Duration="0s"/>
  </Spell>
  <Spell Name="Steal Haste" Restriction="NPC" Cost="500" Duration="120s"
         CastTime="10s" Range="100" FailRate="10%" Recast="15s" Recovery="8s">
    <SpellEffect Type="Buff" Target="Self" Stat="AttackSpeed" Degree="20%" Duration="120s"/>
    <SpellEffect Type="Debuff" Target="Target" Stat="AttackSpeed" Degree="-20%" Duration="60s"/>
  </Spell>
  ...
</Spells>
Run Code Online (Sandbox Code Playgroud)

您还可以选择将数据放在数据库而不是xml中.Sqlite会小巧,快速,简单且免费.您还可以使用LINQ从xml或sqlite查询拼写数据.

当然,你可以为你的怪物做类似的事情 - 至少对他们的数据来说也是如此.我不确定逻辑部分.

如果你使用这种系统,你可以获得额外的好处,可以将你的生物/法术系统用于其他游戏.如果你"硬编码"你的法术,你就不能这样做.它还允许您更改法术(类平衡,错误,无论如何),无需重建和重新分发您的游戏可执行文件.只是一个简单的xml文件.

天啊!我现在对你的项目感到非常兴奋,以及我所描述的内容是如何实现的.如果您需要任何帮助,请告诉我!

  • 我喜欢“那么咒语可以执行多种功能”。TheElderScroll 允许您使用游戏内编辑器来做到这一点:) (2认同)

Jos*_*osh 1

出于某种原因,“咒语”对我来说更像是一种命令模式。但我从来没有设计过游戏所以......