Tutorial 3 · The Trick Tiles
Bruce Lee, Jet Set Willy, Manic Miner — what makes them feel like C64 games isn't the graphics, it's the tiles that do things. Belts that drag you toward the spikes. Floors that crumble the moment you stand on them. Ladders to climb between screens. Here they all are:
You spawn on the orange crumbling shelf — feel it give way. Then explore: the ladder, the two conveyor belts, the spike ledge.
The big idea: behaviour is a flag
You already met SOLID, PLATFORM and HAZARD in the first two tutorials. The trick tiles are just three more flags, combined with | when a tile needs to be several things at once:
import {
TileMap, SOLID, HAZARD, CONVEYOR, CRUMBLE, LADDER,
} from '../../engine/tilemap.js';
The player controller already knows what every flag means. You never write the belt logic or the climbing logic — you just label the tile.
Conveyor belts
A belt is SOLID (you stand on it) plus CONVEYOR (it carries you), with a direction and a speed:
'>': { flags: SOLID | CONVEYOR, kind: 'conveyor', dir: 1, beltSpeed: 0.6, base: C64.GREY, top: C64.LIGHT_GREY },
'<': { flags: SOLID | CONVEYOR, kind: 'conveyor', dir: -1, beltSpeed: 0.6, base: C64.GREY, top: C64.LIGHT_GREY },
dir: 1 drags you right, -1 drags you left. The belt pushes you through the same collision path as walking, so it can pin you against a wall but never shove you through one. Belt speed 0.6 versus a walk speed of 1.4 means you can fight the belt and win — that tension is the whole point (Manic Miner's belts worked exactly this way). The chevrons animate in the belt's direction so you can read it at a glance.
Crumbling floors
SOLID plus CRUMBLE, with an hp measured in ticks of standing-on-it:
'%': { flags: SOLID | CRUMBLE, kind: 'crumble', hp: 26, base: C64.ORANGE, top: C64.YELLOW },
Stand on it and it wears down — the engine draws cracks in three stages so you can see the betrayal coming — then after ~26 ticks (about half a second) it gives way. The catch that makes it fair: crumble state lives on the TileMap instance, so rebuilding the room grows the floor back. That's why the example rebuilds its map on death:
const rebuild = () => { map = new TileMap({ rows, legend, tileSize: 8 }); player.map = map; };
player.onDeath = () => { rebuild(); player.respawn(); };
player.onDeath is a hook — set it and the engine calls it instead of the default respawn. A full game uses this to reset a whole room.
Ladders
Just LADDER — no SOLID, because you pass through it:
'H': { flags: LADDER, kind: 'ladder', base: C64.LIGHT_GREY, top: C64.WHITE },
Press up or down while overlapping a ladder and the player switches into climb mode: gravity off, up/down to move, jump to leap off, and stepping onto solid ground exits climb mode automatically. A ladder poking through a hole in the floor is the entire vertical-movement mechanic — no special case needed. The example reads player.climbing just to label the HUD:
hud.textContent = `${player.climbing ? 'CLIMBING' : player.onGround ? 'GROUND' : 'AIR'}`;
You've now touched every system
Loop, video, input, camera, player, tiles, entities, and the special tiles — that's the complete engine in one room. The best way to learn from here is to break things: change a belt's speed, drop a gravity value, give the guardian mode: 'edge' and watch it turn at ledges.
Then take the next step: the World system strings rooms together into a flick-screen map — that's how The Manor works.