Make sure you have the latest CircuitPython firmware loaded for your board to use displayio. You can download it from the link below.

This example builds on the Sprite Sheet example to show a more sophisticated usage of TileGrid. We'll show how you can have more than one TileGrid and that a TileGrid can be more than just one tile.

The castle wall tiles used in this example were borrowed from this excellent tilesheet: dungeontileset-ii

A Sprite and Its Castle

Our first TileGrid will be another sprite - so a TileGrid with a single tile. This is the same as was done in the Sprite Sheet example. Our second TileGrid will be a little more interesting. It will have more than one tile and will be used to generate the walls and floor of a 2D castle for our sprite to live in.

The idea is to generate the walls and floors by reusing the same source tile over and over. For example, we can create something that looks like this:

You can kind of already see the grid like repetitive pattern. Let's put a reference grid over the top:

This grid is 6 tiles wide by 5 tiles high. You can see how the floor is just the same tile over and over. The walls can similarly be created by reusing the same source tile. So we just need a source bitmap that has each of these basic building pieces. It can come from the same bitmap we'll use for our sprite. Let's do that - here's our new sprite sheet we will work with:

Another super tiny BMP! Here's what it looks like more blown up:

There are a couple of characters we can use for our sprite at the top. But there's also the basic building blocks needed for our castle.

For this example, each item is 16 pixels by 16 pixels. So we'll end up carving up the sprite sheet like this:

As mentioned above, our castle is 6 tiles wide by 5 tiles high. So that will be the size of the TileGrid we'll create to generate the castle. Then, each tile in the castle TileGrid just needs to be set to the correct index from the source bitmap.

Here's what that would look like:

But keep in mind this is only one of the TileGrids we'll create. The other is our simple single tile TileGrid - the sprite. It comes from the same sprite sheet.

Think of it working like this:

And we can assign the single tile of sprite or any of the tiles of castle to any of the indices from sprite_sheet. The (x, y) notation for a couple of tiles in castle are shown as a helpful reminded of how they are accessed.

For example, to set the lower right corner located at (5, 4) of the castle to the "lower right corner" graphic found at index 11 in the sprite_sheet, do this:

Download: file
castle[5, 4] =  11

But of course we need to set all of the tiles. This just ends up being more lines of code.

Here's the full code:

Download: file
import board
import displayio
import adafruit_imageload

display = board.DISPLAY

# Load the sprite sheet (bitmap)
sprite_sheet, palette = adafruit_imageload.load("/castle_sprite_sheet.bmp",
                                                bitmap=displayio.Bitmap,
                                                palette=displayio.Palette)

# Create the sprite TileGrid
sprite = displayio.TileGrid(sprite_sheet, pixel_shader=palette,
                            width = 1,
                            height = 1,
                            tile_width = 16,
                            tile_height = 16,
                            default_tile = 0)

# Create the castle TileGrid
castle = displayio.TileGrid(sprite_sheet, pixel_shader=palette,
                            width = 6,
                            height = 5,
                            tile_width = 16,
                            tile_height = 16)

# Create a Group to hold the sprite and add it
sprite_group = displayio.Group()
sprite_group.append(sprite)

# Create a Group to hold the castle and add it
castle_group = displayio.Group(scale=3)
castle_group.append(castle)

# Create a Group to hold the sprite and castle
group = displayio.Group()

# Add the sprite and castle to the group
group.append(castle_group)
group.append(sprite_group)

# Castle tile assignments
# corners
castle[0, 0] = 3  # upper left
castle[5, 0] = 5  # upper right
castle[0, 4] = 9  # lower left
castle[5, 4] = 11 # lower right
# top / bottom walls
for x in range(1, 5):
    castle[x, 0] = 4  # top
    castle[x, 4] = 10 # bottom
# left/ right walls
for y in range(1, 4):
    castle[0, y] = 6 # left
    castle[5, y] = 8 # right
# floor
for x in range(1, 5):
    for y in range(1, 4):
        castle[x, y] = 7 # floor

# put the sprite somewhere in the castle
sprite.x = 110
sprite.y = 70

# Add the Group to the Display
display.show(group)

If you run that, you should end up with something like this:

Order Matters

Note the order in which the sprite_group and the castle_group were added to the main group that was finally shown on the display.

Download: file
group.append(castle_group)
group.append(sprite_group)

Think of it as building from the bottom up or outward from the display. Each new item will be shown above the previous items. Since we want our sprite to be seen above the castle, we add (append) it after we add the castle.

Using Different Scale

This example shows how you can mix different scales if you want. Since scale is used at the Group level and applies to everything in the Group, we created two separate Groups for the sprite and castle. That way we could set a different scale for the castle.

You don't have to do this. We could have just added the sprite and castle to the same Group. But this shows how there is flexibility in how you setup your collection of items that you send to the display.

Change The Sprite

Want Adabot to be in the castle instead of Blinka? All you need to do is change the source index for the sprite tile. There are two ways you could do this.

The first would be to use the default_tile parameter assignment when creating the TileGrid. In the code above, it was set to 0. If you wanted Adabot, you would change it to 1.

The second way would be to just set it after the TileGrid is created. That would look like this:

Download: file
sprite[0] = 1

Change Sprite Location

Want Blinka to be somewhere else in the castle? Simple, just change the x and y values here:

Download: file
sprite.x = 110
sprite.y = 70

Even more fun - write a loop with these changing inside the loop. Then Blinka will be moving around in the castle!

This guide was first published on Apr 30, 2019. It was last updated on Apr 30, 2019.
This page (Multiple TileGrids) was last updated on Oct 24, 2020.