Skip to content

thinisde/multi-sand-sim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Multi-User Sand Simulation

Monorepo with three apps:

  • backend/: Elixir + Phoenix channels authoritative simulation server.
  • frontend/: SvelteKit + Tailwind client.
  • physics_engine/: Rust + wasm-pack + wgpu client renderer.

All clients join one fixed Phoenix topic: "global".

Screen.Recording.2026-02-28.at.01.03.30.mov

Requirements

  • Elixir 1.19+ and Erlang/OTP 28+
  • Node 20+
  • pnpm
  • Rust stable
  • wasm-pack

Run

  1. Backend
cd backend
mix setup && mix phx.server
  1. Frontend
cd frontend
pnpm install && pnpm dev
  1. WASM build (manual)
cd physics_engine
wasm-pack build --target web --release --out-dir ../frontend/static/wasm --out-name physics_engine

WASM helper script:

./scripts/rebuild-wasm.sh

Environment

Use a single root env file:

  • .env (repo root)

Backend automatically loads this file in config/runtime.exs. You can still override any value from the shell before starting.

cd backend
mix phx.server

Frontend is wired with envDir: '..', so it reads the same root .env.

Protocol

Topic:

  • global

Client -> server:

  • brush: { id, userId, x, y, add, radius, t }
  • reset: { id }

Server -> clients:

  • brush: immediate broadcast of received brush events
  • reset: { type: "reset", id, userId, tick }
  • snapshot: %{type: "snapshot", w: 800, h: 600, bytesB64: "...", tick: tick_count}
    • bytesB64 is Base64(gzip(raw_grid_bytes))

Authoritative Sim

  • Grid: 800x600, bytes 0 or 255
  • Global state owner: Backend.GlobalSim GenServer
  • Tick: 60Hz
  • Per tick:
    1. apply queued brush events
    2. vertical fall pass
    3. diagonal pass (dx = +1 or -1)
    4. opposite diagonal pass
  • Diagonal direction order alternates each tick.
  • Snapshot broadcast interval: every ~2 seconds.

Notes

  • The server is authoritative; clients render locally for responsiveness.
  • On snapshot receipt, frontend decodes + gunzips and calls eng.import_state(bytes).
  • Reset clears authoritative state and broadcasts reset + snapshot.

About

It is a extension to sand simulator but for multi-player

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors