PocketSprite TileGFX tile renderer

The PocketSprite SDK comes with a powerful tile rendered. This tile rendered is capable of rapidly rendering maps of 8x8 graphics tiles to the screen, including effects like transparency and fading. The SDK has integration with the files generated by Tiled, a powerful and open-source tilemap editor, allowing the tilemaps generated in that program to be embedded in and rendered from PocketSprite applications.

Creating tiles and tilemaps

Essentially, tiles are small (in this case, 8x8 pixels) images or parts of bigger images. These tiles can be placed next to each other on a bigger canvas, not unlike floor tiles can be placed on a floor in order to fill the entire floor. The bigger canvas is called a ‘tile map’ and can be however big you want it to be; for instance, an entire level in your platformer game.

The advantage of this approach is that the tile map uses a much smaller amount of memory when compared to having the entire map as an image: because tiles can be re-used (for example, the blue of the sky can be the same tile repeated over and over again) and shared between maps, a tile map can use a much smaller amount of memory than the graphics it represents. Using tiles also has some other advantages: for instance, tiles can be animated, leading to an easy way to add individual elements of animation to a tilemap.

Tilegfx, the PocketSprite tile renderer, is optimized to work with maps generated by Tiled and the SDK contains a conversion program to convert its native .tsx/.tmx files directly into .c/.h files which can then be included in a PocketSprite process.

