raylib-animation-system
Summary
There is no animation system in raylib, so let's write one from scratch!
The basic idea of a 2D animation system is to utilize a texture atlas. A sub-texture size if specified (e.g. 16x16), which divides the texture up into smaller pieces. These pieces are indexed from left to right, top to bottom starting from 0. This makes finding x
texture as easy as a math equation:
texture_size = (16, 16)
atlas_texture_width = 10 # number of textures per row
target_index = 13
target_x = (target_index % atlas_texture_width) * texture_size[0]
target_y = (target_index / atlas_texture_width) * texture_size[1]
Structure
Start with defining an animation:
typedef struct Animation {
uint32_t cur; // the current frame index
uint32_t first; // index of the first frame
uint32_t last; // index of the last frame
uint32_t step; // how many to move over per frame
float speed; // how long each frame lasts
float duration_left; // how much longer a frame lasts
Direction direction; // increasing or decreasing
AnimationType anim_type; // the type of animation (repeating, oneshot, etc.)
} Animation;
Now we need to define what a Direction
is and what an AnimationType
is:
typedef enum Direction {
FORWARD = 1,
BACKWARD = -1
} Direction;
typedef enum AnimationType {
REPEATING,
ONESHOT
} AnimationType;
A Direction
is simply a flag that we multipy our step by to either go forwards of backwards. The AnimationType
is an identifier to tell the system how to use this animation.
With the data modelled out, it's time to make it useful. In this system, there are only two functions that need to be implemented: update
and frame
. Below is their signature.
Note that I'm writing this in a C-style way for compatibility purposes. Feel free to rewrite this as methods of a class if you wish.
// update the animation
void animation_update(Animation *self);
// fetch the current animation frame
Rectangle animation_frame(Animation *self, uint32_t num_textures_per_row, uint32_t tilesize);
First, the easy one:
Rectangle animation_frame(Animation *self, uint32_t num_textures_per_row,
uint32_t tilesize) {
// 1.
uint32_t x = (self->cur % num_textures_per_row) * tilesize;
uint32_t y = (self->cur / num_textures_per_row) * tilesize;
return (Rectangle){
.x = (float)x,
.y = (float)y,
.width = (float)tilesize,
.height = (float)tilesize,
};
}
- The relative
x
andy
are the topleft position of the tile on the texture atlas. For example, index9
on an atlas with dimensions4x4
would have an(x, y)
of(0, 2)
.
TODO: finish this!!
Texture Atlas
A texture atlas is an image containing smaller images. Also known as a sprite sheet. Mostly used for effecient texture rendering and animations.