summaryrefslogtreecommitdiff
path: root/src/content/world/mines.rs
blob: 6ed445183f0c2cae6a973559e348bccf50002157 (plain)
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
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 pixel = tile.pixel_at(IVec2::new(px, py));
                let variant = marched_pixels[(px + py * (pixels.x + 1)) as usize];

                // let pix = marched_pixels[(px + py * pixels.x) as usize];
                // let expansion_cells = [Cell::from_material(MaterialId::from_index(
                //     pix % MaterialId::ALL.len() as u8,
                // ));
                //     (TILESET_SCALING * TILESET_SCALING) as usize];

                // let origin = IVec2::new(px, py) * TILESET_SCALING;
                // for i in 0..TILESET_SCALING {
                //     let y = i + origin.y;
                //     let row = (y * size.x + origin.x) as usize;
                //     cells[row..row + TILESET_SCALING as usize].copy_from_slice(
                //         &expansion_cells[i as usize..i as usize + TILESET_SCALING 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 }
    }
}