RU
games/doom-jumphp / AGENTS.md · commit 8e1cb9f
# IRON ABYSS (games/doom-jumphp) — notes for agentsRead `../../AGENTS.md` first. This game is a retro FPS whose engine is a PHP port of the 1993 GPL engine(renderer + game logic); all content is original. License GPL-2.0-or-later (LICENSE).## Layout- `src/Engine/` (not in the container, created with `new`):  - `Palette` 16 ramps x 16 shades; colormaps = darken along a ramp; index 255 = transparent. `Palette::darken()` = strtr.  - `Art` reads `assets/data/art.pak` (serialized; walls column-major, flats row-major, sprites column-major with    per-column opaque ranges, weapons, HUD pictures); caches darkened copies.  - `Map/LevelBuilder` turns the text levels into sectors / lines (64-unit cells, merges collinear edges,    diagonal cells), `Map/NodeBuilder` builds the BSP, `Map/Level` = geometry + block map + `sectorAt()`.  - `SoftRenderer` = r_bsp / r_segs / r_plane / r_things port (floats). 320x168 view (160 = low detail).  - `Screen` palette frame -> RGBA (strtr) -> one GL texture (rows reversed: GL is bottom-up); GD BMP fallback.- `src/Game/`: `World` (35 Hz tic, things, player) + traits `Physics` (p_map/p_maputl/p_sight), `Actions`  (p_enemy, p_inter, p_pspr), `Specials` (doors, lifts, switches, lights, secrets). `Info` = states and thing  types, `Weapons`, `Player`, `Hud` (status bar), `Bot` (demo / smoke), `Campaign` (levels m1..m3), `SoundBank`.- `src/Scene/`: Title (renders m1 behind the menu), Skill, Play, Pause, Options, Help, Intermission, Victory.## Graphics modesOption `graphics` ('retro' default | 'hd'), switched by GRAPHICS in the title menu (`Game\Graphics`). HD = `Engine\HdRenderer`(+ `HdShaders`, `Game\HdView`): JumPHP's 3D layer ('below', 'native', key colour magenta: scenes clear the 2D with[255, 0, 255] and draw the HUD over it), geometry built once per level, sector heights / lights in a 256x2 texture read bythe vertex shader (doors and lifts move without rebuilding), Scale2x textures, 8 point lights, fog, contact shadows,post shader (bloom, tint, vignette). Supersample 2 in the desktop app only. Scenes call `Graphics::retro()` in exit().Test param `graphics: hd` (PlayScene, TitleScene); `profile: true` prints the render time on stderr.## Levels (`assets/maps/<id>.json`)`legend` (char -> solid / area / diagonal, see the LevelBuilder docblock), `map` rows, `things` rows (same size,chars of `Info::THING_LEGEND`). Kinds: door (use), gate (opened by `switch: open:<char>` or by the warden'sdeath when `boss: true`), lift (use from below, or step on it from above), exit (walk in); `X` solids with`switch: exit`. `hidden: true` doors look like walls; `secret: true` areas count as secrets.The levels were authored with small Python helpers (rectangles painted in a grid); edit the JSON directly.## Tests`tests/*Test.php`: World tests (no window) per mechanic + `GameFlowTest` (scenes). `PlayScene` test params:`level`, `skill`, `demo`, `god`, `weapons`, `at: [col, row, degrees]`, `detail: low|high`.Phones: touch buttons send F (fire) and E (use); the mouse is read by PlayScene on non-mobile only (a touch is a click).Screenshots: `JUMPHP_SCENE='App\Scene\PlayScene' JUMPHP_SCENE_PARAMS='{"level":"m2","at":[9,29,90]}' bin/jumphp shot doom-jumphp 20`.## Non-obvious- 32-bit browser: the RNG is `(75 x + 74) mod 65537`; never multiply big ints.- Things are interpolated between tics (px/py/pz); the scene renders at the display rate.- The art is regenerated by `tools/make-art.php` (monsters take ~a minute: they are ray-traced primitives).