Posts
Search
Contact
Cookies
About
RSS

Sprite Sheets with RayLib

Added 19 Mar 2020, 10:45 p.m. edited 18 Jun 2023, 5:42 p.m.

RayLib has a decent set of functions for rendering textures and as such it makes the task of rendering an animated sprite from a sprite sheet fairly straight forward, however people are at all sorts of levels so I think its still worth while going over one possible solution.


As a quick side tip, there are web sites out there that will allow you to turn GIF's into sprite sheets! (allows such tasteless monstrosities as the above!)

I made a structure for a Sprite which contains all the information needed to render an animation from a sprite sheet.

typedef struct Sprite {
     Texture2D texture;
     Vector2 frameSize;
     int maxFrame;
     int framesWide;
     Vector2 origin;
     int frame;
 } Sprite;

The way frame size is handled means we are limited to the same size for each frame, but that small limitation makes things much easier… the framesWide member refers to the number of columns there are in a sprite frame, for example this animation of a flower opening is arranged in four columns.

With the frame size and number of columns we have everything we need to render from a sprite sheet.

Sprite sprite = { 0 }; 
sprite.texture = LoadTexture("data/dance-dog.png");
sprite.frameSize = (Vector2){ 128, 256 };
sprite.maxFrame = 13;
sprite.framesWide = 4;
sprite.origin = (Vector2){ 64, 128 };

As you can see filling in the needed information is straight forward.

Now we are ready to render it!

void drawSprite(Sprite* sprite, float x, float y, float ang, float scale, Color c) 
{
    float ox, oy;
    ox = (sprite->frame % sprite->framesWide) * sprite->frameSize.x;
    oy = (int)(sprite->frame / sprite->framesWide) * sprite->frameSize.y;
    DrawTexturePro(sprite->texture, (Rectangle){ox, oy, sprite->frameSize.x,sprite->frameSize.y}, 
                                    (Rectangle){x, y, sprite->frameSize.x * scale, sprite->frameSize.y * scale}, 
                                    (Vector2){sprite->origin.x * scale, sprite->origin.y * scale}, ang, c);

}

By taking the modulo of the number of columns in the sprite sheet and multiplying it by the frame width, we have how far across the sprite sheet that frame is. In a similar way dividing the current frame by with number of columns and casting it to an integer before multiplying it by the frame height, gives us how far down the sprite sheet that frame is. I threw in scaling as it was basically a no brainer, notice that the destination size as well as the origin are scaled.

...and it really is as simple as that!

Enjoy!