Inspiration

Most mobile games reset when you leave. Reddit doesn't. A thread you commented on last night grows overnight — people replied, argued, built on what you left. We wanted a game with that exact property, so we started from one sentence and refused to let go of it:

The board remembers everyone.

The mechanical inspiration is curling and shuffleboard; the social inspiration is Reddit itself.

What it does

Knockit is asynchronous multiplayer curling for a subreddit. Every day there is one shared physics board, resetting at midnight Central. You get three stones — four if you're on a 3-day streak. Drag, release, and your stone slides with real physics, knocking other players' stones as it goes.

Scoring has two layers:

  • Live score — the ring value of your stones right now (gold 3 · middle 2 · outer 1). Other players can take it from you.
  • Banked score — accrues for every hour your stones survive in the rings, and it's permanent: a knockout stops the clock but never robs the bank. Camping is worthless; surviving is everything.

Then the hook: knock someone's stone out of the rings and they get a revenge shot with your name on it. Knock out your own attacker with that shot and the game crowns it — REVENGE SERVED — with a bonus banked on top.

The board is alive while you watch: presence shows who's on the rink, other players' shots replay on your screen as they happen, every stone is tappable ("u/whoever · 2 pts · surviving 3h 12m"), and at midnight the day settles — champions posted to the subreddit, a fresh board spawned, seven layouts rotating through the week.

How we built it

Fun first, backend second. Milestone 1 was a deliberately throwaway, client-only Phaser prototype with one job: prove that flicking a stone into a cluster feels satisfying. It did — chain reactions sold it — so we kept the feel and inverted the architecture.

In the shipped game the client never simulates a shot. It sends only $(\theta, p)$ — launch angle and drag distance. The server clamps power into a velocity,

$$v = \min(p \cdot k,\; v_{max})$$

rebuilds the entire board from Redis, runs a headless Matter.js simulation, banks survival accrual, detects knockouts, grants revenge, persists, and returns the trajectory — the client just plays back frames. One source of truth; zero client-side cheating surface.

Concurrency without websockets: simultaneous shots serialize through a per-board Redis lock (15s TTL) with jittered client retry — players never see the collision. A daily scheduler settles the closing day idempotently, rolls scores into the all-time board, posts numbered results threads, and creates the next day's post automatically.

Stack: Devvit Web · Phaser 4 · Matter.js (headless server-side) · Hono · Redis.

Challenges we ran into

  • Tunneling, and the fix that wasn't. Fast stones can pass through walls between physics steps. The "obvious" fix — raising Matter's positionIterations — did nothing: our headless test harness showed stones tunneling at ~120 px/step whether iterations were 6 or 20. The real fix was substepping the simulation 4× plus a server-side speed cap 6× below the tunneling threshold. Measure the failure before trusting the folk remedy.
  • A lock on an undocumented return value. The Redis SET NX types don't document what a failed acquire returns — and a distributed lock built on ambiguity is a corrupted-board bug waiting for launch day. We rebuilt on atomic INCR with a self-healing TTL, so even a crashed lock-holder can't deadlock a board.
  • Shared mutable state vs. player rage. "Someone moved my stone" is the hook and the biggest design risk: if later players could erase your reward after you log off, charm becomes rage. Two-layer scoring is the answer — your time on the board can never be stolen.
  • Platform constraints as design pressure. No websockets, no streaming, 30-second endpoint budget, no client persistence. Every constraint pushed the design somewhere cleaner.

Accomplishments that we're proud of

  • The core loop verified numerically end-to-end: in testing, one player's shot moved another player's persisted stone 261 pixels — the game's emotional hook, reproduced in code.
  • A full shot — lock, board rebuild, physics simulation, accrual banking, knockout detection, persistence — completes in ~21 ms against a 30-second budget.
  • Three real users on three devices sharing one live board, leaderboard updating as they knocked each other around.
  • We killed our own favorite assumption with data (the positionIterations non-fix) before it shipped.

What we learned

Validate the fun with a disposable prototype before writing backend. Server-authoritative design doesn't just stop cheating — it dissolves the multiplayer consistency problem: when only the server's simulation counts, stale client views become a UX detail instead of a correctness bug. Test physics claims numerically and headlessly. And milestone discipline is a feature — one milestone at a time, each gated by a real phone test.

What's next for Knockit

  • Parallel rinks — 16-player boards with sticky daily assignment, same layout everywhere: many tables, one game.
  • Community boards — a grid editor with community voting; the day's board credited to its creator in the daily post.
  • Champion flair — yesterday's #1 wears the crown in every comment they write.

The board remembers everyone.

Built With

Share this project:

Updates

Submission history