In order to create a tiled tile map that works with tilegfx:

  • First, create a .png containing all the tiles in an 8x8 pixel grid in a program of your choosing. Be sure to save the png as true color (RGB), not indexed. You can use one color (#FF00FF is regularily used for this) to indicate a transparent pixel.
  • Open tiled, create a new tileset (File -> New -> New tileset). Select the png created earlier. It’s important to select a tile height and width of 8px by 8px here. Also set the transparency color here, if any.
  • If so desired, modify the tile set (add animations, …)
  • Create the tilemap (File -> New -> New map). Select Orthogonal for orientation, CSV for tile layer format, Right Down for rendering order and set the tile size to 8px x 8px. You can freely choose the map size here.
  • Create your map. Make sure the layer you’re working in has a sane name, as that will be part of the name of the resulting tilegfx_map_t struct containing the layer data.
  • Save the map and tileset somewhere in your project

The conversion from Tiled format to C file can now be automated. In a component.mk file in your PocketSprite project, add a line similar to this:

$(eval $(call ConvertTiles,level1.tmx,levelgfx))

This will convert a tilemap file called level1.tmx and its associated tileset to a file called levelgfx.c as soon as you build the project. The levelgfx.c is automatically compiled and linked with the project. A file called levelgfx.h is also created; you can use this to refer to the tilemap data from other C source files.

Note: because of quirks of the build system, this method breaks the automatic detection of other C files. This means you need to specify them manually. For instance, if the component also contains an app_main.c and a enemy.c file, a minimal component.mk would look like this:

$(eval $(call ConvertTiles,level1.tmx,levelgfx))
COMPONENT_OBJS += app_main.o enemy.o

Rendering tile maps

With tile maps defined, you can now render them using the API defined down below. The way tilegfx works is that it only has one render target, namely the screen buffer. The screen buffer can either be the same height and width of the OLED screen of the PocketSprite, or it can be twice as large and scaled down when sent to the OLED screen. The second option uses more memory, but by using subpixel scaling it can actually make the displayed graphics look like it has a higher resolution than the screen natively has.

It is possible to render multiple layers over eachother: if a tile map has transparency defined, the transparent regions will allow the earlier rendered graphics to shine through.

Functions

int tilegfx_init(int double_res, int hz)

Initialize tilegfx system.

Allocates the OLED framebuffer and the infrastructure for the virtual VBlank.

Return
True if succesful, false if out of memory.
Parameters
  • double_res: Set to 0 to get a framebuffer in the native (80x64) resolution; set to 1 to get a 160x128 framebuffer that is then subpixel-aware scaled to the OLED.
  • hz: Set the ‘refresh rate’, as in the tilegfx_flush call is throttled to a maximum of this amount of calls per second.

void tilegfx_flush()

Render the OLED framebuffer to the actual OLED display.

This shows the result of all tilegfx calls on the PocketSprite display. This call may block for a while in order for it to never be called at more than ‘refresh rate’ passed to tilegfx_init().

void tilegfx_deinit()

De-initialize tilegfx.

This frees the OLED-buffer and all other resources allocated when initializing tilegfx.

void tilegfx_tile_map_render(const tilegfx_map_t *tiles, int offx, int offy, const tilegfx_rect_t *dest)

Render a tilemap to screen.

This renders the content of a tilemap to the OLED framebuffer. It takes care of transparency and clips the regions that fall outside of the destination rectangle. The tilemap is rendered in a repeating way, so it ‘wraps around’ when displaying bits outside its actual height and/or width.

Parameters
  • tiles: The tilemap to render
  • offx: X-offset in the tilemap. The tilemap is started with (offx, offy) in the top right corner if the destionation rectangle.
  • offy: Y-offset in the tilemap.
  • dest: Rectangle, in the coordinates of the OLED framebuffer, to limit rendering to. If this parameter is NULL, the tilemap is rendered to the entire framebuffer.

void tilegfx_fade(uint8_t r, uint8_t g, uint8_t b, uint8_t pct)

‘Fade’ the framebuffer to a certain color.

This effectively sets every pixel in the OLED framebuffer to a color that is (pct/255)’th the original color that was there, 1-(pct/255)’th the color indicated by the RGB values. A pct value of 256 does not affect the OLED framebuffer, a pct value of 0 clears it entirely to the color given in r,g,b.

Parameters
  • r: Red component of fade color
  • g: Green component of fade color
  • b: Blue component of fade color
  • pct: Fade amount (0-256)

tilegfx_map_t *tilegfx_create_tilemap(int w, int h, const tilegfx_tileset_t *tiles)

Create an empty tilemap in RAM.

This can be used to generate a tilemap that is in RAM and this modifiable from the code

Return
The map (with all tiles set to 0xffff/transparent), or NULL if out of memory
Parameters
  • w: Width, in tiles, of the map
  • h: Height, in tiles, of the map
  • tiles: Tileset the map will use

tilegfx_map_t *tilegfx_dup_tilemap(const tilegfx_map_t *orig)

Create an editable copy of a tilemap.

Use this to duplicate a tilemap located into flash into one located into RAM.

Return
Duplicated tilemap, or NULL if out of memory
Parameters
  • orig: Tilemap to duplicate

void tilegfx_destroy_tilemap(tilegfx_map_t *map)

Free a tilemap created with tilegfx_create_tilemap or tilegfx_dup_tilemap.

Parameters
  • map: Map to free

static void tilegfx_set_tile(tilegfx_map_t *map, int x, int y, uint16_t tile)

Set tile position in RAM-allocated map to the specific tile in its associated tileset.

Parameters
  • map: Tilemap to modify
  • x: X-position of tile to change
  • y: Y-position of tile to change
  • tile: Tile index to change to (or 0xffff for completely transparent)

static uint16_t tilegfx_get_tile(const tilegfx_map_t *map, int x, int y)

Get tile in specified tile position of tilemap.

Return
tile Tile index in tileset (or 0xffff for completely transparent)
Parameters
  • map: Tilemap to read
  • x: X-position of tile
  • y: Y-position of tile

uint16_t *tilegfx_get_fb()

Get internal framebuffer.

This returns a pointer to the internal framebuffer memory where tilegfx renders everything. You can use this to manually poke pixels into memory, or to get access to the raw pixels after some tiles have been rendered. Note that in double_res mode, after rendering tilesets this framebuffer is 160x128 pixels in size, but after calling tilegfx_flush the contents will be resized to 80x64!

Pixels here are in big-endian RGB565 format (same as what’s sent to the OLED).

Structures

struct tilegfx_anim_frame_t

Structure describing one frame of animation.

Public Members

uint16_t delay_ms

Delay for one frame. On the 0th frame of a seq, this indicates total duration.

uint16_t tile

Tile index for frame. 0xffff on 0th frame of a seq.

struct tilegfx_tileset_t

Structure describing a set of tiles, usable in a tilemap.

Public Members

int trans_col

transparent color, or -1 if none

const uint16_t *anim_offsets

Array of offsets into the animation frames array. Indexed by tile index. If a tile is animated, it will have an offset number in this array at its index. That offset is 0xffff if no animation.

const uint16_t tile[]

Raw tile data. Each tile is 64 16-bit words worth of graphics data.

struct tilegfx_map_t

Structure describing a tilemap.

Public Members

int h

Height of the tilemap, in tiles

int w

Width of the tilemap, in tiles

const tilegfx_tileset_t *gfx

Pointer to the tileset used in the map

const uint16_t tiles[]

Array of the tiles in the map. Values can be 0xffff for no tile.

struct tilegfx_rect_t

Structure describing a rectangle.

Public Members

int x

Position of left side of rectangle

int y

Position of top of rectangle

int w

Width of rectangle

int h

Height of rectangle