Slow Rush Studios logo,
    depicting an apprehensive-looking snail rushing forward

Slow Rush Studios

◂  Rocking Shields
News index
Mine Your Own Business  ▸

Building a Spellbar

Contents

If a player summons two elements that merge into another element, but the player didn't see the merging happen... did the merging even happen?

Not really! From the player's perspective the game is just unpredictable.

But, our new animated spellbar fixes that - and it was damn tricky to build!

Status Quo

A few weeks ago I implemented a quick and dirty spellbar:

Summoning 3x Water, 4x Fire, 1x Lightning on the old spellbar.
Combining to Steam happens instantly, so you better pay attention!

Since elements combine instantly, spells can be cast straight away - which is really nice.

The only problem was you couldn't tell what element combinations actually happened - even I had trouble telling bugs apart from intended behaviour.

I wanted something like Magicka's spellbar, where you can see the elements combining visually. 1

Clarity vs Responsiveness

As I started implementing an animated spellbar, I realised I have two conflicting goals:

So the existing interface had great responsiveness, at the cost of terrible clarity.

But, animating the element combining to improve clarity would also make spellcasting less responsive: a poor implementation would make players wait for Fire and Water to merge before they could cast their Steam spell.

Representations

My first idea was to enable "fast forwarding" the animation: if the player triggers a cast while the animation is still playing, then just run the animation 1000 times faster - the animation will finish near-instantly and the game can use the result to cast the right spell.

That could have worked, but seemed hard to tweak and debug. And someday I'd like summoned elements wizzing around the player character and visually combining & cancelling there too; I would have to somehow keep that in sync with the animated spellbar.

So instead I made two separate spellbars:

  1. An Instant Spellbar, where elements combine and cancel instantly. This simple, but hidden from players and only used to figure out what spell should be cast.
  2. An Animated Spellbar, where all the element operations are animated. (This is super complicated, but we'll get to that.)

Internally each element combination is expressed as a rule (e.g. there must be only 1 Shield), and so each rule gets checked against the Instant Spellbar and necessary fixes get applied (like insta-removing the excess Shield) .

But! Each fix for a violated rule is recorded so that the Animated Spellbar can schedule an equivalent fix-up (like slowly fading out the excess Shield).2

That was a ton of words, so here's the new spellbar in action:

The new Animated Spellbar, with the same 3x Water, 4x Fire and 1x Lightning summoned as before.

Animating Elements

Animating elements (in response to those recorded "fixes") to get the above is tricky:

So if you don't have the right design, you get something like this:

A broken earlier attempt: the 2nd fire gets stuck because it's being animated to move to two positions at once.
(White text is the trusty Instant Spellbar displayed for debugging, blurry red text is animation debug data.)

After the false starts and a bit of brainstorming,3 I ended up with an animation graph:

  1. Each animation controls only 1 thing, like rescaling or moving a single element.
  2. Each animation can be blocked by other animations.
  3. When an animation X finishes, we kick off any animation Y that X was blocking (only if Y has no other blockers).

So each "recorded fix" results in a few of these animations being queued up; I also make each animation blocked on all previous animations that affect the same element, which minimizes the amount of concurrent changes.

This means that a Fire combining with a Water is represented like this: 4

Animation graph of Fire combining with Water
In order (top to bottom): Fire increases in size, Fire moves to where Water is, Fire gets Hidden, Water gets its displayed element swapped to Steam.

And for fun, a Water absorbing 4x Lightnings is represented like this:

Animation graph of Lightning being absorbed by Water
I'll let you decipher this one. I've already stared at enough of these!

I also fiddled a lot to get the speed to feel decent:

Here's a more complicated example to demonstrate:

Water absorbing Lightning, Arcane cancelling Life and Water, Earth & Arcane making Oil.
(The Shield is just a filler element.)

The graphics are still placeholders, of course.

Stress testing

Naturally this was a major pain to flush bugs out of, so I added a little stress test:

Stress test in action: a new random element is summoned every few milliseconds.
(Video isn't sped up - the animations naturally are playing faster because elements are summoned quickly.)

Playable web build‎

Alright here you go: summon some elements with QER/1234. (Yeah, I'm trying out not needing to hold Shift - seems good so far?)

Press F1 for help, including to see keyboard/mouse controls. Mobile devices probably won't work!

(Pssst. If you look around real careful-like you might even find the new spell I implemented too.)


2

And a future "elements all wizzing around the player character" display could also update itself based on those recorded fixes.

3

Thanks Zeddy!

4

I'm using petgraph as my graph data structure, which can output graphs in DOT format; then I have a debug option that invokes GraphViz to render the graphs as PNGs like those shown below. It's been super useful for debugging!

5

Mathematical functions which remap 0-1 to some other numbers - check out easings.net.

In this context, they're an easy way to make animations "start fast, finish slow", "bounce when reaching destination", etc - which can help players understand what's going on.

◂  Rocking Shields
News index
Mine Your Own Business  ▸