This week I fixed all the major bugs (that I’m aware of) in Bleed 2’s engine! One of them was a problem with how enemies take damage, which I’m giving a big run-down of today.
First off: how damage worked before. Enemies and player attacks are made up of one or more hitboxes — when the hitboxes touch, the enemies take damage. Easy, right?
Weeeeelllll, not quite. The katana’s hitbox, for example, is large and can easily strike multiple hitboxes at once. If those hitboxes all belong to the same enemy, like a boss, the boss gets hammered with “you got hit!” notifications (one per hitbox), multiplying the damage like crazy.
The easiest way to fix that was to make it so enemies only accept damage once per frame — that’s how I solved it for the original Bleed, and how it’s remained since 2011.
But, after lots of testing, I see there are tons of flaws with the system. In co-op play, if two players hit a boss at the same time, only one hit counts. Even in single-player, bosses can take indirect damage — usually from being parried — and if you shoot them on that exact frame, the massive parry damage is blocked by the bullet damaging them first. It doesn’t happen often, but when it does it feels like getting robbed.
My first solution was for some attacks to have an “always hit” option that forced the damage through no matter what. That fixed parry damage but didn’t solve any of the other problems, so I kept looking.
The next idea was for enemies to keep a list of attacks that had hit them, so they’d only allow each attack to damage them once per frame. This would have been the perfect solution, except for the invisible damage volumes that come with each player attack.
Meant to hurt enemies that get too close to be hit by the actual bullets, these special attacks do a reduced amount of damage so that playing properly is always the best option. Under the new rules, the best strategy would be to get close enough to hit bosses with both the bullet and the invisible damage volume, doing something close to double damage.
Finally, I arrived at what seems to be the optimal solution. Every frame, enemies can take one attack each from three different sources: player one, player two, and reflected damage. Further, all attacks from each source are compared, and the highest-damage attack from each source is the one the enemy is actually hurt by.
The solution has its weaknesses. If two bullets from the same player hit an enemy exactly at once, only one bullet will hurt it — it’s not easy to do, but possible. The same thing can happen with reflected bullets, when bosses fire tight groups of shots at once — it’s only realistically possible with a handful of the bosses, though.
So while it isn’t 100% perfect in every situation, it solves 98% of them or more, and that’s a compromise I can live with. Nobody (but me) seemed to notice when things were horrible broken previously, so I think this new method that actually works properly will suffice.
All this work makes me wonder how other action games solve the problem — but on the other hand, maybe it’s only me game and how I’ve coded it that creates the issue, haha. Either way, I hope it was vaguely interesting to read about the kind of coding/design issues I’m facing! Thanks for sticking through it!