← Back to Projects
PropBet cover
Web Game · Crash

PropBet

A real-time crash game. A plane climbs up a multiplier curve, and you need to cash out before it flies away.

Role
  • Developer
  • Vibe coder
Genre
  • Crash game
  • cash-out
House edge
  • 3%
  • 97% RTP
Stack
  • Next.js
  • TypeScript
  • Canvas
Fairness
Block-seeded mulberry32
Platform
  • Browser
  • Game Engine arcade

01The Game

PropBet is a crash game that runs in the browser. A plane takes off and climbs along a multiplier curve that gets steeper and steeper, and it can crash at any moment. You can place up to two bets each round, and the goal is to cash out before the plane flies off.

On the surface, a crash game is just one number going up. But everything important happens in the final frame before it stops. The curve has to climb smoothly at 60fps, the crash point has to be fair and stay hidden until it happens, and when you cash out you need to get exactly the multiplier that was showing on the frame you tapped.

Sealed at take-off

The crash point is decided once, at the start of the round, and the game loop simply reveals it when the time comes.

Frame-exact cash-outs

Whether you cash out by hand or set an automatic target, you’re paid the multiplier from that exact frame.

A cockpit HUD

A huge live multiplier, a neon curve and a colour-coded history bar that you can understand at a glance.

02Screenshots

These screenshots were captured straight from the game. Tap any of them to see it bigger.

03Core Loop

  1. 1

    Bet

    Place up to two bets, and set automatic cash-out targets if you want them.

  2. 2

    Take off

    The crash point is worked out from the round’s seed and locked in before the plane takes off.

  3. 3

    Climb

    The multiplier grows following e^(0.1·t), which means it hits 2× at about 7 seconds and 10× at about 23 seconds.

  4. 4

    Cash out

    Tap to cash out, or let your automatic target do it for you. Each bet panel is settled separately.

  5. 5

    Crash

    The plane flies away, any bets still open are lost, and the result is added to the history bar.

04Key Features

Dual bet panels

You can run two bets at once. For example, you might cash one out early at 2× to play it safe and let the other one ride for 20×. You can also queue bets up for the next round.

Auto cash-out

Set a target for each panel, and the game cashes out the moment the curve passes it.

Crash-history rail

A bar showing recent results, coloured from low to high. It’s the only record of past rounds shown on screen.

Simulated participants

A list of other players cashing out helps every round feel live and busy.

Synthesised sound

Every sound effect is generated with WebAudio, so there are no audio files at all. Everything runs through one master volume control, which handles muting and volume.

Canvas effects

A camera that follows the plane’s altitude, layered skies that move at different speeds, exhaust particles and a 16-frame explosion animation.

05The Maths

It uses the standard crash distribution that most crash games use, with the house edge built right into it. That means the expected return is the same no matter what target a player chooses.

Crash distribution

The chance of the plane reaching at least x is (1 − edge) / x, using a 3% edge, with a cap of 5,000×. About 3% of rounds crash immediately at 1.00×.

Multiplier growth

The multiplier follows m(t) = e^(0.1·t). It climbs smoothly, speeds up over time and behaves identically on every device.

Why every target returns 97%

If you cash out at x, you get paid x, and the chance of getting there is 0.97 / x. Multiply those together and the expected return is always 0.97, whatever target you pick. The only thing that changes is how much the results swing around.

Seeded rounds

Each round is seeded by a number taken from a blockchain block (through /api/crash-seed), combined with a counter that only ever goes up. These seed a mulberry32 random generator, and its first number sets the crash point. If the service is down, the game falls back to Math.random and flags that it did.

06Under the Hood

Canvas and refs

Game.tsx draws the canvas and the bet panels once. The whole simulation lives in refs on a requestAnimationFrame loop, and React state only gets updated a few times a second.

Pure engine

engine.ts holds the crash maths, the growth curve, the timing for each phase and the limits. The random generator is passed in from outside, so the engine can be tested on its own.

Virtual clock

Pausing uses a virtual clock, so time doesn’t suddenly jump forward when you resume.

No stale closures

Cash-outs read the live multiplier from refs rather than from a React value that’s one frame old. Without that, a tap at 8.4× could end up paying the wrong amount.

07Challenges & Solutions

ChallengeUsing setInterval and React state made the curve jittery, and cash-outs were being paid on an out-of-date multiplier.
SolutionI switched to a requestAnimationFrame loop that works with refs, and bets are settled on the exact frame where the condition is met.
ChallengeIf the crash were decided partway through the flight, the outcome would depend on timing.
SolutionThe crash point is locked in at take-off. On each frame, the game only checks whether the multiplier has reached it yet.
ChallengeBuilding a loop where timing matters this much using vibe coding.
SolutionI wrote out the state machine, the crash distribution, the curve and the cash-out rules on paper before writing a single prompt, then checked each part against that plan as it was built.

08Results & Takeaways

97%
return to player at any target
60 FPS
canvas render loop
5,000×
maximum multiplier
Next.jsReactTypeScriptHTML5 CanvasWebAudiomulberry32Vibe coding
  • A finished crash game with two bet panels, automatic cash-outs for each, a history bar, other players, sound effects and 50,000 demo credits to play with.
  • Rounds are seeded from blockchain blocks and can be reproduced, and the house edge sits inside the crash distribution itself.
  • Next up: a "verify" link in the game for each round’s block, saved progress between sessions, and real multiplayer instead of simulated players.

What I learned

  • When you’re building a real-time game in React, running the loop yourself over refs is the right approach.
  • When the timing really matters, vibe coding only works if you’ve designed things properly first.