sand/src/main.cpp
2026-05-04 12:16:16 -04:00

210 lines
5.3 KiB
C++

#include <SDL3/SDL.h>
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_mouse.h>
#include <SDL3/SDL_oldnames.h>
#include <SDL3/SDL_surface.h>
#include <SDL3/SDL_timer.h>
#include <SDL3/SDL_video.h>
#include <sand/sand.h>
#ifdef TRACY_ENABLE
#include <tracy/Tracy.hpp>
#endif
constexpr uint16_t WIDTH = 64;
constexpr uint16_t HEIGHT = 64;
constexpr int WINDOW_WIDTH = 1024;
constexpr int WINDOW_HEIGHT = 1024;
struct color
{
uint8_t r, g, b;
};
int main(int argc, char** argv)
{
auto tb = sand::type::builder();
auto air = tb.assign();
auto sand1 = tb.assign();
auto sand2 = tb.assign();
auto sand3 = tb.assign();
tb.set_default_conversion(sand1, sand2);
tb.set_default_conversion(sand2, sand1);
auto rb = tb.build();
rb.add_rule(air, sand2).top([=](auto t) { return t == sand1; });
rb.add_rule(air, sand1).top([=](auto t) { return t == sand2; });
rb.add_rule(sand1, air).bottom([=](auto t) { return t == air; });
rb.add_rule(sand2, air).bottom([=](auto t) { return t == air; });
rb.add_rule(air, sand1)
.top_right([=](auto t) { return t == sand2; })
.right([=](auto t) { return t != air; })
.top_left([=](auto t) { return t != sand1; });
rb.add_rule(air, sand2)
.top_left([=](auto t) { return t == sand1; })
.left([=](auto t) { return t != air; })
.top_right([=](auto t) { return t != sand2; });
rb.add_rule(air, sand1)
.top_right([=](auto t) { return t == sand2; })
.right([=](auto t) { return t != air; })
.left([=](auto t) { return t == air; })
.top([=](auto t) { return t == air; });
rb.add_rule(air, sand2)
.top_left([=](auto t) { return t == sand1; })
.left([=](auto t) { return t != air; })
.right([=](auto t) { return t == air; })
.top([=](auto t) { return t == air; });
rb.add_rule(air, sand3)
.top_right([=](auto t) { return t == sand2; })
.right([=](auto t) { return t != air; })
.top_left([=](auto t) { return t == sand1; })
.left([=](auto t) { return t != air; })
.top([=](auto t) { return t == air; });
rb.add_rule(sand3, sand1).top([=](auto t) { return t == air; });
rb.add_rule(air, sand1)
.bottom([=](auto t) { return t == sand3; })
.top([=](auto t) { return t != sand1 && t != sand2; });
rb.add_rule(air, sand3)
.bottom([=](auto t) { return t == sand3; })
.top([=](auto t) { return t == sand1 || t == sand2; });
rb.add_rule(sand1, air)
.bottom_right([=](auto t) { return t == air; })
.bottom([=](auto t) { return t != air; })
.right([=](auto t) { return t == air; });
rb.add_rule(sand2, air)
.bottom_left([=](auto t) { return t == air; })
.bottom([=](auto t) { return t != air; })
.left([=](auto t) { return t == air; });
rb.add_rule(sand1, sand3).bottom([=](auto t) { return t == sand3; });
rb.add_rule(sand2, sand3).bottom([=](auto t) { return t == sand3; });
rb.add_rule(sand3, sand1)
.top([=](auto t) { return t == sand1 || t == sand2; });
auto s = rb.build(WIDTH, HEIGHT, air);
const auto& cf = [=](sand::type t) -> color
{
if (t == air)
{
return { 0x40, 0x60, 0x80 };
}
else if (t == sand1 || t == sand2 || t == sand3)
{
return { 0xB0, 0x90, 0x50 };
}
else
{
return { 0, 0, 0 };
}
};
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window
= SDL_CreateWindow("sand test", WINDOW_WIDTH, WINDOW_HEIGHT, 0);
SDL_Surface* surface
= SDL_CreateSurface(WIDTH, HEIGHT, SDL_PIXELFORMAT_RGB24);
int prev_ms = SDL_GetTicks();
float time = 0;
bool cont = true;
int prev_count = 0;
while (cont)
{
SDL_Event e;
while (SDL_PollEvent(&e))
{
if (e.type == SDL_EVENT_QUIT)
{
cont = false;
}
}
int ms = SDL_GetTicks();
float dt = (ms - prev_ms) / 1000.0f;
prev_ms = ms;
time += dt;
float x, y;
int state;
if (time > 0)
{
time = 0;
s.tick();
int count = 0;
for (int i = 0; i < WIDTH; i++)
{
for (int j = 0; j < HEIGHT; j++)
{
if (s.get(i, j) == sand1 || s.get(i, j) == sand2)
{
count += 1;
}
else if (s.get(i, j) == sand3)
{
count += 2;
}
}
}
if (count != prev_count)
{
SDL_Log("%d\n", count);
}
prev_count = count;
}
if ((state = SDL_GetMouseState(&x, &y)))
{
int ix = x * WIDTH / WINDOW_WIDTH;
int iy = y * HEIGHT / WINDOW_HEIGHT;
if (ix >= 0 && ix < WIDTH && iy >= 0 && iy < HEIGHT)
{
if (state == SDL_BUTTON_LEFT)
{
s.set(ix, iy, sand1);
}
else
{
s.set(ix, iy, sand3);
}
}
}
SDL_LockSurface(surface);
for (int i = 0; i < WIDTH; i++)
{
for (int j = 0; j < HEIGHT; j++)
{
color c = cf(s.get(i, j));
static_cast<uint8_t*>(surface->pixels)[3 * (i + j * WIDTH) + 0] = c.r;
static_cast<uint8_t*>(surface->pixels)[3 * (i + j * WIDTH) + 1] = c.g;
static_cast<uint8_t*>(surface->pixels)[3 * (i + j * WIDTH) + 2] = c.b;
}
}
SDL_UnlockSurface(surface);
SDL_BlitSurfaceScaled(surface, nullptr, SDL_GetWindowSurface(window),
nullptr, SDL_SCALEMODE_NEAREST);
SDL_UpdateWindowSurface(window);
FrameMark;
}
SDL_DestroySurface(surface);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}