Sprites in uxn are 8 pixels square and stored either as 1- or 2-bit per pixel (1bpp/2bpp), for monochrome or 4-color sprites respectively. Usually the sprite data is stored after all of the main program's code, to ensure we don't run what should be raw hexadecimal data.
We can store each 8 pixel row as a byte, with each bit representing whether the pixel should be filled with the foreground (
1) or background (
0) color, similar to how PGM/PBM files in raytracing are represented.
To draw a character, we can represent it first in raw ASCII:
00111100 01111110 01011010 01111111 00011011 00111100 01011010 00011000
Converting each of these lines into hexadecimal bytes from top to bottom and placing them one after the other results in the following values:
3c 7e 5a 7f 1b 3c 5a 18. To store this as a sprite in uxn, we assign a label to it and put them in as raw values:
@character 3c7e 5a7f 1b3c 5a18
A 2bpp sprite contains four possible values using the two bits instead of two:
3. The way this is stored is not like a PGM file.
Say we have a square sprite:
00000001 03333311 03333211 03332211 03322211 03222211 01111111 11111111
Instead of neatly being able to convert each line into a hexadecimal value, we have to do create our 2bpp sprite as follows:
For each pixel, convert them into a 2-bit number.
(00) (00) (00) (00) (00) (00) (00) (01) (00) (11) (11) (11) (11) (11) (01) (01) etc.
Separate each of these pixels into high bits and low bits. They should end up looking like standard 1bpp sprites.
00000000 00000001 01111100 01111111 etc.
Convert each of these 1bpp sprites into hexadecimal like we did above, and then store them in memory with the low bit sprite first, followed by the high bit.
@square 017f 7b73 6343 7fff 007c 7c7c 7c7c 0000
Drawing To Screen
Then to draw it on the screen, we send the address found at our new label to the screen device by using the literal address rune (
;character .Screen/addr DEO2
The byte sent when telling the screen to actually draw the sprite will contain information on how to manipulate the sprite, as well as how to draw the information contained within the sprite.
The high nibble determines what mode we are in, whether we write to the background or foreground, and if we should flip our sprite on the x- or y-axis. The low nibble determines which of the four system colors are used to draw our sprite, with each table column representing which system color will be painted on which pixel value.
1bpp Low Nibble
0 will clear the tile at a given X/Y coordinate, and the various
none combinations will draw only the
1 pixels and leave what already exists at the
0 pixels alone.
2bpp Low Nibble
Sprites can be designed using uxn's nasu, which allows you to export a
chr file. Once you have a
chr file, you can use the Unix tool
hexdump to get the hex representation of the sprite you created.
hexdump -C file.chr
- Compudanza's uxn tutorial
Last modified: 202212070107