Drawing Sprites

Drawing sprites is the primary task in a game’s visual presentation.

In cerlib, the cer::drawSprite() function is responsible for this.

There are two versions of drawSprite() available:

1) void drawSprite(const Image& image,
                   Vector2 position,
                   Color color = white);
2) void drawSprite(const Sprite& sprite);

Version 1 is merely a shortcut version for version 2; they both perform the same action. We will focus on version 2, which takes a single sprite parameter.


Let’s have a look at the Sprite structure:

struct Sprite {
    Image image;
    Rectangle dstRect;
    Option<Rectangle> srcRect;
    Color color = white;
    Radians rotation;
    Vector2 origin;
    Vector2 scale = {1.0f, 1.0f};
    SpriteFlip flip = SpriteFlip::None;
};

Using a sprite, you are able to specify every detail of how it’s drawn. All coordinates and sizes of a sprite are expressed in pixels.

For example:

const auto sprite = Sprite {
    .image   = myImage,
    .dstRect = { 200, 200, 128, 128 }, // Draw at {200, 200} with size {128, 128}
    .color   = red,
    .flip    = SpriteFlip::Horizontally,
};

cer::drawSprite(sprite);

Which version of drawSprite you choose is up to your convenience.

Destination and source

As you have seen, a sprite has two special properties called dstRect and srcRect. The destination specifies the sprite’s area within the canvas (window).

A destination of { 200, 250, 128, 64 } means that the sprite is drawn with its top-left corner at position { 200, 250 }, of size { 128, 64 }.

This means that its right border will be at X-coordinate 200 + 128 = 328, while its bottom border will be at Y-coordinate 250 + 64 = 314.

The destination rectangle is often used to stretch or shrink (scale) a sprite, disregarding its image size. For example, when you draw a sprite using cer::drawSprite(image, {200, 200}), the function calculates a destination rectangle for you, which ultimately is { pos.x, pos.y, imageWidth, imageHeight }.

The source rectangle on the other hand refers to coordinates within the sprite’s image. To illustrate this, let’s take a look at the following image:

The red rectangle represents the source rectangle.

In this case, it would be { 75, 75, 150, 150 }.

The source rectangle is often used to implement sprite sheets and sprite animations. This allows multiple images to be stored in a single large image (atlas) and to still be drawn independently.

Such a technique is necessary when your game has hundreds or thousands of sprites in order to minimize texture changes and draw operations in the internal graphics API, which are an expensive operation.

One example is cerlib’s text rendering, whcih makes use of source rectangles. Since all characters are stored in a large image, each character in a string is drawn as a sprite that references its region in that image.