Вложенные if / else, переключатели или что-то более эффективное для RPG-боя?

Я разрабатываю RPG с поворотом в java для телефонов Android, и сейчас я пытаюсь выяснить, как обрабатывать атаки, у которых есть дополнительные переменные за пределами урона. Например, я хотел бы, чтобы огненные атаки наносят дополнительный 10-процентный урон, когда цель имеет эффект ожога. Я немного не уверен, как это сделать эффективным образом, и это позволяет будущим дополнениям к моей системе статуса / атаки.

Итак, вот мои мысли о том, как я могу это сделать:

  1. Серия операторов if / else или switch

    switch (status) { case burned: if (type == fire) { damage = damage * 1.1; } break; case frozen: if (type == ice) { damage = damage * 2; } break; } 

    Я мог бы также использовать вложенные ключи, если у меня есть много возможных результатов для каждого состояния.

  2. Используйте двухмерный массив со значениями x являющимися статусами, а значения y – атаками или типами. Когда вы проверяете [x][y] он возвращает числовое значение для изменения, которое произойдет при атаке.

      Burned Frozen Fire [1.1] [1] Ice [1] [2] 

Хотя пока оба они кажутся прекрасными, я не уверен, что это сработает в будущем. Прямо сейчас, я могу, конечно, использовать комбинации, которые изменяют количество урона, но как насчет атак, которые имеют не численные эффекты, когда я не могу просто вернуть значение и умножить свой урон на это значение?

Можно ли создать какой-то код, который представляет такую ​​ситуацию, как:

 Burned = 1 в первой позиции, замороженный = 2
 Fire attack = f во 2-й позиции, ice = i
 Мотив повреждений находится в 3-м положении

Поэтому огонь на сожженном враге будет 1-f-1.1 .

Вы должны попытаться использовать полиморфизм.

Для переключателей / if-elses

Создайте интерфейс, который представляет атаки, и пусть он объявит один метод:

 public interface Attack { double doAttack(double baseDamage); } 

Затем создайте классы, реализующие этот интерфейс:

 public class FireAttack implements Attack { double doAttack(double baseDamage){ return 1.1 * baseDamage; } } public class IceAttack implements Attack { double doAttack(double baseDamage){ return 2 * baseDamage; } } 

Затем вместо использования операторов switch в вашем коде выполните следующие действия:

 public class Player { private Attack mAttack; // Somewhere in your code, you setup something like void setFireWeapon(){ mAttack = new FireAttack(); } // This is where the attack is taken care of double inflictDamage() { return mAttack.doAttack(); } } 

Это позволяет вам реализовать любой новый тип атаки, который вам может пожелать в будущем, и просто назначить Attack mAttack этой новой реализацией интерфейса Attack . Это тривиальный пример, вы можете сделать что-то гораздо более мощное, чем baseDamage * aDouble если хотите.

Для статуса (сожженного / замороженного)

Существует много способов реализовать такие состояния, как замороженные. Сначала вы можете использовать тот же шаблон, который я объяснил выше.

Помимо того, что у Attack mAttack элемент Attack mAttack , вы также можете добавить аналогичную логику с помощью HealthStatus mHealthStatus или любого HealthStatus mHealthStatus имени, которое вы предпочитаете. Тогда вызов inflictDamage() перенаправит объект mHealthStatus объект mHealthStatus .

Тогда класс HealthStatus снова будет интерфейсом,

 public interface HealthStatus { double considerAttack(Attack anAttack); } 

Которая имела бы реализацию различных состояний:

 public class NormalStatus implements HealthStatus{ double considerAttack(Attack anAttack){ return anAttack.doAttack(); // No change here } } public class FrozenStatus implements HealthStatus{ double considerAttack(Attack anAttack){ return 0; // Can't attack when froxen } } public class BurnedStatus implements HealthStatus{ double considerAttack(Attack anAttack){ return anAttack.doAttack() * 2.0; // Get berserk when on fire! } } 

Вы также можете использовать другие шаблоны. Я рекомендую вам взглянуть на Design Patterns, которые решают проблемы, подобные тем, с которыми вы сталкиваетесь.

Просто назвать несколько.

AntonieG находится на правильном пути. Общее решение этой проблемы – использовать шаблон стратегии разработки.

стратегия

мотивация

Существуют обычные ситуации, когда классы отличаются только поведением. Для этих случаев целесообразно изолировать алгоритмы в отдельных классах, чтобы иметь возможность выбирать разные алгоритмы во время выполнения.

умысел

Определите семейство алгоритмов, инкапсулируйте каждый из них и сделайте их взаимозаменяемыми. Стратегия позволяет алгоритму варьироваться независимо от клиентов, которые его используют.

Реализация

Шаблон стратегии Impl http://www.oodesign.com/strategy-pattern.html

Также взгляните на следующие ссылки.

http://en.wikipedia.org/wiki/Strategy_pattern

http://blogs.microsoft.co.il/blogs/gilf/archive/2009/11/22/applying-strategy-pattern-instead-of-using-switch-statements.aspx

Ваше мышление кажется слишком линейным. Используйте объектно-ориентированные принципы для разработки вашей игры. Создавайте классы для своих атак, которые расширяют общую атаку.

 public abstract class Attack{ protected String attackName; protected Double damage; public Attack(){ attackName = "Standard"; damage = 1.0; } public Double getDamage(){ return damage; } public String getAttackName(){ return attackName; } } 

Затем продолжим:

 public class FireStorm extends Attack{ public FireStorm(String attackName, Double damage){ this.attackName = attackName; this.damage = damage; } @Override public Double getDamage(Enemy target){ if(target.hasBurnEffect()){ damage *= 2.0; } else { damage = super.getDamage(); } return damage; } } 

Я не очень много знаю о масштабах вещей в вашей игре, поэтому я не могу сделать это слишком много описательным. Но если вы хотите сделать свою игру гибкой и расширяемой, как вы предлагаете, то вам захочется использовать наследование и другие принципы объектно-ориентированного программирования.

Intereting Posts
Как показать количество уведомлений на значок приложения, например Facebook? Ошибка: для Multi Dex требуется версия Build Tools Android Lollipop EditText: автозаполнение не работает для адресов электронной почты Проблема при удалении библиотеки supportV4 Изменение размера изображения с высокой эффективностью в Android WebView.setWebContentsDebuggingEnabled (false), но я могу отлаживать код после установки подписанного APK Фотосъемка при записи видео на Android Телефонная связь: сбой передачи файлов на Android Как получить текущее местоположение GPS (широта-долгота) с помощью Google API в приложении для Android? Обновление приложения для Android с eclipse Android NFC transceive () с использованием технологии NFCF (Sony Felica) Как получить представление вкладки TabLayout? Android 4.0.3 ScrollingTabContainerView NullPointerException Приложение ListView для обмена сообщениями показывает неправильный макет listItem после прокрутки Что означает «ICU» в Android SDK?