Table of Contents

Importing and Drawing Sprites

The SDK makes it easy to bring images into your game after you've exported them, particularly from Aseprite. This page will go into a bit more detail on how to incorporate the image files into your project and then how to load and draw them in your code.

Warning: when exporting BMP images from GIMP, make sure to check “Do not write color space information” in the Compatibility options.

Import

The 2MB Cartridges have 128 banks of 16KB each, and the SDK scripts are designed to assign image assets to these banks based on the contents of the assets folder. Each subfolder of assets comprises one of the cartridge banks. Files dropped directly into the assets folder are ignored by the import scripts.

After adding files to folders inside assets, run

make import

For example, in the games/tanks branch of the SDK there are three assets folders: “font”, “gfx”, and “music”. For these folders the import script outputs

[ 'bios8.bmp' ]
[
  'countdown.bmp',
  'countdown.json',
  'exlposion.bmp',
  'exlposion.json',
  'green_tank.bmp',
  'green_tank.json',
  'ground.bmp',
  'title.bmp'
]
[ 'tank_intro.mid' ]

In addition these files will be created in src/gen/assets with names based on the subfolders.

Drawing

Drawing sprites on the GameTank is a two-step process. Before a sprite can be drawn it must be loaded into Sprite RAM. Once it is loaded into one of the sprite banks, it can be drawn either by specifying a rectangular portion of a sprite bank, or by an index into frame data exported by Aseprite.

The function allocate_sprite takes a pointer to a sprite load list. References to sprite load lists can be found in generated header files, eg. src/gen/gfx if you created a “gfx” folder, ASSET__gfx__mysprite_bmp_load_list.

allocate_sprite returns a SpriteSlot handle to pass to drawing functions.

//Near top of file
#include "../gen/assets/gfx.h"
...
//During your init process
player_sprite = allocate_sprite(&ASSET__gfx__mysprite_bmp_load_list);

Drawing by rectangle

Once your graphics are loaded into a sprite bank, you can draw them with queue_draw_sprite

queue_draw_sprite(X,Y,W,H,GX,GY,SPRITESLOT);

X and Y indicate coordinates on the screen. W and H are the width and height. GX and GY are the coordinates in the source image which you'd use to pick a tile or frame of animation from a sheet. SPRITESLOT is the SpriteSlot value returned by allocate_sprite when you loaded the image data.

queue_draw_sprite is part of the queued drawing API, so you can consecutively call other queued drawing functions and they'll be processed one at a time, in order.

When there's no more drawing or computation to do for the current frame, use await_draw_queue(), await_vsync(1), and flip_pages() to present your frame to the TV!

Drawing by frame number

If you've exported a packed sprite sheet alongside JSON frame data, you can use queue_draw_sprite_frame. This function can not only select the rectangle in your sprite sheet from a frame number, it also centers your sprite on the canvas center used in Aseprite and had a parameter for flipping horizontally and/or vertically.

void queue_draw_sprite_frame(
    SpriteSlot sprite,
    char x, char y,
    char frame,
    char flip);

Before calling any version of _draw_sprite_frame you need to associate the JSON data to the SpriteSlot with set_sprite_frametable. The JSON data can be referred to with a generated convenience macro that provides both the data pointer and bank number arguments.

//init
player_sprite = allocate_sprite(&ASSET__gfx__TemplateCharacter_bmp_load_list);
set_sprite_frametable(player_sprite, &ASSET__gfx__TemplateCharacter_json);
...
//draw
queue_draw_sprite_frame(player_sprite, player_x, player_y, player_frame_start + player_frame, 0);