Procedural Animation 1: State Machines

Intro

This is the first in a 3 part series on procedural animation, all taken from a talk I gave in January of 2019. The posts ramp up in complexity, and I've tried to make the animations interactive where possible!

  • This first post justifies and covers a general mentality I have for working on procedural animations, and applies it to a simple example.
  • The second post gives a more powerful and harder tool - talking about function shapes, and how you can build more complex behavour by combining simple movements.
  • The third and final post (coming soon) covers inverse kinematics, and generally how to approximate solutions much harder problems using gradient descent.

All of the animations are running in javascript canvas, so you can open the source code in the inspector or find it on my github for the site!

Differences vs traditional animation.

  • Advantages:
    • Greater (infinite?) variety. Simulate large numbers easily.
    • Can react to player/ world better.
    • When done well: More realistic.
  • Disadvantages:
    • Loss of control. Can be harder to tweak.
    • Hard to get very charachterful movement. Can look robotic (Unless that's intentional…)
    • When it breaks it often breaks hard.

State, Update & Apply

This is the core of how I approach these animations. I find it's helpful to try and break down the system into 3 parts - State, Update, and Apply. These systems can very easily become hard to tweak and work with, and this is just one tool that might help with that.

  • State:
    • One or more variables, no logic.
    • All we need to know to draw a frame
  • Update:
    • Changes (only) state variables on each frame or update cycle.
  • Apply:
    • Move and/or draw stuff according to state.

Each part can be thought about separately, and by moving the state into a clear separate variable the system becomes much easier to reason about. Animations won't go out of sync, and it's to debug as you can just view and edit the state directly.

Anyway… Lets look at an example!

Example: Light

State machines are one of the simplest forms of procedural animation. The idea is there is a single 'state' we're in, and also a set of rules for why/ when we change state. State machines are often used in game AI - where states might be { Defend, Rush, Flank }, or for a character: { Falling, Walking, Sprinting, Attacking }.

Here we've just got a light, our State is one of: { On, Off }.

Your browser sucks :c.

Anim 1: Randomly flickering light.

The second part of State, Update, Apply: Update, is also simple. We randomly choose to either stay in the current state or move to the other. I found a \(98\%\) chance to stay On and a \(93\%\) chance to stay Off works decently.

We can view the state and the transitions as a graph, where the arrows denote probabilities.

light_state.png

Figure 1: Light state diagram

And finally, our Apply section simply determines if we should draw a circle that frame, or leave the frame blank.

Overall, our code looks like this…

// STATE
bool _on = false;

void Update(float dt) {
    // UPDATE:
    if (_on && Random.value > 0.98) {
	_on = false;
    }
    else if (!_on && Random.value > 0.93) {
	_on = true;
    }

    // APPLY:
    if (_on) {
	// Draw here!!
    }
}

Tune in next time for some more interesting examples!