A guide on procedural sprite animation.

Started by
-1 comments, last by Night Gleam Studio 7 years, 10 months ago

I’d like to share a tale of how I made a procedural animation set for the main character of my game. I’m a programmer and possess no artistic ability whatsoever, so the task seemed daunting at first. But after a bit of experimenting I’ve managed to turn this

  • into
  • this. Since I’ve been fairly satisfied with the result and there’s not much information on the topic, I’ve decided to write a small guide on how to achieve a similar effect in your game.

    Prerequisites.

    In order to follow the steps of this guide, basic knowledge of the image rendering mechanism is required. Basically, if phrases like “mesh” or “vertex buffer” don’t scare you – you are good to go =).

    Also for proper implementation of this technique, the engine you use must be advanced enough to support direct manipulation of vertex and texture coordinates buffers.

    Even if some of those things aren’t true, the last chapter gives information on a high level API that you can use to achieve the same result – might want to look into that!

    Overview.

    The technique is called Free-Form Deformation. When you create a sprite, your renderer sees it as a set of 4 points and a texture that is stretched over them. We can apply linear transformations to the points – that allows us to move, rotate and skew the sprite. Not enough for complex animations! We need to step up our approach and:

    • Create a proper mesh – a set of several 2D vertices that cover our image

    • Find an appropriate texture coordinate for each vertex.
    • During an update cycle, apply a chosen transformation to a subset of the vertices (without moving the texture coordinates).
    • Upload the changes to the renderer and enjoy the results.

    Step 1: Crafting a mesh.

    The least complicated way of creating our mesh is to do it manually. Literally all you need to do is to open the image in Paint and write down the pixel coordinates of the points that you want to turn into vertices. When choosing the points you have to keep the desired animation in mind. For my task I needed separate animations for eyes, ears and fur. The eyes were animated with a separate sprite so no points were created for them. The ears are pretty straightforward: a simple set of points covered and separated their shapes.

    Here cyan dots denote a set of immobile points that serve as a base of ear rotation and white dots constitute the form of ears that is going to rotate around the base. The marked white dot is actually 2 dots at the same place, one for each ear.

    For the fur I needed 3 layers of points. The inner red layer doesn’t move and serves as a static base. The dynamic yellow layer consists of moving points at the edges of the fur. It’s important not to have too many of these points so that they don’t create ugly intersections during their movement. Finally, the green layer is not strictly necessary for the movement – it merely contains the outer layer of the sprite.

    After choosing the points we need to properly order them to form vertices of triangles. The exact method of ordering depends on your constraints. If you must have performance in mind, you might want to weave the points into a triangle strip. The easier way would be to just state the triangles explicitly. In any case the end result should look something like this.

    Step 2: Drawing the sprite.

    In order to display the resulting set of points, we need to create two arrays from it: the vertex array that contains the position information and the texture coordinate array that associate a point in the image with each vertex. Fortunately, in a 2D case our set of points can be used for both!

    The actual way of creating the required structures depends a lot on the exact implementation you use. Here’s a very general algorithm:

    • Create an array of 2D vectors containing the points you chose in pixel coordinates.

    • Convert the vectors in the array into model space to receive the vertex buffer.

    • Again, take the original array and convert its vectors into texture space to receive the texture coordinates buffer.

    • Use your implementation to combine the two buffers into a mesh and draw the result.


    Step 3: Animating vertices.

    The amount of stuff you can do with the resulting mesh is enormous: starting from simple linear movements and ending in emulating small rotations in 3D space. The end result is only bound by your imagination (and math knowledge). In comparison with what could be done, my own animations are relatively simple.

    For fur movements I used a simple linear oscillation formula to move the yellow vertices in time:

    x(t) = x0 + Ax * cos (Px * t + Fx) ;

    y(t) = y0 + Ay * sin (Py * t + Fy) ;

    where x,y – current vertex position, x0 and y0– initial vertex position from the mesh, Ax and Ay – oscillation amplitudes, Px and Py – oscillation periods, Fx and Fy – oscillation initial phases.

    Amplitudes, periods and initial phases were randomly generated individually for each vertex before the update start.

    The ear movement is a bit more complicated. First, for every vertex of the ear we determine the two pivot points on top of the head: (x1, y1) and (x2,y2).

    Second, we need to find a unit vector parallel to a given pair of pivot points.

    Finally, we can determine the position of the ear vertex as a rotation around the normal vector:

    d = |(x0 - x1) * ny - (y0 - y1) *nx |

    x = x0 +d * ( cos (a) + ny ) ;

    y = y0 + d * ( sin (a) - nx ) ;

    where x and y – current vertex position, x0 and y0 – initial position from the mesh, d – distance from the base to the current point, a – angle of the ear.

    By modifying the angle with time we get the ear movement that you can see in the final result

    Alternatives.

    The biggest drawback of the manual approach is the sheer amount of work and calculations you have to do just to convert and display the image. In my case I only had to create a single sprite, so the whole procedure was bearable. But if you are going to create animations for several images, you might want to look into ways to automate the process.

    I’m aware of a single program that is capable of doing what we need – it’s called Spine. Unfortunately, it’s quite costly and the trial is severely gimped, so I don’t have any practical experience to share. On the plus side, the program seems extremely powerful, some stuff people do with it is absolutely mesmerizing.

    If you’d like to see and play with the end result, I have recently released the game on Android, here’s a market link.

    This topic is closed to new replies.

    Advertisement