Knights Province needs a lot of animations. They are essential to making the games’ world feel alive. Here’s how they work and how they just got better.
Animations start with a skeleton rig. Rig is a description of how character skeleton bones are located and which of the characters parts they affect. Typical character rig in Knights Province consists of ~20 bones. 20 is a good compromise between animation visual quality (more is better), animation cost (less is cheaper) and game’s performance (less is faster). Typical rig looks like this:
After the rig comes the animation. Typical animations are made by an artist in 3D modelling app (Blender, Maya, etc.) with keyframes. Keyframes are bones positions at specified times. For example a simple walk animation has 2 keyframes for legs movements, spine, arms and head (this is much alike “penguin” walk animation was made).
Once animation is made it gets exported into format compatible with the game. Simplest way is to record each animation frame (each bones position and orientation) at fixed frame-rate (typically 30). This way, 3 seconds of exported animation look like a list of 90 frames, each describing each bone’s position and rotation in the rig:
At 30 frames of animation per second it looks good enough.
When in game, every house and character has some state. This state links to an animation (e.g. work state of a Stonecutter links to a stonecutting animation). The game then knows that it needs to render a Stonecutter using the stonecutting animation and choose a specific frame.
Simple approach of choosing an animation frame was to see when the state has started, calculate state duration to the moment, then convert this into an animation position (picking closest frame). E.g. Stonecutter has been cutting the stone for 2.3 seconds:
Round(2.3 * 30 / animation_framecount)
Interpolating is very similar to the approach above – it takes two closest frames and “blends” them together proportionally. For this we take pairs of bones from each frame and linearly interpolate between them, obtaining new bone position/orientation.
Best example of interpolation is a Mill:
Mill blades make a full revolution in 6 seconds. Before interpolation that would require 6*30 = 180 frames of animation (that would still look choppy in high fps, cos every frame is strictly 2 degrees apart). Now, with interpolation we can do just 2(!) frames. First frame at 0 rotation, second – at 360 degrees (perfectly looped, since 0 = 360). Now every time the blades are rendered their rotation gets interpolated between 0 and 360 degrees, giving us the best smooth animation!
Of course interpolation has some caveats as well. Now we need to be careful about animations, so that bones rotations do not reset to 0 when passing 360 degrees. Otherwise interpolating between 359 on one frame and 1 on other would give 180 instead of 0.