Sonic Battle (GBA) Renderer Series - Sprites

Posted on September 29, 2019

Table of Contents

Welcome to the tenth article of the Sonic Battle (GBA) Renderer series.


Sprites are much simpler to render than walls or tilemaps. They have no affine transformations at all!

Sprite flip

Characters always look towards either the +X or the -X direction (even when walking along the Y axis). So depending on if the camera is more aligned with +Y or -Y the renderer needs to show a different face of the character by flipping the sprite along the X axis.

Flipping isn’t done with an affine matrix but instead by setting a sprite bit flag designed for this purpose.

Camera heading rotated 180 degrees, sprites are flipped on the horizontal axis

First or second floor

Sprites on the first floor need to be drawn between the bottom and top tilemaps while sprites on the second floor need to be drawn on top of the top tilemap and everything underneath it.

My first instinct was to mark a sprite as belonging to the second floor if its bottom point is above the top tilemap’s height:

bool isTop = sprite.pos.z >= lvl.tilemaps[TILEMAP_TOP].pos.z

But this approach has the unfortunate effect of massive overdraw when the sprite is off the ground but not above the top tilemap. Here’s what a character jumping could look like:

Feet on the ground.

The character's feet are still below the top tilemap's height -> it's considered first floor. There's a bit of overdraw.

The character is still below the top tilemap but the overdraw is massive.

The character's feet are now above the top tilemap's height -> it's considered second floor and drawn on top of the top tilemap.

First or second floor - with offset

Well this is more of a patch than a fix but if we decide the trigger point is not the feet but somewhat higher:

bool isTop = sprite.pos.z + lvl.floorSortOffset >= lvl.tilemaps[TILEMAP_TOP].pos.z

This is the maximum amount of overdraw we can get. Not bad compared to earlier.

The price we pay for this is that now there’s some overdraw when dropping down from second to first floor. We didn’t have this problem earlier:

Second floor level.

Dropping down. This is the max possible overdraw.

Considered first floor, no overdraw.

But it’s a good trade: at least now overdraw isn’t overwhelmingly bad in either up or down directions. Also during actual gameplay characters are never suspended in between floors so this artifact only lasts a few frames when it does happen.

First or second floor - in the original game

Here’s footage from the original renderer to corroborate the offset method.

Jumping up from first to second floor

Jumping down from second to first floor


Exactly the same as walls, sprites are sorted by the camera-space depth of their midpoints.

The extra factor I hadn’t mentioned in the wall article is that for the first floor only (since there’s no walls on the second floor) walls and sprites need to be sorted in the same collection.

The next article discusses drop shadows (those black ovals under the characters).