A New Battle-System


Since the release of the demo, we got a lot of valuable feedback.
While mostly positive, one of the major complaints was the battle system. The issues in the demo could have been solved, but I had concerns of the battles becoming too dull (break shield -> attack normally).
The shield breaking mechanic is a nice gimmick, but not deep enough to support the entire game. Also the battles started to feel repetitive and not that different from other games. This is why we decided to replace the whole thing.

Hello Battle-System #4
So while we were coming up with ideas for the new system, Sebastian suggested to also change the perspective to a front-view. I didn't like this at first, because I wanted a traditional side-view Final Fantasy stlye system. And it didn't look any more exciting than the current one.
But what if we took the Mode7 we are already using on the world-map and applied it here?
I tested this and with the addition of a few other ideas made a prototype in 2 days:


The main idea is that you have to time your attacks with a button press.
There is no indicator for when to press the button. You will have to find out yourself.
Also, each attack has different timings (just before the attack lands).
On top of that, you can reduce enemy damage with a timed button press.
For well timed button presses you will do more damage/reduce damage.

Another thing that is in there is an ActionPoint system.
Each action consumes AP. On round start, you will get just enough AP to execute a normal attack. You will also be rewarded extra AP if you hit the timings for the button presses well (2 stages, good and perfect) and other activities. You can then use these AP to use stronger skills.
This is the current status:



Next up

The next thing I am going to change is the sphere/item system.
We found out people loved to hord items, when we intended them to be used generously :/
This is such a fundamental (human) problem, that I don't think it could be solved well. The new system will still be based around finding spheres which have abilities.
This time, you won't loose them though. More on this another time.

---

Technical Structure

While the prototype was quick to build, the real system took a lot longer, especially removing the old battle-code.
The new one is separated in 3 distinct layers:

  • data
  • logic
  • renderer

The data is a class encapsulating all the state the battle will need. It contains the heroes and enemies, the phase in which the turn is currently in, if it's the heroes turn, particles, different systems, etc. It does not contain any logic whatsoever. It just holds the data, that's it.
The logic part takes the input of the player/enemy and transforms the data.
Finally the renderer just takes the data and draws it.
This structure makes it easy to write free standing functions, that take the data and then transform it.

Notes on allocation: What I have really become to appreciate is the simplicity of preallocating (nearly) everything.
In practice this means choosing an array with a maximum size already allocated instead of a more dynamic structure (e.g. linked list) or creating an object each time you want to represent something.
I implemented battle-conditions/status-effects and first wanted to create 1 class per condition. Then I figured that the conditions can only be on/off and have a duration of how long they are applied. Here is the simplified class:

class BattleConditions {
    int rounds[4];
    
    const int ATK_UP = 0;
    const int ATK_DOWN = 1;
    const int DEF_UP = 2;
    const int DEF_UP = 3;
    
    bool IsActive(int index) {
        return rounds[index] > 0;
    }
    
    void Activate(int index, int forRounds) {
        rounds[index] = forRounds;
    }
}

This works for all conditions. Now each hero and enemy has 1 of these condition classes.

class BattleData {
    BattleCondition conditions[];
    // ... other data
    BattleActor heroes[];
    BattleActor enemies[];
}

The reason the conditions are not inside the hero/enemy classes, is so that you can loop over them independently (and not load the whole BattleActor class into memory). This is not only more efficient, but I find it to be much easier to reason about when I see all the data pieces layed out this way.

Leave a comment

Log in with itch.io to leave a comment.