#include "sandbox.hpp" #include "common.hpp" #include #include // 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, 10, 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 = _y = 0; for (; _y < height; ++_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 Sandbox::to_bitmap() const { // // TODO // }