Replaces the CPU pixel-baking quilter system (QuiltCache, TerrainSprite, pixel_buffers) with Bevy's native TilemapChunk GPU-index-lookup API. Architecture: - TilemapChunk entities replace TerrainSprite entities per (chunk, z, layer) - Tileset PNG stacked vertically as texture_2d_array (11 rows: 6 floor + 5 fixture) - populate_chunk_tiles reads TileMap HashMap directly; no ECS FloorTile entities - Chunk spawn deferred to apply_terrain_blobs (after TileMap data exists) - Dirty key system triggers repopulate on occlusion/camera-z changes Bug fixes: - populate_chunk_tiles: add chunk_pos offset to world tile lookups (was always (0,0)) - spawn_tilemap_chunks: offset Transform by -TILE_SIZE/2 (tile-centre vs bottom-left) - spawn_tilemap_chunks: AlphaMode2d::Blend (was Opaque, blocking DF fade) - update_tilemap_chunk_visibility: actually mutate Visibility (was read-only) - handle_tile_occlusion_updates: mark dirty keys inline (was double-reading events) - TilemapChunkSpawner: deduplicate pending queue and guard stale registry Performance: - ~115K FloorTile ECS entities eliminated - GPU memory: O(tile_data) instead of O(CHUNK_TILES² × z_levels × pixel_bytes) - Z-scroll: only TilemapChunkTileData repopulates (no entity re-spawn) - Benchmarks via TilemapBenchmark resource (F9 to report)
51 lines
1.7 KiB
Rust
51 lines
1.7 KiB
Rust
use image::{GenericImageView, ImageBuffer, Rgba};
|
|
|
|
const TILE_PX: u32 = 16;
|
|
|
|
const ROWS: &[(&str, u8)] = &[
|
|
("assets/sky.png", 0), // air (transparent)
|
|
("assets/grass_floor.png", 1), // grass
|
|
("assets/dirt_floor.png", 2), // dirt
|
|
("assets/rock_floor.png", 3), // rock
|
|
("assets/bedrock_floor.png", 4), // bedrock
|
|
("assets/sky.png", 5), // sky (transparent)
|
|
("assets/dirt_wall.png", 6), // dirt_wall fixture
|
|
("assets/rock_wall.png", 7), // rock_wall fixture
|
|
("assets/bedrock_wall.png", 8), // bedrock_wall fixture
|
|
("assets/log.png", 9), // log fixture
|
|
("assets/leaves.png", 10), // leaves fixture
|
|
];
|
|
|
|
fn main() {
|
|
let rows = ROWS.len() as u32;
|
|
let mut combined: ImageBuffer<Rgba<u8>, Vec<u8>> =
|
|
ImageBuffer::from_pixel(TILE_PX, TILE_PX * rows, Rgba([0, 0, 0, 0]));
|
|
|
|
for (i, (path, _id)) in ROWS.iter().enumerate() {
|
|
let y = i as u32 * TILE_PX;
|
|
match image::open(path) {
|
|
Ok(img) => {
|
|
image::imageops::overlay(&mut combined, &img, 0, y as i64);
|
|
println!("cargo:rerun-if-changed={}", path);
|
|
}
|
|
Err(e) => {
|
|
eprintln!(
|
|
"Warning: could not open {} — leaving row {} blank ({})",
|
|
path, i, e
|
|
);
|
|
let mut row_pixels = combined.rows_mut();
|
|
if let Some(row) = row_pixels.nth(i) {
|
|
for px in row {
|
|
*px = Rgba([255, 0, 255, 255]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
combined
|
|
.save("assets/tileset.png")
|
|
.expect("Failed to write assets/tileset.png");
|
|
println!("cargo:rerun-if-changed=build.rs");
|
|
}
|