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.
maptileasks 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.