escape/sprites.md

10 KiB
Raw Blame History

Spritesheets to make

The game runs fine without any art (it bakes placeholder patterns), but these are the sheets it will pick up automatically the moment the PNG files exist. No code changes needed — the paths and frame numbers below come straight from src/config/*.json, so if you rearrange anything, update the JSON to match.

Format rules (all sheets)

  • PNG, laid out as a horizontal strip of square frames, left to right.
  • Frame size is 192×192 px (set by textureSize in walls.json for the wall sheet and by TEX_SIZE in src/engine/registry.js for the rest; everything is baked to 192×192 internally, so larger source frames just get downscaled).
  • frame in the config JSON is the 0-based index into the strip.
  • The view renders at 960×600 (1:1 with the display canvas), so wall textures are seen at roughly full detail at one cell's distance. Draw with neutral, flat lighting — the engine adds its own directional shade (east/west faces darker) and distance dimming.
  • Different entries may point at different files; each unique path is loaded once. A sheet that is missing, or too narrow for a requested frame, falls back to the placeholder for that entry only.

1. assets/textures/walls.png — wall textures

7 frames → 1344×192 px. Opaque (no transparency; these fill the whole wall).

Frame Pixels Wall (walls.json) Placeholder it replaces
0 0–191 id 1 — Gray Brick gray #9a9a9a brick courses
1 192–383 id 2 — Blue Stone blue #4a6fa5 pattern
2 384–575 id 3 — Red Brick red #a5503f pattern
3 576–767 id 4 — Wood brown #8a6a3a planks
4 768–959 id 5 — Door gold #c8a838 pattern
5 960–1151 id 6 — Gold Door (locked) gold #d4af37 pattern
6 1152–1343 id 7 — Silver Door (locked) silver #a8a8c0 pattern

Notes:

  • One texture covers one full grid cell (all four faces use the same image; the engine un-mirrors back faces so text/asymmetric details stay readable).
  • Make the texture tileable left-to-right if you want long runs of the same wall type to look continuous.
  • Door frames (4–6) are drawn on the sliding panel itself — it slides sideways as the door opens, so avoid critical detail hugging the left edge (that's the edge that disappears first). Locked doors should visually hint at their key color.

2. assets/textures/overlays.png — wall overlays

3 frames → 576×192 px. Transparent background required — these are alpha-composited over the wall texture, so every transparent pixel shows the wall behind.

Frame Pixels Overlay (overlays.json) Intended look
0 0–191 painting1 — Portrait framed picture, centered
1 192–383 banner — Banner hanging cloth banner
2 384–575 vines — Vines creeping foliage over the wall

Notes:

  • The 192×192 frame maps to the entire wall face; leave generous transparent margins (the placeholder uses ~30 px) so it reads as an object on the wall.
  • One overlay per wall cell, shown on all faces of that block.

3. assets/sprites/items.png — decorative items

3 frames → 576×192 px. Transparent background required — rendered as floor-anchored billboards that always face the player.

Frame Pixels Item (items.json) In-game height (scale) Blocks?
0 0–191 plant — Potted Plant 0.6 × wall height yes
1 192–383 lamp — Floor Lamp 0.8 × wall height yes
2 384–575 rubble — Rubble 0.4 × wall height no

Notes:

  • Fill the frame with the object (touching the bottom edge) — the engine handles sizing via scale and anchors the frame's bottom to the floor, so empty space at the bottom of the frame makes the item float.

4. assets/sprites/enemy_*.png — enemies (one sheet per enemy)

13 frames → 2496×192 px each. Transparent background required — full-wall-height billboards. One PNG per enemy type:

File Enemy (enemies.json) Stats to suggest visually
assets/sprites/enemy_guard.png guard baseline: 50 hp, average speed
assets/sprites/enemy_heavy.png heavy tanky: 120 hp, slow — bulkier build
assets/sprites/enemy_scout.png scout fragile: 25 hp, fast — lighter build

Every sheet uses the same fixed frame order (ENEMY_FRAME_ORDER in src/engine/registry.js), offset from the enemy's frame base index in enemies.json (0 for a dedicated file; a nonzero base lets several enemies share one long strip):

Offset Pose Shown when
0 front facing the player, standing
1 frontWalk facing the player, walk-cycle alternate
2 left facing left (its left shoulder toward you), standing
3 leftWalk walk-cycle alternate
4 right facing right, standing
5 rightWalk walk-cycle alternate
6 back facing away, standing
7 backWalk walk-cycle alternate
8 aim spotted the player, weapon raised (reaction window / between shots)
9 fire flashed for ~150 ms after each shot
10 pain flinch while hurt (~120 ms after a non-fatal hit)
11 dying first 0.5 s after death (falling)
12 dead corpse — held 3 s, then fades out over 1 s

Notes:

  • Walk frames alternate with their standing pose while the enemy patrols (cadence tracks the enemy's speed); aim/fire are front-facing only — enemies turn to face the player whenever they engage.
  • Enemies are drawn at full wall height and stand on the floor; have the feet touch the bottom edge of the frame. The dying/dead frames live in the same full-height square, so draw the corpse lying along the bottom edge.
  • The hurt flash is generated automatically (white-tinted copy of the pain frame) — you don't need to draw one.
  • Any missing/short sheet falls back per-frame to pose-specific placeholder art, so partial sheets are fine while you work.

5. assets/sprites/pickups.png — pickups & keys

16 frames → 3072×192 px. Transparent background required — small floor-anchored billboards (drawn at 0.5 × wall height by default; add a scale field in pickups.json to change per pickup).

Frame Pixels Pickup (pickups.json) Placeholder it replaces
0 0–191 ammo — Ammo yellow diamond
1 192–383 health — Health green diamond
2 384–575 treasure — Treasure gold diamond
3 576–767 key_gold — Gold Key gold key glyph
4 768–959 key_silver — Silver Key silver key glyph
5 960–1151 ammo_mg — MG Ammo orange diamond
6 1152–1343 ammo_gatling — Gatling Ammo orange diamond
7 1344–1535 ammo_plasma — Plasma Cells teal diamond
8 1536–1727 gun_machinegun — Machine Gun brown diamond
9 1728–1919 gun_gatling — Gatling Gun rust diamond
10 1920–2111 gun_plasma — Plasma Gun teal diamond
11 2112–2303 ammo_rocket — Rockets red-orange diamond
12 2304–2495 gun_rocket — Rocket Launcher dark-red diamond
13 2496–2687 ammo_shells — Shells amber diamond
14 2688–2879 gun_shotgun — Shotgun tan diamond
15 2880–3071 gun_doubleshotgun — Double Shotgun brown diamond

Notes:

  • Key colors should match their door and their HUD chip (the chip uses the pickup's color from pickups.json).

Not needed (yet)

  • The exit uses a built-in generated marker (it's a level mechanic, not a configurable pickup).
  • Floors/ceilings are flat colors (FLOOR_COLOR / CEILING_COLOR in src/engine/constants.js); textured floors are a separate engine feature.
  • Weapon/hands on the HUD is a gray rectangle stub (HudScene).

Adding more content later

New wall/overlay/item/pickup = one new 192×192 frame appended to the relevant strip + one JSON entry in src/config/ pointing at its frame index. A new enemy = a fresh 13-frame sheet (see section 4) + its JSON entry. Nothing else. You can also start a fresh PNG per entry if you prefer — the texture path is per-entry, not global.

Changing resolution later

Frame size and render resolution are independent knobs: TEX_SIZE in src/engine/registry.js (+ textureSize in walls.json) for textures, RENDER_WIDTH/RENDER_HEIGHT in src/engine/constants.js for the view. Existing art keeps working after a change — frames are scaled at bake time — but redraw at the new size for full sharpness.