Replace placeholder rendering with real sprites and audio

Terrain, actors, boss and bullets are sprites now, and four sounds play off
server events. 548KB total across seven files, out of 3.9GB of source packs.

- src/view/art.gd holds every atlas rect and sound path in one table, copied
  from the 0x72 pack's own tile_list. Scattering coordinates through draw calls
  would make re-cutting the atlas a hunt, and a wrong rect invisible.
- Bullets get one MultiMesh per kind rather than one overall: a
  MultiMeshInstance2D carries a single texture and each kind needs a different
  region of the sheet. Four draw calls, no custom shader passing UVs through
  per-instance data.
- src/view/sfx.gd is a 16-voice round-robin pool. Bullet-hell fire rates mean
  sounds overlap constantly, and identical sounds landing within two frames are
  collapsed so a ring hitting eight bullets is a bang rather than clipping.
  Every sound is triggered by a server event, never a local guess, so what you
  hear matches what happened.

Audio was converted, not copied: the pack ships 24-bit/96kHz masters averaging
2MB. Downsampled to 16-bit/44.1kHz mono, silence-trimmed, and the shoot sound
hard-capped to 0.30s -- it came out at 2.03s, against a fire cooldown of 0.12s,
which would have smeared held fire into noise.

tests/unit/test_art.gd checks what cannot be eyeballed here: every atlas rect
lands inside its texture, every animation frame of a strip fits (the last frame
is what runs off the sheet, not the first), there is a sprite per bullet kind
and per enemy visual, and no sound is long enough to stack badly. A wrong atlas
coordinate does not error -- it silently draws the wrong pixels.

Licence sources recorded in docs/ASSETS.md now that they are known. All four
are free versions and four rows still say "confirm at source": free itch packs
vary on credit and commercial use, and there is no credits screen yet.

