HackSpace – September 2019

(Jacob Rumans) #1
FORGE

with open(“/images/otters.bmp”, “rb”) as otters_
img:
otter_bitmap = displayio.
OnDiskBitmap(otters_img)
otter_tile = displayio.TileGrid(otter_
bitmap, pixel_shader=displayio.
ColorConverter(),width=1, height=1, tile_
width=96, tile_height=96)
group.append(otter_tile)

This opens the otters bitmap and uses the file
object to create a bitmap object. The TileGrid object
takes a few more parameters:


otter_bitmap is the bitmap that the grid is
taken from.
pixel_shader: Bitmaps contain a grid of colours; as
we’ll see later, these aren’t necessarily actual RGB
colours, so we need a way of converting between
the bitmap and the display colour. This is the
pixel_shader, and in this case we can use the
built-in one.
width and height define how many tiles will be
displayed in the TileGrid when it’s on the screen.
As we only want one of the otter images on a
screen at any one time, this is ‘ 1 ’ in both cases.
tile_width and tile_height are the size of each
tile in the source bitmap.


At this point, we’ve got all our images loaded into
memory, and sliced up, but we haven’t actually put
any of them on the screen. We do that in the while
loop, particularly in these three lines:


otter_tile[0] = image_num + 8
otter_tile.x = counter
display.show(group)

The first line is probably the oddest. We’ve got our
TileGrid called otter_tile that only displays one tile
(at index ‘ 0 ’), but contains 16 source tiles from our
bitmap. We have to decide which of these source
tiles to put on the screen. This is in a for loop that
iterates between the numbers 0–3, and we want the
displayed image to rotate between images 8–11. We
also have the variable counter that we increment and
decrement to move the x position of the TileGrid
along the screen. Finally, we have to display the
group in order to make our changes visible.
If you upload this code, you should see an otter
running backwards and forwards across your screen.
However, it will be in a white square on a black
background. Otters don’t run in white squares, so
the next step is to get ours running joyfully across a
natural background.

ENTERING THE FOREST
Our source image has a transparent background, but
this gets lost when we convert it to a bitmap image.
We need a way of importing our image which
preserves this. The alternative way of bringing
images into displayio is by setting the data points in
the bitmap directly and creating a palette.
Each pixel in a bitmap is stored as a single
number. The palette then links these individual
numbers to an actual RGB value. As such, it uses
far less memory because there’s only one number
per pixel rather than three (one for each RGB value).
We need to process our image in the right format.
It’s a bit CPU-intensive to do this on the
CircuitPython device, so we’ll do it on our main
computer using Python. You’ll need Python 3 with
NumPy and Python Imaging Library (PIL) installed –
we recommend using Anaconda, but you can also

Above
OpenGameArt is
a fantastic resource
for graphics for
embedding in your
projects (whether
game-related or not)

Left
Our lo-res otter
gives us a good
hit of nostalgia for
16-bit consoles
Free download pdf