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
|
#include "sandbox.hpp"
#include "common.hpp"
#include <cstring>
#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(so)];
}
Sandbox::Sandbox(int w, int h)
: _bitmap(w * h)
, _a(w * h)
// TODO random seed
, _pcg()
, _wall_tile{ Tile::ROCK }
, width{ w }
, height{ h } //
{
memset(_bitmap.data(), 0xff, _bitmap.size() * sizeof(_bitmap[0]));
set_sand(10, 80, Tile{ .so = Tile::SAND });
}
static void simulate_sand_tile(Sandbox& self, int x, int y) {
const auto at0 = self.gs(x, y);
if (at0.updated) {
// Clear update bit for next cycle
self.gs(x, y).updated = false;
return;
}
switch (at0.so) {
case Tile::AIR: break;
case Tile::ROCK: break;
case Tile::SAND: {
const auto below = self.gs(x, y - 1);
if (below.so == Tile::AIR) {
self.set_sand(x, y, below);
self.set_sand(x, y - 1, at0);
} else {
Pt loc1[]{ Pt(x - 1, y - 1), Pt(x + 1, y - 1) };
auto bound = 2;
auto which = self._pcg.next_u32(bound);
for (int i = 0; i < bound; ++i) {
// Try going to a side
auto at1 = self.gs(loc1[i].x, loc1[i].y);
if (at1.so == Tile::AIR) {
self.set_sand(x, y, at1);
self.set_sand(loc1[i].x, loc1[i].y, at0);
}
which = (which + 1) % bound;
}
}
} break;
}
if (at0.so == Tile::AIR)
switch (at0.fl) {
case Tile::NOTHING: break;
case 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.fl == Tile::WATER) {
// auto p = neigh.fmass;
// max_pressure = max_pressure > p ? max_pressure : p;
// }
// }
} break;
}
}
void Sandbox::simulate_step() {
_x = 0;
_y = height ;
for (; _y >= 0; --_y) {
for (; _x < width; ++_x) {
simulate_sand_tile(*this, _x, _y);
}
_x = 0;
}
++ncycle;
}
Tile& Sandbox::gs(int x, int y) {
if (x < 0 || x >= width || y < 0 || y >= height)
return _wall_tile;
return _a[y * width + x];
}
void Sandbox::set_sand(int x, int y, Tile sand) {
auto& target = _a[y * width + x];
target = sand;
// Set update bit if the target is after cursor
if (y < _y || x > _x)
target.updated = true;
_bitmap[y * width + x] = sand.get_color();
}
// std::vector<uint32_t> Sandbox::to_bitmap() const {
// // TODO
// }
|