Building Worlds
What you'll learn:
- Use nested loops to generate maps, borders, and decorative patterns.
- Layer screen and colour memory writes cleanly inside loops.
- Parameterise generators (size, offsets, tile codes) so worlds adapt.
Lesson 14 – Building Worlds
You’ve got arrays, logic, and data; now you need whole rooms. Nested loops paint tiles row by row, column by column—exactly how the VIC-II expects you to think.
[📷 suggested: screenshot of a patterned dungeon room generated by loops]
The One-Minute Tour
- Outer loop handles rows, inner loop handles columns.
- Calculated screen address =
SCREEN + ROW*40 + COL
. - Write character and colour together to keep visuals coherent.
- Parameterize size and offsets so the same code can draw multiple rooms.
Template: Drawing a Room
NEW
10 PRINT CHR$(147)
20 SCREEN=1024 : COLOR=55296
30 WIDTH=18 : HEIGHT=12
40 OFFSETX=10 : OFFSETY=6
50 FOR R=0 TO HEIGHT
60 FOR C=0 TO WIDTH
70 LOC=SCREEN+(OFFSETY+R)*40+(OFFSETX+C)
80 CHAR=32 : COL=1
81 IF R=0 OR R=HEIGHT OR C=0 OR C=WIDTH THEN CHAR=160:COL=0
82 IF R>0 AND R<HEIGHT AND (C MOD 5=0) THEN CHAR=46:COL=3
90 POKE LOC,CHAR
100 POKE COLOR+(OFFSETY+R)*40+(OFFSETX+C),COL
110 NEXT C
120 NEXT R
- Lines 70–82: pick wall (
160
), floor (32
), and pillars (46
) based on loop indices. - Offsets centre the room without rewriting the math.
- Changing
WIDTH
/HEIGHT
redraws the room instantly.
[🎥 suggested: room drawing line-by-line across the screen]
Checkerboard Floors (pattern logic)
NEW
10 SCREEN=1024 : COLOR=55296
20 FOR R=0 TO 7
30 FOR C=0 TO 7
40 LOC=SCREEN+(R+8)*40+(C+16)
50 COL=(R+C) AND 1
60 POKE LOC,32
70 POKE COLOR+(R+8)*40+(C+16),COL
80 NEXT C
90 NEXT R
Use (R+C) AND 1
to alternate values. Swap 32
for 160
if you want solid tiles, or 42
to mark special zones.
Decorative Borders and Doorways
NEW
10 PRINT CHR$(147)
20 SCREEN=1024 : COLOR=55296
30 FOR I=0 TO 39
40 POKE SCREEN+I,160 : POKE COLOR+I,0
50 POKE SCREEN+24*40+I,160 : POKE COLOR+24*40+I,0
60 NEXT I
70 FOR I=0 TO 24
80 POKE SCREEN+I*40,160 : POKE COLOR+I*40,0
90 POKE SCREEN+I*40+39,160 : POKE COLOR+I*40+39,0
100 NEXT I
110 FOR C=15 TO 24
120 POKE SCREEN+12*40+C,32 : POKE COLOR+12*40+C,1
130 NEXT C
The last loop carves a doorway. Guard door logic is now a matter of checking map values, not rewriting art.
Generating Repeatable Patterns with Functions
NEW
10 PRINT CHR$(147)
20 SCREEN=1024 : COLOR=55296
30 WIDTH=14 : HEIGHT=10
40 OFFSETX=12 : OFFSETY=7
50 DEF FNPLAT(X,Y) = (X MOD 4=0 AND Y MOD 2=0)
60 FOR R=0 TO HEIGHT
70 FOR C=0 TO WIDTH
80 LOC=SCREEN+(OFFSETY+R)*40+(OFFSETX+C)
90 CHAR=32 : COL=1
100 IF R=0 OR R=HEIGHT OR C=0 OR C=WIDTH THEN CHAR=160:COL=0
110 IF FNPLAT(C,R) THEN CHAR=163:COL=6
120 POKE LOC,CHAR
130 POKE COLOR+(OFFSETY+R)*40+(OFFSETX+C),COL
140 NEXT C
150 NEXT R
DEF FNPLAT
decides where to drop platform tiles, and because it’s a function you can reuse it across rooms.
Experiment Section
- Split the loops into a subroutine
GOSUB 2000
that takesWIDTH
,HEIGHT
,OFFSETX
,OFFSETY
as global variables. - Fill an array
MAP(R,C)
first, then draw from it—mirrors what the full engine uses. - Add light/dark shading:
IF (R+C) AND 1 THEN COL=COL+8
to toggle between colour banks. - Load patterns from DATA: call
RESTORE
,READ
each tile, and print inside the loop. - Scroll backgrounds by shifting OFFSET values frame by frame.
[📷 suggested: screenshot comparing two rooms generated with different parameters]
Concept Expansion
Nested loops are your procedural paintbrush. Later you’ll translate these patterns into sprite data, decompress maps from disk, and use assembly to accelerate updates, but the structure—the double loop—never changes.
Game Integration
- Room templates: reuse the same generator with different offsets to build multi-room dungeons.
- Collision map sync: fill both the visual screen and a collision array from the same loop so they stay in lockstep.
- Animated floors: swap the character code each frame inside the loop for water or lava effects.
- Minimap: run a smaller nested loop to render a thumbnail of the room in the HUD.
From the Vault
- Gridlocked — base map lesson this builds on.
- Paradroid — classic example of tile-based rooms drawn by nested loops.
Quick Reference
FOR ROW=0 TO HEIGHT
FOR COL=0 TO WIDTH
LOC = SCREEN + (OFFSETY+ROW)*40 + (OFFSETX+COL)
POKE LOC, CHAR
POKE COLOR + (OFFSETY+ROW)*40 + (OFFSETX+COL), COLVALUE
NEXT COL
NEXT ROW
- Keep constants (
SCREEN
,COLOR
) at the top. - Compute offsets once, reuse them inside loops.
- Separate tile selection logic (if/else) from the write statements for clarity.
What You’ve Learnt
- Built reusable room generators with nested loops and offsets.
- Layered screen and colour memory updates to keep tiles and palettes aligned.
- Parameterized pattern functions for platforms, borders, and checkerboards.
- Set the stage for Week 2’s maze mini-game to stitch rooms together.
Next lesson: Math Magic — wrap formulas in DEF FN so your loops can call clean, reusable calculations.