Drop the chunk palette; chunks are plain u16 tile arrays

The 64-entry per-chunk palette was a wire-format artifact and capped a chunk
at 64 distinct tiles. A Chunk is now Box<[u16; 1024]> with flags derived from
the id on lookup — the same layout a binary on-disk format would use.

Map path becomes the first CLI argument; assets/map_large is a generated
256×256 stress map (loads in ~0.5 ms release). The snapshot test takes
SNAPSHOT_MAP.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
irrlicht
2026-09-18 23:40:52 +02:00
co-authored by Claude Opus 5
parent 5a055c048d
commit 1d14076468
10 changed files with 317 additions and 104 deletions
+11 -7
View File
@@ -76,13 +76,16 @@ pub struct Game {
}
impl Game {
pub fn start() -> Self {
pub fn start(map_path: &str) -> Self {
let tileset = Image::from_png("assets/tilesets/overworld.png").to_tileset();
let entity_tileset = Image::from_png("assets/tilesets/entities.png").to_tileset();
let map = TileMap::from_csv("assets/map_test");
println!("loaded map {}×{} ({} tiles)", map.width, map.height, map.tiles.len());
let mut sim = Sim::new(load_world(&map));
let t0 = std::time::Instant::now();
let map = TileMap::from_csv(map_path);
let world = load_world(&map);
println!("loaded {map_path}: {}×{} tiles in {:.1} ms",
map.width, map.height, t0.elapsed().as_secs_f64() * 1e3);
let mut sim = Sim::new(world);
let player_id = sim.world.spawn_entity(0, (0, 0), 100);
let mut game = Game {
@@ -338,7 +341,7 @@ impl Game {
let (ccx, ccy) = sim::world::tile_to_chunk(wx as i16, wy as i16);
let (lx, ly) = sim::world::tile_to_local(wx as i16, wy as i16);
let tile_id = self.sim.world.chunk(ccx, ccy)
.map(|c| c.get_tile(lx, ly).tile_id)
.map(|c| c.get_tile(lx, ly))
.unwrap_or(0);
let px = sx + vx * TILE_PX;
let py = sy + vy * TILE_PX;
@@ -389,13 +392,14 @@ impl Game {
#[cfg(test)]
mod snapshot {
/// Renders the first frame headlessly to the PNG named by `$SNAPSHOT` — a way to
/// eyeball the renderer without a window:
/// eyeball the renderer without a window. `$SNAPSHOT_MAP` picks the map:
/// `SNAPSHOT=/tmp/frame.png cargo test -p game snapshot -- --ignored`
#[test]
#[ignore]
fn dump_frame() {
std::env::set_current_dir("..").unwrap();
let mut g = super::Game::start();
let map = std::env::var("SNAPSHOT_MAP").unwrap_or_else(|_| "assets/map_test".into());
let mut g = super::Game::start(&map);
let input = crate::input::InputState::new();
let mut frame = vec![0u16; 320 * 240];
g.update(&mut frame, 0, &input);
+3 -1
View File
@@ -19,7 +19,9 @@ fn main() {
let input_map = input::InputMap::new();
let mut input_state = input::InputState::new();
let mut last_update = Instant::now();
let mut game = game::Game::start();
// Optional map path: `game assets/map_large`.
let map_path = std::env::args().nth(1).unwrap_or_else(|| "assets/map_test".into());
let mut game = game::Game::start(&map_path);
while !plat.should_close() {
plat.poll_events(Some(Duration::from_millis(20)));