155 tests (was 146). check.sh, test.sh and smoke.sh pass.
This commit is contained in:
2026-09-03 23:43:13 +02:00
parent 7ee6c8e761
commit 9fa2e260f2
23 changed files with 563 additions and 113 deletions
+31 -21
View File
@@ -5,35 +5,45 @@ The packs themselves are **not in git** (see
licence files are not either. This file is the record that survives. Keep it
current when a pack is added or removed.
## Why nothing is imported yet
## How assets get from a pack into the game
`assetpacks/` carries a `.gdignore`, so Godot skips it entirely. Nothing there
can be referenced from a scene or script until it is copied into
`res://assets/` in game-ready form. That is deliberate: the tree is 3.9 GB, and
`tools/check.sh` runs `--import`, which would otherwise walk all of it on every
run.
`assetpacks/` carries a `.gdignore`, so Godot skips it entirely — nothing there
can be referenced from a scene or script. Files are copied into `res://assets/`
in game-ready form, and only then imported. The tree is 3.9 GB and
`tools/check.sh` runs `--import`, which would otherwise walk all of it every run.
What is in the game today totals **548 KB** across seven files: three sprite
sheets and four sounds. Sprite rects and sound paths are all declared in one
place, [src/view/art.gd](../src/view/art.gd), and
`tests/unit/test_art.gd` asserts every rect lands inside its texture — a wrong
atlas coordinate does not error, it silently draws the wrong pixels.
## Packs
| Pack | Size | Intended use | Licence |
All four are the **free** versions. Source URLs are recorded because the packs
themselves are gitignored, so their bundled licence files are not in the repo.
| Pack | Source | In use | Licence |
| --- | --- | --- | --- |
| 0x72 Dungeon Tileset II v1.7 | 1.6 MB | Dungeon tiles — maps to the `MapGrid.Kind` tiles the generator already emits | **Unrecorded.** Bundled README is technical, not legal. Widely distributed as CC0 by Robert Norenberg (0x72), but confirm at the source before shipping. |
| Effect and FX Pixel All Free | 29 MB | Hit flashes, muzzle flashes, death effects | **Unrecorded** — no licence file in the pack. |
| Helton Yan's Pixel Combat | 3.9 GB | Combat SFX | **Unrecorded** — no licence file in the pack. |
| New All Fire Bullet Pixel 16x16 | 360 KB | Bullet sprites, to replace the generated dot in `bullet_renderer.gd` | **Unrecorded** — no licence file in the pack. |
| `considering_dont_use_yet/` — RF Catacombs v1.0 | part of 1.6 MB | Undecided | **Public domain**, per bundled `public-license.txt`. "Free to use, personal or commercial. Credit not required but appreciated. You can edit, but not resell the asset pack." Artwork by Szadi art. |
| `considering_dont_use_yet/` — Tiny RPG Character Pack 02, neo_zero v1.0 / 3.0 demo | part of 1.6 MB | Undecided | **Unrecorded.** |
| 0x72 Dungeon Tileset II v1.7 | https://0x72.itch.io/dungeontileset-ii | Terrain, player, enemies, boss → `assets/sprites/dungeon_tileset.png` | Confirm at source. Widely distributed as CC0 by Robert Norenberg (0x72); the bundled README is technical, not legal. |
| Fire Pixel Bullet 16x16 | https://bdragon1727.itch.io/fire-pixel-bullet-16x16 | Bullets → `assets/sprites/bullets.png` | Confirm at source (free version). |
| 750+ Effect and FX Pixel All | https://bdragon1727.itch.io/750-effect-and-fx-pixel-all | Impact effect → `assets/sprites/impact.png` | Confirm at source (free version). |
| Helton Yan — Pixel Combat | https://heltonyan.itch.io/pixelcombat | SFX → `assets/audio/sfx/*.wav` | Confirm at source (free version). |
### Action needed before shipping anything
### Not in use
Four of the six packs arrived with no licence text at all. Redistribution terms
for pixel-art and audio packs vary a lot — some free packs forbid commercial
use, some require credit, and "free demo" versions (two of the undecided packs
are demos) are often more restricted than the paid ones.
`assetpacks/considering_dont_use_yet/` is the user's own "not chosen" marker and
nothing there is referenced by the game. It contains RF Catacombs v1.0 (public
domain per its bundled `public-license.txt` — free for personal or commercial
use, credit appreciated, no reselling; artwork by Szadi art), plus Tiny RPG
Character Pack 02 and neo_zero demos, whose terms are unrecorded.
Record the source URL and terms for each **Unrecorded** row above before any of
it goes into a build. The `considering_dont_use_yet/` packs are the user's own
"not chosen yet" marker; leave them there until that changes.
### Still to confirm
Free itch.io packs vary: some are CC0, some require credit, some restrict
commercial use, and "free version" often carries different terms from the paid
one. Four rows above say *confirm at source* — do that before a public build,
and if any require attribution, the credits screen does not exist yet.
## Converting audio before use
+16
View File
@@ -53,6 +53,22 @@ draws whatever it holds. The defence is what the server declines to send.
---
## Art and audio · *first pass done*
Placeholders are gone: terrain, actors and bullets are sprites, and four sounds
play off server events. Enough to prove the pipeline, not a finished look.
| Feature | State | Where |
| --- | --- | --- |
| Atlas/sound table in one place | done | [src/view/art.gd](../src/view/art.gd) |
| Terrain, actors, boss from the 0x72 atlas | done | `WorldView._draw_tile` / `_draw_sprite` |
| Animated bullet sprites, one MultiMesh per kind | done | [src/view/bullet_renderer.gd](../src/view/bullet_renderer.gd) |
| SFX pool driven by server events | done | [src/view/sfx.gd](../src/view/sfx.gd) |
| Rects validated without a display | done | `tests/unit/test_art.gd` |
| Impact/death VFX animation | todo | `Art.IMPACT` is loaded and validated but nothing plays it yet |
| Directional sprites, hit flashes, screen shake | todo | |
| Audio buses and a volume setting | todo | Everything plays on Master at hardcoded dB |
## Stage 2 — Characters, persistence, levels · *todo, next*
Depends on nothing in Stage 1 except a place to stand. Blocked only on the