Switch to 16-bit truecolor framebuffer and PNG assets
pbio moves to git.bnd.wtf/irrlicht/pbio.git branch truecolor16: the framebuffer is now RGB565 u16, no palette. Assets are loaded from PNG via the png crate and quantized to RGB565 on load; transparency comes from the alpha channel as a per-tile opacity mask, so any color (black included) can be opaque. The TGA loader and the palette-order fragility are gone. overworld.png is the unmodified Mini-Medieval Overworld sheet (same 24-column layout as the old TGA, so map tile ids are unchanged); entities.png holds the player sprite extracted from the old entities.tga. Adds an ignored snapshot test that renders the first frame headlessly to a PNG for eyeballing the renderer without a window. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
64a6e1d42d
commit
5a055c048d
+19
-12
@@ -2,15 +2,22 @@
|
||||
|
||||
## Current state
|
||||
|
||||
TGA loading is implemented in `game/src/assets.rs`. `Image::from_tga(path)` reads the file,
|
||||
parses the 18-byte header, skips the colormap block, and returns an `Image` — supporting
|
||||
type 1 (uncompressed) and type 9 (RLE) via the private `decode_rle()` function in the same
|
||||
module. `game.rs` uses it directly: `Image::from_tga("assets/tilesets/overworld.tga")`.
|
||||
PNG loading is implemented in `game/src/assets.rs`. `Image::from_png(path)` decodes via the
|
||||
`png` crate (any color type, expanded to 8-bit RGBA) and quantizes on load to the
|
||||
framebuffer's RGB565 format with `pbio::rgb565`; alpha ≥ 128 counts as opaque. The result
|
||||
is an `Image { width, height, pixels: Vec<u16>, opaque: Vec<bool> }`. Artists work in
|
||||
truecolor; there is no palette an asset could be "in the wrong order" for. `game.rs` uses it
|
||||
directly: `Image::from_png("assets/tilesets/overworld.png")`.
|
||||
|
||||
`Image` also provides `to_tileset() -> Vec<[u8; 64]>`, which splits the image into 8×8
|
||||
tiles row-major. Every tile is emitted; tile ID is the flat row-major index into the Vec,
|
||||
so tiles are never skipped or reordered. (Transparency is a per-pixel concern handled at
|
||||
blit time by `blit_tile`, not by the splitter.)
|
||||
`Image` also provides `to_tileset() -> Vec<Tile>`, which splits the image into 8×8 tiles
|
||||
row-major. A `Tile` is 64 RGB565 pixels plus a `u64` opacity bitmask. Every tile is
|
||||
emitted; tile ID is the flat row-major index into the Vec, so tiles are never skipped or
|
||||
reordered. `overworld.png` is the unmodified Mini-Medieval `Overworld.png` sheet (24
|
||||
columns), so Tiled tile ids line up with the Vec index.
|
||||
|
||||
History: the first iteration used 8-bit indexed TGAs on a palette framebuffer (RGB332,
|
||||
`pbio` master branch). The colormap-ordering fragility and the index-0-is-transparent
|
||||
convention are gone with the switch to `pbio`'s `truecolor16` branch.
|
||||
|
||||
`AssetStore` (a named registry) is **not yet implemented**. Assets are currently loaded
|
||||
inline in `Game::start()`.
|
||||
@@ -22,12 +29,12 @@ files directly at the call site.
|
||||
|
||||
## Design notes
|
||||
|
||||
- `Image` struct: `width: u32`, `height: u32`, `pixels: Vec<u8>` — done.
|
||||
- `Image` struct: `width: u32`, `height: u32`, `pixels: Vec<u16>`, `opaque: Vec<bool>` — done.
|
||||
- A simple `AssetStore` could be a `HashMap<&'static str, Image>` loaded at startup.
|
||||
- No streaming needed — the whole game is small enough to load everything upfront in `start()`.
|
||||
- Palette index 0 is transparent when blitting sprites. This convention is enforced by
|
||||
`blit_tile()` in `pixelhelper.rs`; the loader itself does not need to handle it.
|
||||
- Pixel assets are stored as flat `Vec<u8>` of palette indices, row-major, width × height bytes.
|
||||
- Transparency is the tile's mask bit, checked by `blit_tile()` in `pixelhelper.rs`. Any
|
||||
color — black included — can be an opaque pixel.
|
||||
- Pixel assets are stored as flat `Vec<u16>` of RGB565 values, row-major, width × height.
|
||||
- Future: consider embedding assets with `include_bytes!` to produce a single binary.
|
||||
|
||||
## Open questions
|
||||
|
||||
Reference in New Issue
Block a user