summaryrefslogtreecommitdiff
path: root/src/proc_gen/mod.rs
diff options
context:
space:
mode:
authorKai Stevenson <kai@kaistevenson.com>2026-08-31 00:03:32 -0700
committerKai Stevenson <kai@kaistevenson.com>2026-08-31 00:03:32 -0700
commitd68cf09f7b8e5cb783dc495097c17eaf2a4d5427 (patch)
tree59216cae8c466ad63fa6ff47dc5c7f35c64c23d2 /src/proc_gen/mod.rs
parent8e128d3ca24fa10dc7d871f7daf6c43eaddc385c (diff)
Diffstat (limited to 'src/proc_gen/mod.rs')
-rw-r--r--src/proc_gen/mod.rs101
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
}
}