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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
use glam::{IVec2, Vec2};
use crate::{
config::TILESET_SCALING,
content::materials::MaterialId,
proc_gen::{
Biome, TileCells,
tileset_loader::{Tile, TilesetPixelType},
},
sim::{cell::Cell, lib::marching_squares::compute_types},
};
const FULL: [bool; (TILESET_SCALING * TILESET_SCALING) as usize] =
[true; (TILESET_SCALING * TILESET_SCALING) as usize];
const EMPTY: [bool; (TILESET_SCALING * TILESET_SCALING) as usize] =
[false; (TILESET_SCALING * TILESET_SCALING) as usize];
pub struct MinesBiome {
pixel_expansion_by_type: [[bool; (TILESET_SCALING * TILESET_SCALING) as usize]; 16],
}
fn circular_pixel_expansion(
c: Vec2,
r: f32,
) -> [bool; (TILESET_SCALING * TILESET_SCALING) as usize] {
let rs = r.powi(2);
let mut ret = [false; (TILESET_SCALING * TILESET_SCALING) as usize];
for y in 0..TILESET_SCALING {
for x in 0..TILESET_SCALING {
// definitely can be optimized a lot
let dist = Vec2::new(x as f32, y as f32).distance_squared(c);
if dist <= rs {
ret[(x + y * TILESET_SCALING) as usize] = true;
}
}
}
ret
}
impl MinesBiome {
pub fn new() -> Self {
MinesBiome {
pixel_expansion_by_type: [
// empty
EMPTY,
// BL
circular_pixel_expansion(
Vec2::new(0.0, TILESET_SCALING as f32 - 1.0),
TILESET_SCALING as f32,
),
// BR
circular_pixel_expansion(
Vec2::new(TILESET_SCALING as f32 - 1.0, TILESET_SCALING as f32 - 1.0),
TILESET_SCALING as f32,
),
// BL BR
FULL,
// TR
circular_pixel_expansion(
Vec2::new(TILESET_SCALING as f32 - 1.0, 0.0),
TILESET_SCALING as f32,
),
// TR BL
FULL,
// TR BR
FULL,
// TR BR BL
FULL,
// TL
circular_pixel_expansion(Vec2::new(0.0, 0.0), TILESET_SCALING as f32),
// TL BL
FULL,
// TL BR
FULL,
// TL BR BL
FULL,
// TL TR
FULL,
// TL TR BL
FULL,
// TL TR BR
FULL,
// surrounded
FULL,
],
}
}
}
impl Biome for MinesBiome {
fn derive_world_from_tile(&self, tile: &Tile) -> TileCells {
let pixels = tile.size();
let marched_pixels = compute_types(tile);
let size = pixels * TILESET_SCALING;
let mut cells = vec![Cell::void(); (size.x * size.y) as usize];
for py in 0..pixels.y {
for px in 0..pixels.x {
let variant = marched_pixels[(px + py * (pixels.x + 1)) as usize];
let expansion = self.pixel_expansion_by_type[variant as usize];
// TODO optimize
let expansion_cells = expansion.map(|c| {
if c {
Cell::from_material(MaterialId::Dirt)
} else {
Cell::void()
}
});
let origin = IVec2::new(px, py) * TILESET_SCALING;
for i in 0..TILESET_SCALING {
let dst_y = i + origin.y;
let dst_row = (dst_y * size.x + origin.x) as usize;
let src_row = (i * TILESET_SCALING) as usize;
cells[dst_row..dst_row + TILESET_SCALING as usize].copy_from_slice(
&expansion_cells[src_row..src_row + TILESET_SCALING as usize],
);
}
}
}
TileCells { size, cells }
}
}
|