Eight windows per room and random zombie entry from different windows
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
# 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:
|
||||
|
||||
```gdscript
|
||||
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:
|
||||
|
||||
```gdscript
|
||||
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 = 4` points spread across the opening, `SPAWN_OUTSIDE = 1.2 m`
|
||||
outside 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.gd` now 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
|
||||
|
||||
```sh
|
||||
"$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:
|
||||
|
||||
1. 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;
|
||||
2. physics ray queries need `await physics_frame` after building the room, otherwise
|
||||
`direct_space_state` is 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.
|
||||
Reference in New Issue
Block a user