1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
pub mod herringbone;
pub mod tileset_loader;
use glam::IVec2;
use crate::{
config::{CHUNK_SIZE, TILESET_SCALING},
proc_gen::{
herringbone::tiles_overlapping,
tileset_loader::{Tile, TileOrientation, Tileset, load_tileset},
},
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();
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, biome: Box<dyn Biome>) -> Self {
let tileset = load_tileset(tileset_path);
TilesetWorldGenerator { tileset, biome }
}
}
|