Skip to content

Sprites

Philip Howard edited this page Sep 21, 2020 · 2 revisions

Sprite

32blit supports 128x128 pixel sprite sheets containing 64 8x8 sprites. The engine is optimised to work with these particular sizes but larger assets can be represented using multiple individual sprites.

Since 32blit has no hardware sprite engine there is no hard limit to the number of sprites that can be displayed at the same time. However excessive sprite use will affect the framerate.

Loading Sprites

Sprites are typically expected to be loaded via the asset pipeline using the 32blit tool to convert a 128x128 pixel PNG image with 255 or fewer colours into a packed, palette-based asset.

Using The Asset Pipeline

Given the file assets/sprites.png the following assets.yaml will convert it into an assets.cpp and assets.hpp file containing a uint8_t array asset_sprites that contains the packed data:

assets.cpp:
  assets/sprites.png:
    name: asset_sprites

The CMakeLists.txt file must then register assets.yml as part of the build:

blit_assets_yaml(application-name assets.yml)

And the resulting asset.hpp should be included into the application:

#include "assets.hpp"

This data can be unpacked into the screen spritesheet ready for use:

void init() {
  screen.sprites = SpriteSheet::load(asset_sprites);
}

Going It Alone

screen.sprites is expected to be a SpriteSheet which derives from Surface and adds some helper functions for loading packed data and determining sprite bounds.

A SpriteSheet can be declared as:

SpriteSheet *more_sprites;

And then loaded at runtime with packaged data:

more_sprites = SpriteSheet::load(packed_data);

Since more_sprites is effectively just a Surface it can be copied to the screen with blit, which accepts a Rect() describing the source region pixels and a Point() describing the destination location in pixels.

For example, the following are equivalent:

screen.blit(more_sprites, Rect(0, 0, 8, 8), Point(0, 0));
screen.sprites = more_sprites;
screen.sprite(0, Point(0, 0))

However, blit offers more flexibility† and can operate on regions of the SpriteSheet that are not aligned to the 8x8 grid.

  • † at the expense of performance?

Drawing Sprites

By Index

A 128x128 spritesheet contains 64 individual 8x8 sprite tiles numbered 0 to 63 following across left to right.

The top left tile is thus tile 0 and the top right is tile 7. Immediately below on the next row the left and right tiles are 8 and 15 respectively, and so on.

A single sprite can be drawn to the drawn via its index at a given Point():

screen.sprite(1, Point(30, 30));

By Location

Sprites can be addressed by their column and row location, ranging from 0 to 15 in both cases.

A sprite with index 1 is also addressable as row 0, column 1. A Point() is used to specify this location, in this case it would be Point(0, 1).

A single sprite can be drawn via its location at a given Point():

screen.sprite(Point(0, 1), Point(30, 30));

In Groups

When addressing sprites by their row/column location a Rect() can be supplied in lieu of a Point(), giving both the row and column of the first sprite, and a width/height value to specify how many sprites wide and high the draw should include.

The first four sprites in the top row of the spritesheet can be drawn like so:

screen.sprite(Rect(0, 0, 4, 0), Point(0, 0));

The four top left most sprites in a grid of 2x2 can be drawn like so:

screen.sprite(Rect(0, 0, 2, 2), Point(0, 0));

Using A TileMap

Large groups of sprites, such as those used to construct a level, are easier to manage using a TileMap - effectively a 2d array of tile IDs and additional attribute flags. For more information on drawing with TileMaps see: TODO: TileMap page and link here

Clone this wiki locally