#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)) // Correct byte order for this platform constexpr uint32_t bo(uint32_t n) { if (std::endian::native == std::endian::little) return std::byteswap(n); return n; } static constexpr uint32_t material_color_lut[] = { bo(0xffffff'ff), // AIR bo(0xababab'ff), // SOLID bo(0xe3dd24'ff), // SAND bo(0x435bf7'ff), // WATER }; uint32_t Tile::get_color() const { return material_color_lut[std::to_underlying(so)]; } Sandbox::Sandbox(int w, int h) : _bitmap(w * h) , _a(w * h) // TODO random seed , _rand() , _wall_tile{ Tile::ROCK } , width{ w } , height{ h } // { memset(_bitmap.data(), 0xff, _bitmap.size() * sizeof(_bitmap[0])); } 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._rand.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 = 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 // }