diff options
| author | Kai Stevenson <kai@kaistevenson.com> | 2026-08-30 18:42:16 -0700 |
|---|---|---|
| committer | Kai Stevenson <kai@kaistevenson.com> | 2026-08-30 18:42:16 -0700 |
| commit | 56bba5560be95c1e05bfec11e4fc085654f3589d (patch) | |
| tree | f4eee7eb7abdce9ab6d0a7a66e3e43d429229b97 /src/proc_gen/herringbone.rs | |
| parent | a0e3b22efb1d1a8b885717481061074459fe109f (diff) | |
working with tilesets
Diffstat (limited to 'src/proc_gen/herringbone.rs')
| -rw-r--r-- | src/proc_gen/herringbone.rs | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/src/proc_gen/herringbone.rs b/src/proc_gen/herringbone.rs new file mode 100644 index 0000000..5e930ec --- /dev/null +++ b/src/proc_gen/herringbone.rs @@ -0,0 +1,83 @@ +use fxhash::hash32; +use glam::IVec2; + +use crate::{ + config::TILESET_SCALING, + content::materials::MaterialId, + proc_gen::tileset_loader::{Tile, TileOrientation, Tileset, TilesetPixelType}, + sim::cell::Cell, +}; + +fn split_position(world: IVec2, tileset: &Tileset) -> (IVec2, IVec2, TileOrientation) { + let s = tileset.dimensions.short as i32; + let tx = world.x.div_euclid(s); + let ty = world.y.div_euclid(s); + let fx = world.x.rem_euclid(s); + let fy = world.y.rem_euclid(s); + + match (tx - ty).rem_euclid(4) { + // left half of horizontal tile + 0 => ( + IVec2::new(tx, ty), + IVec2::new(fx, fy), + TileOrientation::Horizontal, + ), + // right half of horizontal tile + 1 => ( + IVec2::new(tx - 1, ty), + IVec2::new(fx + s, fy), + TileOrientation::Horizontal, + ), + // top half of vertical tile + 3 => ( + IVec2::new(tx, ty), + IVec2::new(fx, fy), + TileOrientation::Vertical, + ), + // bottom half of vertical tile + 2 => ( + IVec2::new(tx, ty - 1), + IVec2::new(fx, fy + s), + TileOrientation::Vertical, + ), + _ => unreachable!(), + } +} + +// better "%" for hashes since it prefers the high bits +#[inline] +fn reduce(h: u32, n: usize) -> usize { + (((h as u128) * (n as u128)) >> 32) as usize +} + +fn pick_variant(tile_pos: IVec2, orientation: TileOrientation, tileset: &Tileset) -> &Tile { + let h = hash32(&tile_pos); + match orientation { + TileOrientation::Horizontal => { + &tileset.horizontal_tiles[reduce(h, tileset.horizontal_tiles.len())] + } + TileOrientation::Vertical => { + &tileset.vertical_tiles[reduce(h, tileset.vertical_tiles.len())] + } + } +} + +// TODO: optimize +fn get_pixel_at_position(world: IVec2, tileset: &Tileset) -> TilesetPixelType { + let scaled_world = world.div_euclid(IVec2::new(TILESET_SCALING, TILESET_SCALING)); + let (tile_pos, local, orientation) = split_position(scaled_world, tileset); + let tile = pick_variant(tile_pos, orientation, tileset); + let width = match orientation { + TileOrientation::Horizontal => tileset.dimensions.long as i32, + TileOrientation::Vertical => tileset.dimensions.short as i32, + }; + tile.pixels[(local.x + local.y * width) as usize] +} + +pub fn get_cell_at_position(world: IVec2, tileset: &Tileset) -> Cell { + let pixel = get_pixel_at_position(world, tileset); + match pixel { + TilesetPixelType::Void => Cell::void(), + TilesetPixelType::Terrain => Cell::from_material(MaterialId::Dirt), + } +} |
