summaryrefslogtreecommitdiff
path: root/src/proc_gen/herringbone.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/proc_gen/herringbone.rs')
-rw-r--r--src/proc_gen/herringbone.rs83
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),
+ }
+}