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

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

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

  1. Серия операторов if / else или переключателей

    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]
    

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

Будет ли возможно сгенерировать какой-то код, представляющий ситуацию, подобную:

сгорел = 1 в первой позиции, заморожен = 2
огненная атака = f во 2-й позиции, лед = i
мод урона находится в 3-ей позиции

поэтому огненная атака на сожженного врага будет 1-f-1.1,

3 ответа

Решение

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

Для выключателей /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 член, вы также можете добавить аналогичную логику с HealthStatus mHealthStatus или любое другое имя, которое вы предпочитаете. Тогда призыв к inflictDamage() перенаправит mAttack возражать против 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!
    }
}

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

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

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

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;
    }
}

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

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

стратегия

мотивация

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

умысел

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

Реализация

Стратегия Pattern 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

Другие вопросы по тегам