4.4 KiB
Eight windows and random entry
Layout
scripts/room.gd now builds eight windows, two per wall (four walls), spaced
symmetrically about each wall centre. WIN_EDGE_GAP = 2.4 m is the wall left between a
window edge and the room corner, which for an 18 m wall with 4 m windows gives: openings
centred at ±4.6 m, 2.4 m of wall at each corner, and a 5.2 m pillar between the two
openings. The number of windows follows from the constants:
const WINDOWS_PER_WALL := 2
const WIN_EDGE_GAP := 2.4
static func window_offsets(length: float) -> Array[float]
window_offsets() works for any count: centres are spread evenly between
±(length/2 − WIN_W/2 − WIN_EDGE_GAP), so raising WINDOWS_PER_WALL widens the row
instead of pushing openings out of the wall, and a single window stays centred.
The wall builder was generalised from "one opening in the middle" to any number of
openings: solid pieces along the wall between openings and at both ends, plus a sill and
a header per opening. The room-space UVs (see OFFICE-SURFACES.md) are unchanged: a
segment is mapped from its own world position, so the extra openings do not restart the
pattern. With two openings per wall there are 7 segments per wall, 29 surfaces in total
(counted from the constants by test_office_uv.gd).
Spawn data
Every window publishes one record:
windows.append({"center": center, "normal": wall.normal, "axis": wall.axis,
"slots": slots, "glass": glass})
center: a point on the room-side wall face at y = 0;normal: pointing into the room;slots:SPAWN_SLOTS = 4points spread across the opening,SPAWN_OUTSIDE = 1.2 moutside the wall;glass: the pane of that specific window.
The old window_spawn_points and window_normals arrays are still filled and are now
actually consumed — they were computed and ignored before, which was one of the known
anomalies of this prototype.
Entry logic
main.gd no longer uses four hardcoded cardinal centres:
_pick_window()draws a random window and never repeats the previous one, so successive zombies come from different openings instead of always the same wall;- a random slot inside that window is picked, so even the same window is entered from a different spot;
- the entry tween is unchanged (1.2 s rising to sill height, then 0.8 s into the room);
- only that window's glass is shattered (looked up by identity) instead of scanning every pane and guessing by distance.
Notes and limits
- With eight openings, three of the window-to-centre diagonals are crossed by furniture
(the rotated chair at (6.8, 0, −4) and the two desks). This is not a defect: the A*
grid routes zombies around it, and
test_office_atmosphere.gdnow asserts what matters — every window is a real opening and every window is connected to the room centre through the navigation grid. It prints a note for the obstructed diagonals. - Zombies entering from eight directions spend visibly less time in a queue at one wall,
which changes the pacing a little; wave sizes are untouched (
4 + 2n).
Verification
"$G" --headless --path . --script res://tools/test_spawn_windows.gd
"$G" --display-driver x11 --rendering-method gl_compatibility --path . --script res://tools/shot_windows.gd
test_spawn_windows.gd checks: eight windows, two per wall, symmetric, with at least 1 m
of wall at the corners and the expected pillar; 32 spawn slots, all outside the room,
aligned with their opening and at the right distance; 400 random draws covering all eight
windows with no immediate repetition; a ray proving each opening is a real hole in the
wall while the pillar between the openings is solid; six real spawns, all starting
outside and ending inside with the correct pane shattered (counted by identity, so two
zombies using the same window break it once).
Two traps met while writing it, both worth remembering:
- the first wave starts automatically in
_ready, so a test that counts panes must wait for that wave and its tweens, otherwise the counts are polluted; - physics ray queries need
await physics_frameafter building the room, otherwisedirect_space_stateis still empty and the assertions pass or fail for the wrong reason.
Images /tmp/zombie-windows-{nord,est,sud,ovest,angolo,ingresso}.png show the two
openings per wall, the pillar between them, and a group of zombies that came in.