Cryptographic Fairness in a WebGL 3D Coin Flip
When you flip a physical coin, physics determines the outcome: the force of the thumb, the air resistance, the bounce on the table. When you flip a digital coin, code decides. But how do you make a 3D web experience feel realistic while guaranteeing statistical fairness?
Math.random() vs Crypto.getRandomValues()
The most common way to generate random numbers in JavaScript is Math.random(). It's fast and easy, but it is a pseudo-random number generator (PRNG). For casual games, it's fine. But if you are building a tool to settle disputes or split bills, users need to know it's fair.
For the Coin Flip experiment on vishva.lol, I bypassed Math.random() for the actual outcome and used the Web Crypto API instead.
function flipUnbiased(): 'heads' | 'tails' {
const arr = new Uint8Array(1);
crypto.getRandomValues(arr);
return arr[0] % 2 === 0 ? 'heads' : 'tails';
}This method uses the operating system's cryptographic random source, ensuring a truly unbiased 50/50 distribution over thousands of flips.
Decoupling Physics from the Outcome
Here is the trick of the 3D coin flip: the physics engine does not decide the result. The instant you release the "Flip" button, the Web Crypto API determines if it will be heads or tails.
We use React Three Fiber (a React wrapper for Three.js) to render the 3D coin. We calculate a pre-determined animation path. If the outcome is 'heads', we ensure the coin spins an even number of times (or lands face up). If it's 'tails', we add an extra half-rotation to the animation.
The user controls the "power" by holding down the button to charge a meter. This power value influences how high the coin goes (the apex), how many total spins it completes, and the camera shake on impact, but it never influences the 50/50 cryptographic draw.
Procedural Audio Impacts
A flip isn't satisfying without a good "clink" when it lands. Instead of just playing a static MP3, the app uses the Web Audio API to synthesize procedurally generated metallic pings.
By creating oscillators at specific inharmonic frequencies (the way metal resonates) and applying rapid decay envelopes, the coin "sounds" different depending on how hard it was flipped. A charged flip has a louder, sharper impact with a longer reverberation, while a soft flip gives a duller thud.
Conclusion
Digital toys work best when they combine mathematical precision with aesthetic flair. The 3D Coin Flip is a simple utility, but by utilizing cryptographically secure randomness, WebGL, and procedural audio, it elevates a mundane decision-making process into an experience.