dimanche 25 décembre 2016

Software design solution - Game

Before getting to the point, I'll make an introduction of WHAT I am trying to do. I will then provide some code and finally state my issue/question/problem.

The scenario is the following: The battle system of a turn-based rpg game is designed. During the battle, player input can produce different results depending on the "current state" of the battle. I am implementing the State Pattern to solve this.

For example, if the battle is in the action selection state, then the player highlights the action he desires to take, using the UP and DOWN keys and then activates it using the ENTER key.

The next state that the battle system goes into, depends on the action chosen. E.g. if "Attack" is selected, the battle goes into the SelectTargetState. If "Spell" is selected, the battle goes into the SelectSpellState, and then into the SelectTargetState.

Below I provide some code in Java, including only the parts that are immediately relevant. After that, the actual question is asked.

// The BattleScene class, representing the whole battle system
public class BattleScene
{
    private State currentState; // The current state of the system
    // Below are all other attributes such as, heroes, enemies etc.
    ..
    ..

    public void input(int key)
    { currentState.input(key); }
    // The actual implementation depends on the state
    // As said above: "player input can produce different results,
    //  depending on the 'current state'"

    // Setter
    public void setState(State state)
    { currentState = state; }

}

// The abstraction of all States
public abstract class State
{
    // All of them contain a reference to the system they belong to,
    // so that they can "change/control" it
    private BattleScene parent;

    // Constructor
    public State(BattleScene parent)
    { this.parent = parent; }

    // The actual input handling is to be represented by subclasses
    public abstract void input(int key);
}

// A concrete State class, displaying a proper example
public class ActionSelectState extends State
{
    private String[] actions; // List of available actions
    private int index; // The currently "highlighted" action

    // Constructor
    public ActionSelectState(BattleScene parent, String[] actions)
    {
        super(parent);
        this.actions = actions;
    }

    public void input(int key)
    {
        switch(key)
        {
            case DOWN:
                incIndex(); // Increases index safely by 1
                break;
            case UP:
                decIndex(); // Decreases index safely by 1
                break;
            case ENTER:
                activateAction();
                break;
        }
    }

// THE ACTUAL PROBLEM - READ BELOW
    private void activateAction()
    {
        if(action.compareTo("Attack")==0)
            parent.setState(new SelectTargetState(parent));
        else if(action.compareTo("Spell")==0)
            parent.setState(new SelectSpellState(parent));
    }
}

The problem/issue is that for every possible action, there could be a different path and number of states to be followed. E.g.: - Attack->Select Target-> Execute Action - Spell->Select Spell->Select Target(s)->Execute Action - Item->........ - Possibly dozens of commands in the future....->....->....

The activateAction() above would then need dozens of "if..else". And what if other states need similar conditional selections depending on the action? That would require each state to have long "if..else" statements as well. Maybye even the number/kind of states change in the future, for instance more will be added.

Is there any sophisticated solution to this problem? Any way to make it resistant to scaling (i.e. avoid exponential increase in conditional statements)? Or am I limited to the large if..else (or switch..doesn't matter)?

Open to any ideas, suggestions, solutions. Maybye some different overall design? Another pattern? Additional patterns? If you want more details, let me know. Regarding code, you can also provide equivalent C++ code if it's more convenient for you. I'm interested in a design solution, from a software engineering point of view...not in language specific solutions.

Aucun commentaire:

Enregistrer un commentaire