Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Tile maps

A level is mostly the same few pictures over and over: floor, wall, grass, water. A tile map is a grid of numbers, one for each square of the level, and an image of tiles to draw them from. You change a number and I change the picture.

The tiles

The tiles are one image cut into squares, the same way a sprite sheet is. Here are three, sixteen pixels square, drawn side by side in a MEMORYBUFFER: grass, a wall and water.

SCREEN 320, 240
MEMORYBUFFER "tiles", 48, 16
    LINE (0, 0) -> (15, 15), 2 !! box fill
    LINE (16, 0) -> (31, 15), 8 !! box fill
    LINE (17, 1) -> (30, 7), 7 !! box
    LINE (32, 0) -> (47, 15), 1 !! box fill
END MEMORYBUFFER
PUTIMAGE (140, 100), "tiles" !! scale((2, 2))

The map

The grid is something your program keeps: a grid of whole numbers, rows of columns. A TILEMAP says which image the tiles come from, how big a tile is, how big the map is, and which grid it’s drawn from. CREATE MAP puts it on a layer.

SCREEN 320, 240
MEMORYBUFFER "tiles", 48, 16
    LINE (0, 0) -> (15, 15), 2 !! box fill
    LINE (16, 0) -> (31, 15), 8 !! box fill
    LINE (17, 1) -> (30, 7), 7 !! box
    LINE (32, 0) -> (47, 15), 1 !! box fill
END MEMORYBUFFER

// 15 rows of 20 tiles fill a 320 x 240 screen.
ground = (15, 20):INTEGER
FOR row = 0 ... 14
    FOR column = 0 ... 19
        ground(row, column) = 1
    NEXT
NEXT
FOR column = 0 ... 19
    ground(0, column) = 2
    ground(14, column) = 2
NEXT
FOR row = 5 ... 9
    FOR column = 7 ... 12
        ground(row, column) = 3
    NEXT
NEXT

TILEMAP "field"
    TILESET "tiles"
    TILESIZE 16
    SIZE 20, 15
    TILES 0 !! from(ground)
END TILEMAP
CREATE MAP "field" !! layer_to(0)
corner = maptile(0, 0)
pond = maptile(9, 7)
SET LAYER 1
PRINT "tile at the top left:", corner, " in the pond:", pond
tile at the top left: 1  in the pond: 2

A number in the grid picks a tile from the image, counting from 1: 1 is grass, 2 the wall, 3 the water, and 0 is no tile at all. maptile(x, y) asks which tile a square shows, counting the image’s tiles from 0 the way the frames of a sprite sheet are counted, so the wall is 1 there and the water 2.

Crash-tan’s Tip: I draw a map’s layer afresh every frame, so words printed on that layer are gone as soon as they’re there. Print on a layer above the map, the way this goes up to layer 1. maptile asks about the map on the layer you’re on, so ask it first, then go up.

Changing the map

The grid is still yours after the map is made. Change it, then UPDATE MAP shows the changes all at once. Click a square to drain the pond, or to flood the grass:

SCREEN 320, 240
MEMORYBUFFER "tiles", 48, 16
    LINE (0, 0) -> (15, 15), 2 !! box fill
    LINE (16, 0) -> (31, 15), 8 !! box fill
    LINE (17, 1) -> (30, 7), 7 !! box
    LINE (32, 0) -> (47, 15), 1 !! box fill
END MEMORYBUFFER

ground = (15, 20):INTEGER
FOR row = 0 ... 14
    FOR column = 0 ... 19
        ground(row, column) = 1
    NEXT
NEXT
TILEMAP "field"
    TILESET "tiles"
    TILESIZE 16
    SIZE 20, 15
    TILES 0 !! from(ground)
END TILEMAP
CREATE MAP "field" !! layer_to(0)

was_down = FALSE
DO
    IF COOLDOWN(1)
        IF mousedown AND NOT was_down
            column = int(mousex / 16)
            row = int(mousey / 16)
            IF ground(row, column) = 1 THEN ground(row, column) = 3 ELSE ground(row, column) = 1
            UPDATE MAP "field"
        END IF
        was_down = mousedown
    END IF
LOOP

Bigger than the screen

A map can be much bigger than the screen. SET SCROLL slides the layer it’s on, and the screen shows the part you’ve scrolled to.

SCREEN 320, 240
MEMORYBUFFER "tiles", 48, 16
    LINE (0, 0) -> (15, 15), 2 !! box fill
    LINE (16, 0) -> (31, 15), 8 !! box fill
    LINE (32, 0) -> (47, 15), 1 !! box fill
END MEMORYBUFFER

// Sixty tiles across: three screens wide.
ground = (15, 60):INTEGER
FOR row = 0 ... 14
    FOR column = 0 ... 59
        ground(row, column) = 1 + (int(column / 4) + int(row / 3)) MOD 3
    NEXT
NEXT
TILEMAP "long"
    TILESET "tiles"
    TILESIZE 16
    SIZE 60, 15
    TILES 0 !! from(ground)
END TILEMAP
CREATE MAP "long" !! layer_to(0)
SET LAYER 0

x = 0
DO
    IF COOLDOWN(1)
        IF keydown("Right") AND x < 640 THEN x = x + 4
        IF keydown("Left") AND x > 0 THEN x = x - 4
        SET SCROLL x, 0
    END IF
LOOP

Click the screen and use the arrow keys to scroll along.