summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/content/world/mines.rs41
-rw-r--r--src/main.rs6
-rw-r--r--src/proc_gen/herringbone.rs46
-rw-r--r--src/proc_gen/mod.rs60
-rw-r--r--src/proc_gen/tileset_loader.rs12
5 files changed, 138 insertions, 27 deletions
diff --git a/src/content/world/mines.rs b/src/content/world/mines.rs
index e69de29..ae859bc 100644
--- a/src/content/world/mines.rs
+++ b/src/content/world/mines.rs
@@ -0,0 +1,41 @@
+use crate::{
+ config::TILESET_SCALING,
+ content::materials::MaterialId,
+ proc_gen::{
+ Biome,
+ tileset_loader::{Tile, TileOrientation, TilesetPixelType},
+ },
+ sim::cell::Cell,
+};
+
+pub struct MinesBiome;
+
+impl Biome for MinesBiome {
+ fn derive_world_from_tile(&self, tile: &Tile) -> Vec<Cell> {
+ let tp = TILESET_SCALING.pow(2) as u32;
+ let mut cells =
+ vec![Cell::void(); (tile.dimensions.short * tile.dimensions.long * tp) as usize];
+ let ey = match tile.orientation {
+ TileOrientation::Horizontal => tile.dimensions.short,
+ TileOrientation::Vertical => tile.dimensions.long,
+ };
+ let ex = match tile.orientation {
+ TileOrientation::Horizontal => tile.dimensions.long,
+ TileOrientation::Vertical => tile.dimensions.short,
+ };
+
+ for y in 0..ey {
+ for x in 0..ex {
+ let idx = (x + y * ex) * tp;
+ for i in 0..tp {
+ cells[(idx + i) as usize] = match tile.pixels[(x + y * ex) as usize] {
+ TilesetPixelType::Void => Cell::void(),
+ TilesetPixelType::Terrain => Cell::from_material(MaterialId::Dirt),
+ }
+ }
+ }
+ }
+
+ cells
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index 0dd725d..118f2a4 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -26,6 +26,7 @@ use crate::{
entity_grenade::entity_grenade_def, entity_tnt::entity_tnt_def,
},
materials::MaterialId,
+ world::mines::MinesBiome,
},
input::{
Input::{self},
@@ -147,7 +148,10 @@ impl Default for App {
vfx_manager: Some(VfxManager::new()),
sim_manager: Some(SimManager::new()),
- world_generator: TilesetWorldGenerator::new("assets/tilesets/tileset1"),
+ world_generator: TilesetWorldGenerator::new(
+ "assets/tilesets/tileset1",
+ Box::new(MinesBiome),
+ ),
last_render: Instant::now(),
diff --git a/src/proc_gen/herringbone.rs b/src/proc_gen/herringbone.rs
index 5e930ec..271b7a1 100644
--- a/src/proc_gen/herringbone.rs
+++ b/src/proc_gen/herringbone.rs
@@ -3,12 +3,10 @@ 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) {
+pub 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);
@@ -74,10 +72,40 @@ fn get_pixel_at_position(world: IVec2, tileset: &Tileset) -> TilesetPixelType {
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),
- }
+pub fn tiles_overlapping(
+ a: IVec2,
+ b: IVec2,
+ tileset: &Tileset,
+) -> impl Iterator<Item = (IVec2, &Tile, TileOrientation)> {
+ let s = IVec2::new(
+ tileset.dimensions.short as i32,
+ tileset.dimensions.short as i32,
+ );
+
+ let ta = a.div_euclid(s) - 1;
+ let tb = (b - 1).div_euclid(s);
+
+ (ta.y..=tb.y)
+ .flat_map(move |ty| (ta.x..=tb.x).map(move |tx| (tx, ty)))
+ .filter_map(move |(tx, ty)| match (tx - ty).rem_euclid(4) {
+ 0 => Some((
+ IVec2::new(tx, ty),
+ pick_variant(IVec2::new(tx, ty), TileOrientation::Horizontal, tileset),
+ TileOrientation::Horizontal,
+ )),
+ 3 => Some((
+ IVec2::new(tx, ty),
+ pick_variant(IVec2::new(tx, ty), TileOrientation::Vertical, tileset),
+ TileOrientation::Vertical,
+ )),
+ _ => None,
+ })
}
+
+// 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),
+// }
+// }
diff --git a/src/proc_gen/mod.rs b/src/proc_gen/mod.rs
index 7913d22..049ad1a 100644
--- a/src/proc_gen/mod.rs
+++ b/src/proc_gen/mod.rs
@@ -4,34 +4,68 @@ pub mod tileset_loader;
use glam::IVec2;
use crate::{
- config::CHUNK_SIZE,
+ config::{CHUNK_SIZE, TILESET_SCALING},
proc_gen::{
- herringbone::get_cell_at_position,
- tileset_loader::{Tileset, load_tileset},
+ herringbone::tiles_overlapping,
+ tileset_loader::{Tile, TileOrientation, Tileset, load_tileset},
},
- sim::cell_manager::chunk::Chunk,
+ sim::{cell::Cell, cell_manager::chunk::Chunk, entity::EntityDef},
};
+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> {
+ Vec::new()
+ }
+}
+
pub struct TilesetWorldGenerator {
tileset: Tileset,
+ biome: Box<dyn Biome>,
}
impl TilesetWorldGenerator {
pub fn generate_chunk(&self, chunk_position: IVec2) -> Chunk {
let mut chunk = Chunk::void();
- for x in 0..CHUNK_SIZE {
- for y in 0..CHUNK_SIZE {
- let cell = get_cell_at_position(
- chunk_position * CHUNK_SIZE + IVec2::new(x, y),
- &self.tileset,
- );
- chunk.set_cell_at_local_position(x as u8, y as u8, cell);
+
+ 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));
+
+ 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 {
+ continue;
+ }
+
+ 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];
+ }
}
}
+
chunk
}
- pub fn new(tileset_path: &str) -> Self {
+
+ pub fn new(tileset_path: &str, biome: Box<dyn Biome>) -> Self {
let tileset = load_tileset(tileset_path);
- TilesetWorldGenerator { tileset }
+ TilesetWorldGenerator { tileset, biome }
}
}
diff --git a/src/proc_gen/tileset_loader.rs b/src/proc_gen/tileset_loader.rs
index 925b3ac..acb4d65 100644
--- a/src/proc_gen/tileset_loader.rs
+++ b/src/proc_gen/tileset_loader.rs
@@ -26,8 +26,8 @@ fn load_img(path: &Path) -> Result<(Vec<u8>, u32, u32), Box<dyn Error>> {
Ok((buf, info.width, info.height))
}
-#[derive(Deserialize, Debug)]
-pub struct TilesetDimensions {
+#[derive(Deserialize, Clone, Copy, Debug)]
+pub struct TileDimensions {
pub short: u32,
pub long: u32,
}
@@ -40,7 +40,7 @@ pub enum TilesetPixelType {
#[derive(Deserialize, Debug)]
struct TilesetManifest {
- dimensions: TilesetDimensions,
+ dimensions: TileDimensions,
palette: HashMap<u8, TilesetPixelType>,
}
@@ -50,12 +50,14 @@ fn load_manifest(path: &Path) -> Result<TilesetManifest, Box<dyn Error>> {
#[derive(Debug)]
pub struct Tile {
+ pub orientation: TileOrientation,
+ pub dimensions: TileDimensions,
pub pixels: Vec<TilesetPixelType>,
}
#[derive(Debug)]
pub struct Tileset {
- pub dimensions: TilesetDimensions,
+ pub dimensions: TileDimensions,
pub vertical_tiles: Vec<Tile>,
pub horizontal_tiles: Vec<Tile>,
}
@@ -115,6 +117,8 @@ fn parse_row(
);
tiles.push(Tile {
+ orientation,
+ dimensions: manifest.dimensions,
pixels: tile_pixels,
});