Monday, April 06, 2015

DevLog #1: That's Affine Transformation!

Todd alluded to the fact that we had to rework some of our math to make things work in our zeroth log. Unlike his diagnosis, I don't believe we were lying insomuch as just being sloppy. When I program a 2D platformer, I think in 2D, I breathe 2D, and I calculate in 2D. That's usually fine until it isn't.

For example, in 2D when the character changes direction, a simple scaleX *= -1 gets your character facing the right direction and you're on your way. If we need to rotate a character, setting orientation = π/2 is trivial. 2D rocks.

Click to get a better look at the shiftiness and twistiness.
However, this has its limitations. If we combine these transforms, things get messy. If we rotate and then flip, it's not the same as flipping and then rotating. Also when we flip, does it count as a 180 degree turn since we're about-face? And if we need to change direction again, we've really gotten ourselves in a mess: which way are we actually facing?

The problem is that we're not storing enough relevant information. Both of these cases look the same.

But they're not! This becomes quite obvious when we apply these same transformations to woolly, pixelly sheep.

That's where affine transformations come in. They can store all the data we need to render the sprites correctly. Conveniently, we can also send other vectors through these same transformations to handle other directional information like velocity. Linear Algebra is awesome like that. Essentially, an affine transformation takes a 2D plane and handles it in 3D space to put it back in 2D space in a transformed way. So our 180 rotation becomes a rotation around the z-axis, and more importantly our flip is represented as a rotation through 3D space around the y-axis.

By stacking these transforms, we can keep a record of what has happened to a given game entity and make sure we're rendering the entity correctly. In this method, each transform is represented by a 3x3 matrix as shown below.

As each transform occurs, we multiply it against the entity's current transform resulting in a new transform that completely describes its orientation. For example, if our woolly, pixelly sheep is flipped diagonally and then is later rotated 90 degrees, he's simply been horizontally flipped from his original orientation.

Our intent is to include these graphic enhancements in The Shifty, Twisty Forest alpha to make the visual transitions a bit more fluid. Check back in awhile... ...if you care (about shifty, twisty forests or woolly, pixelly sheep).