diff options
| author | Kai Stevenson <kai@kaistevenson.com> | 2026-08-31 00:03:32 -0700 |
|---|---|---|
| committer | Kai Stevenson <kai@kaistevenson.com> | 2026-08-31 00:03:32 -0700 |
| commit | d68cf09f7b8e5cb783dc495097c17eaf2a4d5427 (patch) | |
| tree | 59216cae8c466ad63fa6ff47dc5c7f35c64c23d2 /src/proc_gen/mod.rs | |
| parent | 8e128d3ca24fa10dc7d871f7daf6c43eaddc385c (diff) | |
cleanupkai/herringbone
Diffstat (limited to 'src/proc_gen/mod.rs')
| -rw-r--r-- | src/proc_gen/mod.rs | 101 |
1 files changed, 66 insertions, 35 deletions
diff --git a/src/proc_gen/mod.rs b/src/proc_gen/mod.rs index 049ad1a..caec241 100644 --- a/src/proc_gen/mod.rs +++ b/src/proc_gen/mod.rs @@ -6,66 +6,97 @@ use glam::IVec2; use crate::{ config::{CHUNK_SIZE, TILESET_SCALING}, proc_gen::{ - herringbone::tiles_overlapping, + herringbone::{tiles_overlapping, variant_index}, tileset_loader::{Tile, TileOrientation, Tileset, load_tileset}, }, sim::{cell::Cell, cell_manager::chunk::Chunk, entity::EntityDef}, }; +pub struct TileCells { + pub size: IVec2, + pub cells: Vec<Cell>, +} + pub trait Biome { - fn derive_world_from_tile(&self, _tile: &Tile) -> Vec<Cell> { - Vec::new() - } - fn derive_entities_from_tile(&self, _tile: &Tile) -> Vec<EntityDef> { + fn derive_world_from_tile(&self, tile: &Tile) -> TileCells; + fn derive_entities_from_tile(&self, tile: &Tile) -> Vec<EntityDef> { Vec::new() } } pub struct TilesetWorldGenerator { tileset: Tileset, - biome: Box<dyn Biome>, + horizontal_tiles: Vec<TileCells>, + vertical_tiles: Vec<TileCells>, } impl TilesetWorldGenerator { + pub fn new(tileset_path: &str, biome: &dyn Biome) -> Self { + let tileset = load_tileset(tileset_path); + + let horizontal_tiles = tileset + .horizontal_tiles + .iter() + .map(|tile| biome.derive_world_from_tile(tile)) + .collect(); + let vertical_tiles = tileset + .vertical_tiles + .iter() + .map(|tile| biome.derive_world_from_tile(tile)) + .collect(); + + TilesetWorldGenerator { + tileset, + horizontal_tiles, + vertical_tiles, + } + } + + fn grid_size(&self) -> IVec2 { + IVec2::splat(self.tileset.dimensions.short as i32 * TILESET_SCALING) + } + + fn tile_at(&self, grid: IVec2, orientation: TileOrientation) -> &TileCells { + let tiles = match orientation { + TileOrientation::Horizontal => &self.horizontal_tiles, + TileOrientation::Vertical => &self.vertical_tiles, + }; + &tiles[variant_index(grid, tiles.len())] + } + pub fn generate_chunk(&self, chunk_position: IVec2) -> Chunk { let mut chunk = Chunk::void(); - let a = chunk_position * CHUNK_SIZE; - let b = (chunk_position + 1) * CHUNK_SIZE; - let tiles = tiles_overlapping(a * TILESET_SCALING, b * TILESET_SCALING, &self.tileset); - let world_tiles = tiles.map(|(p, t, o)| (p, self.biome.derive_world_from_tile(t), o)); + let chunk_min = chunk_position * CHUNK_SIZE; + let chunk_max = chunk_min + CHUNK_SIZE; + + let grid = self.grid_size(); + let tiles = tiles_overlapping( + chunk_min.div_euclid(grid), + (chunk_max - 1).div_euclid(grid) + 1, + ); + + for (grid_position, orientation) in tiles { + let tile = self.tile_at(grid_position, orientation); + let tile_min = grid_position * grid; - for (tp, t, o) in world_tiles { - let p = tp * self.tileset.dimensions.short as i32 * TILESET_SCALING; - let ta = p.max(a); - let tb = p.min(b); - if ta.x >= tb.x || ta.y >= tb.y { + // subset of tile in chunk + let min = tile_min.max(chunk_min); + let max = (tile_min + tile.size).min(chunk_max); + if min.x >= max.x { continue; } + let width = (max.x - min.x) as usize; - for y in ta.y..tb.y { - for x in ta.x..tb.x { - let sw = match o { - TileOrientation::Horizontal => { - self.tileset.dimensions.long as i32 * TILESET_SCALING - } - TileOrientation::Vertical => { - self.tileset.dimensions.short as i32 * TILESET_SCALING - } - }; - - let src = (y - p.y) * sw + (x - p.x); - let dst = (y - a.y) * CHUNK_SIZE + (x - a.x); - chunk.cells[dst as usize] = t[src as usize]; - } + for y in min.y..max.y { + let src = ((y - tile_min.y) * tile.size.x + (min.x - tile_min.x)) as usize; + let dst = ((y - chunk_min.y) * CHUNK_SIZE + (min.x - chunk_min.x)) as usize; + chunk.cells[dst..dst + width].copy_from_slice(&tile.cells[src..src + width]); } } - chunk - } + chunk.mark_collider_dirty(0); - pub fn new(tileset_path: &str, biome: Box<dyn Biome>) -> Self { - let tileset = load_tileset(tileset_path); - TilesetWorldGenerator { tileset, biome } + chunk } } |
