169 lines
5.6 KiB
C#
169 lines
5.6 KiB
C#
using Raylib_cs;
|
|
using Sand.ChunkPrototype;
|
|
|
|
const int screenWidth = 1280;
|
|
const int screenHeight = 800;
|
|
const int sidebarWidth = 220;
|
|
const int particleSize = 4;
|
|
const int simWidth = (screenWidth - sidebarWidth) / particleSize;
|
|
const int simHeight = screenHeight / particleSize;
|
|
const int brushRadius = 3;
|
|
|
|
var adapter = new PrototypeSparseSandAdapter(simWidth, simHeight);
|
|
var accumulator = 0f;
|
|
var fixedStep = 1f / 60f;
|
|
var stepCounter = 0;
|
|
var currentParticle = PrototypeParticleType.Sand;
|
|
var frameBuffer = new byte[simWidth * simHeight * 4];
|
|
|
|
Raylib.SetConfigFlags(ConfigFlags.ResizableWindow);
|
|
Raylib.InitWindow(screenWidth, screenHeight, "Sand Chunk Prototype");
|
|
Raylib.SetTargetFPS(120);
|
|
var frameImage = Raylib.GenImageColor(simWidth, simHeight, Color.Black);
|
|
var frameTexture = Raylib.LoadTextureFromImage(frameImage);
|
|
Raylib.UnloadImage(frameImage);
|
|
|
|
while (!Raylib.WindowShouldClose())
|
|
{
|
|
var dt = Raylib.GetFrameTime();
|
|
var mouse = Raylib.GetMousePosition();
|
|
var simMouseX = Math.Clamp((int)((mouse.X - sidebarWidth) / particleSize), 0, simWidth - 1);
|
|
var simMouseY = Math.Clamp((int)(mouse.Y / particleSize), 0, simHeight - 1);
|
|
var overWorld = mouse.X >= sidebarWidth;
|
|
|
|
if (Raylib.IsKeyPressed(KeyboardKey.C))
|
|
{
|
|
adapter = new PrototypeSparseSandAdapter(simWidth, simHeight);
|
|
accumulator = 0f;
|
|
stepCounter = 0;
|
|
}
|
|
|
|
if (Raylib.IsKeyPressed(KeyboardKey.One))
|
|
{
|
|
currentParticle = PrototypeParticleType.Sand;
|
|
}
|
|
|
|
if (Raylib.IsKeyPressed(KeyboardKey.Two))
|
|
{
|
|
currentParticle = PrototypeParticleType.Water;
|
|
}
|
|
|
|
if (Raylib.IsKeyPressed(KeyboardKey.Three))
|
|
{
|
|
currentParticle = PrototypeParticleType.Steam;
|
|
}
|
|
|
|
if (Raylib.IsKeyPressed(KeyboardKey.Four))
|
|
{
|
|
currentParticle = PrototypeParticleType.Wall;
|
|
}
|
|
|
|
if (Raylib.IsMouseButtonDown(MouseButton.Left) && overWorld)
|
|
{
|
|
PaintCircle(adapter, simMouseX, simMouseY, brushRadius, currentParticle, add: true);
|
|
}
|
|
|
|
if (Raylib.IsMouseButtonDown(MouseButton.Right) && overWorld)
|
|
{
|
|
PaintCircle(adapter, simMouseX, simMouseY, brushRadius, currentParticle, add: false);
|
|
}
|
|
|
|
accumulator += dt;
|
|
var maxSteps = 8;
|
|
while (accumulator >= fixedStep && maxSteps-- > 0)
|
|
{
|
|
adapter.World.ClearDirtyChunks();
|
|
adapter.Step();
|
|
stepCounter++;
|
|
if ((stepCounter % 30) == 0)
|
|
{
|
|
adapter.TrimResidency(marginChunks: 1);
|
|
}
|
|
|
|
accumulator -= fixedStep;
|
|
}
|
|
|
|
if (accumulator > fixedStep * 4f)
|
|
{
|
|
accumulator = fixedStep;
|
|
}
|
|
|
|
var rgbaFrame = adapter.BuildRgbaFrame();
|
|
rgbaFrame.CopyTo(frameBuffer);
|
|
unsafe
|
|
{
|
|
fixed (byte* pixels = frameBuffer)
|
|
{
|
|
Raylib.UpdateTexture(frameTexture, pixels);
|
|
}
|
|
}
|
|
|
|
Raylib.BeginDrawing();
|
|
Raylib.ClearBackground(new Color(8, 10, 14, 255));
|
|
Raylib.DrawRectangle(0, 0, sidebarWidth, screenHeight, new Color(20, 24, 30, 255));
|
|
Raylib.DrawTextureEx(frameTexture, new System.Numerics.Vector2(sidebarWidth, 0), 0f, particleSize, Color.White);
|
|
if (overWorld)
|
|
{
|
|
Raylib.DrawCircleLines((int)mouse.X, (int)mouse.Y, brushRadius * particleSize, new Color(255, 255, 255, 180));
|
|
}
|
|
|
|
DrawPanel(adapter, currentParticle);
|
|
Raylib.EndDrawing();
|
|
}
|
|
|
|
Raylib.UnloadTexture(frameTexture);
|
|
Raylib.CloseWindow();
|
|
|
|
static void PaintCircle(PrototypeSparseSandAdapter adapter, int centerX, int centerY, int radius, PrototypeParticleType type, bool add)
|
|
{
|
|
for (var dx = -radius; dx <= radius; dx++)
|
|
{
|
|
for (var dy = -radius; dy <= radius; dy++)
|
|
{
|
|
if ((dx * dx) + (dy * dy) > radius * radius)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var x = centerX + dx;
|
|
var y = centerY + dy;
|
|
if (x < 0 || y < 0 || x >= adapter.Width || y >= adapter.Height)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (add)
|
|
{
|
|
adapter.AddParticle(x, y, type);
|
|
}
|
|
else
|
|
{
|
|
adapter.RemoveParticle(x, y);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void DrawPanel(PrototypeSparseSandAdapter adapter, PrototypeParticleType currentParticle)
|
|
{
|
|
Raylib.DrawText("Chunk Proto", 12, 14, 28, new Color(110, 172, 228, 255));
|
|
DrawParticleButton(12, 60, "1 Sand", currentParticle == PrototypeParticleType.Sand, new Color(214, 188, 96, 255));
|
|
DrawParticleButton(12, 96, "2 Water", currentParticle == PrototypeParticleType.Water, new Color(72, 132, 232, 255));
|
|
DrawParticleButton(12, 132, "3 Steam", currentParticle == PrototypeParticleType.Steam, new Color(182, 196, 214, 255));
|
|
DrawParticleButton(12, 168, "4 Wall", currentParticle == PrototypeParticleType.Wall, new Color(96, 96, 104, 255));
|
|
Raylib.DrawText($"FPS {Raylib.GetFPS()}", 12, 228, 20, Color.White);
|
|
Raylib.DrawText($"Particles {adapter.ParticleCount}", 12, 252, 20, Color.White);
|
|
Raylib.DrawText($"Loaded Chunks {adapter.World.LoadedChunkCount}", 12, 276, 20, Color.White);
|
|
Raylib.DrawText($"Active Chunks {adapter.World.ActiveChunkCount}", 12, 300, 20, Color.White);
|
|
Raylib.DrawText($"Dirty Chunks {adapter.World.DirtyChunkCount}", 12, 324, 20, Color.White);
|
|
Raylib.DrawText("LMB paint", 12, 372, 18, Color.LightGray);
|
|
Raylib.DrawText("RMB erase", 12, 394, 18, Color.LightGray);
|
|
Raylib.DrawText("C clear", 12, 416, 18, Color.LightGray);
|
|
}
|
|
|
|
static void DrawParticleButton(int x, int y, string label, bool selected, Color color)
|
|
{
|
|
Raylib.DrawRectangleRounded(new Rectangle(x, y, 188, 28), 0.2f, 6, selected ? new Color(236, 236, 242, 255) : color);
|
|
Raylib.DrawText(label, x + 10, y + 5, 18, selected ? Color.Black : Color.Black);
|
|
}
|