aboutsummaryrefslogtreecommitdiff
path: root/src/sandbox.cpp
blob: f71be9b8b2f2987f6cb5dc019d3122dce652bcb0 (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
#include "sandbox.hpp"
#include "common.hpp"

#include <utility>

// Copied from IM_COL32
#define COL_U32(r, g, b, a) (((uint32_t)(A) << IM_COL32_A_SHIFT) | ((uint32_t)(B) << IM_COL32_B_SHIFT) | ((uint32_t)(G) << IM_COL32_G_SHIFT) | ((uint32_t)(R) << IM_COL32_R_SHIFT))

static constexpr uint32_t MAT_COLOR_LUT[] = {
    0xffffff'ff, // AIR
    0xababab'ff, // SOLID
    0xfffca8'ff, // SAND
    0x435bf7'ff, // WATER
};

uint32_t Tile::get_color() const {
    return MAT_COLOR_LUT[std::to_underlying(mat)];
}

Sandbox::Sandbox(int w, int h)
    : _bitmap(w * h)
    , _a(w * h)
    // TODO random seed
    , _pcg()
    , _solid_tile{ Tile::SOLID }
    , width{ w }
    , height{ h } //
{
}

static void simulate_sand_tile(Sandbox& self, int x, int y) {
    auto& at0 = self.gs(x, y);
    switch (at0.mat) {
    case Tile::AIR: break;

    case Tile::SOLID: break;

    case Tile::SAND: {
        auto& below = self.gs(x, y - 1);
        if (below.mat == Tile::AIR) {
            below = at0;
            below.updated = true;
            at0 = {};
            at0.updated = true;
        } else if (below.mat == Tile::WATER) {
            Pt neighs[]{ Pt(x - 1, y), Pt(x + 1, y), Pt(x, y + 1), Pt(x, y - 1) };
            int max_pressure = 0;
            for (auto [x1, y1] : neighs) {
                auto& neigh = self.gs(x1, y1);
                if (neigh.mat == Tile::WATER) {
                    auto p = neigh.pressure;
                    max_pressure = max_pressure > p ? max_pressure : p;
                }
            }
        } else {
            // Try going to a side
            // TODO
        }
    } break;

    case Tile::WATER: {
        // TODO pressure system
    } break;
    }
}

void Sandbox::simulate_step() {
    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            simulate_sand_tile(*this, x, y);
        }
    }
    ++ncycle;
}

Tile& Sandbox::gs(int x, int y) {
    if (x < 0 || x >= width || y < 0 || y >= height)
        return _solid_tile;
    return _a[y * width + x];
}

void Sandbox::set_sand(int x, int y, Tile sand) {
    _a[y * width + x] = std::move(sand);
    _bitmap[y * width + x] = sand.get_color();
}

// std::vector<uint32_t> Sandbox::to_bitmap() const {
//     // TODO
// }