Як створити клас атаки в грі RPG?


37

Я перебуваю на етапі планування невеликої гри в стилі RPG.

У символу буде набір атрибутів, таких як сила, спритність тощо, які представлені у вигляді цілих чисел. У персонажа також буде набір атак, представлених як клас атаки.

При кожній атаці я хочу, щоб вона заподіяла шкоду на основі атрибутів символів, наприклад: "нахил меча" атаки буде робити 10 дмг + значення сили символів.

Я думав зробити це - мати абстрактний клас атаки, у якому є абстрактний метод Attack, і для кожної атаки я створюю один клас, який реалізує метод Attack.

public class SwordSlash:Attack
{
    public void Attack(Character attacker, Character defender)
    {
        defender.DoDamage(10 + attacker.Strength);
    }
}

Я бачу, що це дозволить підтримувати кошмар.

Хтось має уявлення про те, як я можу досягти цього більш приємно?

Я вважаю, що головна проблема полягає в тому, як ввести правильний атрибут на основі атаки.

Відповіді:


34

Тут, мабуть, варто звернутися до проекту, керованого даними.

Створіть загальний клас Attack, який містить параметри, з якими потрібно працювати - базовий збиток, який статистика впливає на шкоду, набір потенційних ефектів статусу ... подібні речі:

public enum AttackStat
{
  Strength,
  Agility,
  Intellect
  // etc.
}

public class Attack
{    
  private int baseDamage;
  private AttackStat stat;
  private double damageMultiplier;
  // ...and so on

  public void Attack(Character attacker, Character defender)
  {
    defender.DoDamage(baseDamage + attacker.GetStatValue(stat) * damageMultiplier);
  }    
}

// Put a method on Character to fetch the appropriate value given an AttackStat:
public int GetStatValue(AttackStat s)
{
  switch(s)
  {
    case AttackStat.Strength:
      return strength;
    case AttackStat.Agility:
      return agility;
    // etc.
  }
}

Потім помістіть свої атаки у файл, наприклад, XML-файл, і завантажте звідти дані:

<Attacks>
  <Attack name="Sword Slash" damage="10" stat="Strength" multiplier="1" />
  <!-- More attacks here -->
</Attacks>

Ви можете навіть розширити це, щоб отримати значення з декількох статистичних даних, скажімо, Fireball, де збиток обчислюється як від інтелекту, так і від пожежної статистики:

<Attack name="Fireball" damage="20">
  <StatModifier stat="Intellect" multiplier="0.4" />
  <StatModifier stat="Fire" multiplier="0.8" />
</Attack>

Якщо ви не хочете використовувати однакову формулу основної шкоди для всього (наприклад, обчислити магічний збиток, відмінний від фізичного пошкодження), створіть підкласи Attack для кожної потрібної вам формули та замініть Attack та вкажіть, який тип ви бажаєте у своєму XML-файлі.


1
+1, але я б навіть замінив GetStatValue на якусь таблицю пошуку, щоб уникнути підтримки цього оператора перемикача.

1
Проблема цього методу полягає в тому, що ви можете мати лише загальні атаки, керовані даними - ви не можете мати нічого, що використовує спеціальну логіку. У вас з'явиться дуже загальний набір предметів (як ви потрапляєте у warcraft
Iain

2
@Iain: Це дуже легко вирішити, просто додавши більше даних, щоб це дозволити. Наприклад, у вас може бути підклас SpecialAttack, який робить більше речей, або обчислює шкоду зовсім іншим чином. Це лише питання визначити потрібну вам поведінку, а потім висловити її як дані.
Майкл Мадсен

2
@Iain: Окрім того, що ви просто додасте більше полів, ви також можете вирішити, що деякі поля даних є виразами або кодовими блоками, наприклад, Lua. Гарне використання ортогональних компонентів також дає більш цікаві результати.

1
+1 для загальної ідеї керування даними. Я не згоден із пропозицією xml. Там є кращі формати - yaml, json або звичайний файл .lua, якщо ви вставляєте Lua.
egarcia


2

У мене був би клас зброї, який має метод нападу, який ви переважаєте над поведінкою, яку ви хочете. Потім ви також можете обробити, як виглядає зброя в грі, в інвентарі, скільки вона продається за тощо в тому ж класі.


6
-1, це не лише керування даними, це глибша ієрархія, а не керована компонентами. Це найгірше можливе рішення.

4
Тільки тому, що цей конкретний метод не керується даними, це не робить його поганим вибором, а ієрархія все одно не буде такою глибокою. Це просто, але все-таки потужно (UnrealEngine є прекрасним прикладом цього), якщо зроблено правильно (тобто немає твердо кодованих значень). Звичайно, у неї є свої недоліки, але в подальшому знижуючи цикл розвитку системи, керованої даними, я впевнений, що її недоліки проявляються. Я думаю, що ваш базовий дизайн OOP все ще є дійсним рішенням у цьому, і якщо він хоче на лету редагувати значення за замовчуванням, він може бути реалізований на вершині системи ієрархії так само легко.
Dalin Seivewright

6
Не все має керуватися даними - це залежить від масштабу гри. Напевно, трохи зарозуміло думати, що моя відповідь "неправильна", але дякую за вашу чесність. Я думаю, що це лише зіткнення стилів між тим, що працює для мене, виготовлення Flash-ігор щодня та вашою більш традиційною моделлю розвитку. Я можу вам сказати, що мій підхід реалізується набагато швидше, і ви краще перевіряєте час компіляції. Ваш коментар повторно. Lua припускає, що запитувач працює на платформі, яка б це підтримувала.
Iain

2
Будучи грою RPG, реально реалізувати кожен подібний предмет, мабуть, досить недоцільно.
Вуан Хілтс

1

Я справді новачок у цьому, але так, як би це зробити, - це створити загальний клас атаки.

Коли один екземпляр символу хоче атакувати інший екземпляр символу, він створить екземпляр класу атаки, наповнений необхідними даними, та ідентифікатором символу, який його створив. Потім коригування передач буде застосовано до об'єкта атаки, використовуючи дані, які можуть бути введені в XML-документ або подібний.

Цей екземпляр класу буде потім загорнутий в інший клас, щоб забезпечити гачки для оточення для визначення діапазону чи подібного. Якщо атака є дійсною, екземпляр атаки буде переданий персонажу, який атакується, який застосує ефекти.

Сподіваюся, що це мало сенс.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.