178 lines
10 KiB
Markdown
178 lines
10 KiB
Markdown
# 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.
|