flan/sand.fln

142 lines
3.3 KiB
Plaintext

import rl "vendor:raylib"
import agent "vendor:agent"
import edn "vendor:edn"
const screen-width = 900
const screen-height = 600
const cell-size = 5
const rows = screen-height / cell-size
const cols = screen-width / cell-size
const brush-size = 10
fn dyn->f64(v: f64) -> f64 = v
fn dyn->u32(v: i64) -> u32 = u32(v)
let gravity = 0.05
let colors =
let v = vec-new(dyn)
push(v, 0xFFF00FFF)
push(v, 0x3B6E8CFF)
push(v, 0xA83232FF)
push(v, 0xCC6B1FFF)
v
once grid: [rows [cols u32]]
once velocity: [rows [cols f32]]
once current-color = 0
fn clear-grid() -> ()
grid = zeroed()
velocity = zeroed()
fn next-color() -> ()
current-color = (current-color + 1) % length(colors)
fn paint-at(row: i32, col: i32) -> ()
let half = brush-size / 2
for x in range(brush-size)
for y in range(brush-size)
let r = y + (row - half)
c = x + (col - half)
if r >= 0 and r < rows - 1 and c >= 0 and c < cols - 1 and 0 == grid[r, c] and f32(rand()) < 0.5
grid[r, c] = dyn->u32(colors[current-color])
velocity[r, c] = 1.0
fn settle(row: i32, col: i32) -> ()
let vel = f32(dyn->f64(gravity)) + velocity[row, col]
let y = min(rows - 1, row + i32(vel))
while y > row
if 0 == grid[y, col]
grid[y, col] = grid[row, col]
grid[row, col] = 0
velocity[y, col] = vel
velocity[row, col] = 0.0
return
let is-left = col > 0 and 0 == grid[y, col - 1]
is-right = col < cols - 1 and 0 == grid[y, col + 1]
if is-left or is-right
let side =
if not is-left
1
elif not is-right
-1
elif f32(rand()) < 0.5
1
else
-1
grid[y, col + side] = grid[row, col]
grid[row, col] = 0
velocity[y, col + side] = vel
velocity[row, col] = 0.0
return
y -= 1
velocity[row, col] = 0.0
fn step() -> ()
let row = rows - 2
while row >= 0
for col in range(cols)
unless(0 == grid[row, col]):
settle(row, col)
row -= 1
const fnv-offset: u64 = 0xcbf29ce484222325
const fnv-prime: u64 = 1099511628211
fn hash-grid() -> u64
let h = fnv-offset
for row in range(rows)
for col in range(cols)
let c = grid[row, col]
for b in range(4)
h = h ^^ u64(c >> u32(b * 8) && 255)
h *= fnv-prime
h
fn game-update() -> ()
if rl/is-key-pressed(:key-r)
clear-grid()
if rl/is-mouse-button-down(:mouse-left)
let m = rl/get-mouse-position()
paint-at(i32(m.y) / cell-size, i32(m.x) / cell-size)
if rl/is-mouse-button-released(:mouse-left)
next-color()
step()
fn game-draw() -> ()
rl/clear-background(rl/black)
for row in range(rows)
for col in range(cols)
let c = grid[row, col]
unless(0 == c):
rl/draw-rectangle(i32(col * cell-size), i32(row * cell-size), cell-size,
cell-size, rl/get-color(c))
rl/draw-fps(20, 20)
once frame: Allocator = arena-new(262144)
let game-data =
handler-case
edn/read-file("game-data.edn")
on FileError(c)
nil
fn main() -> ()
rl/set-trace-log-level(:log-warning)
rl/init-window(screen-width, screen-height, "SAND")
defer rl/close-window()
rl/set-target-fps(120)
agent/start("/tmp/flan-sand.sock")
until rl/window-should-close()
restart-case
agent/poll()
game-update()
restart continue()
()
rl/with-drawing:
game-draw()