8-Ball Pool: Real Physics, Not a Convincing Fake
Spin transfer, rail bounces, and ghost-ball AI targeting — why this one runs on an actual simulation instead of scripted shot animations.
I could have built pool the easy way — scripted ball paths, canned animations for common shots, something that looks convincing without actually simulating anything. I didn't, because pool is a game people already know intimately from real tables, and a version that fakes physics is the kind of thing an experienced player notices within their first three shots. This runs on real 2D physics: actual collision response between balls, actual spin transfer, actual rail bounces. It's a genuine simulation, not a convincing illusion of one.
Spin is where the simulation had to earn its keep
Straight-line collisions are the easy 80% of pool physics — two circles colliding, momentum transferring along the line between their centers, fairly standard stuff. Spin is the part that separates a real simulation from a shallow one. Topspin needs to keep the cue ball rolling forward after contact instead of stopping dead. Backspin needs to pull it backward. Side english needs to curve its path off a rail at a different angle than a spinless shot would produce. All of that requires tracking angular momentum on the cue ball as its own real quantity, separate from its linear velocity, and correctly transferring the right portion of it at the moment of collision or rail contact. Get that wrong and the spin pad becomes a cosmetic control that doesn't actually change outcomes, which would have undermined the entire reason to simulate real physics in the first place.
Charging power needed to feel different from aiming
Aiming is cursor movement — continuous, precise, immediate. Power is a separate click-and-hold charge-up before release, and keeping those two interactions distinct rather than combining them into one gesture was deliberate. Aiming and power are different decisions with different ideal input types: aiming benefits from being able to endlessly adjust before committing, while power benefits from a clear, deliberate commitment moment. Blending them into a single drag gesture — like pulling back further to add more power the way some pool games do — would make it harder to separately perfect each half of the shot. I wanted a player to be able to lock in a perfect angle, then separately and deliberately decide how hard to hit it, without one adjustment accidentally disturbing the other.
Ghost-ball targeting for the AI, on purpose
The AI opponent uses ghost-ball targeting — a classic, well-understood method where you aim at the point a cue ball's center would need to occupy at the moment of contact to send the object ball toward its pocket. I picked it specifically because it's a real technique real players actually use and can learn to read, rather than some opaque, unexplainable evaluation function. Watching where the AI's ghost-ball point lands before it takes a shot is something an attentive player can learn to anticipate, which turns the AI into something you can study and get better against, rather than a black box that just produces outcomes. A more advanced targeting system might make marginally better shot choices, but it would also stop being something a human opponent could learn to read and predict.
Rail bounces are where small errors compound fast
A ball bouncing off a rail has to reflect at an angle that respects both its incoming velocity and whatever spin it's carrying, and small errors in that calculation compound badly over a shot with multiple bounces. A single-bounce shot can absorb a tiny angle error without anyone noticing. A bank shot intended to clip two rails before reaching a pocket makes that same small error obvious, because it gets amplified at every subsequent bounce. I ended up testing rail response specifically against multi-bounce combination shots rather than simple single-rail bank shots, since that's where an inaccurate reflection angle actually becomes visible and frustrating rather than a rounding error nobody would ever notice.
Where the simulation still isn't perfect
I'll be honest that this isn't a tournament-accurate physics model — real pool involves subtleties like squirt and swerve on heavily spun shots that this simulation doesn't fully capture, and cushion response isn't modeled with the same precision a physical table's rail rubber actually has. What it does model correctly is enough to make the fundamentals — angle, power, spin, rail banking — behave the way they should for someone using this to actually practice pool sense, not just click toward pockets. Chasing full simulation accuracy past that point would have been a much larger project for a level of realism that most players clicking into a browser pool game wouldn't actually notice or need.
This is also the first game on the site built to support both a solo session against the AI and a local two-player game on the same device, from the same codebase, rather than maintaining two separate rule implementations. The physics and rule validation don't care who's taking the shot — only the turn-management layer on top needs to know whether the next input is coming from a person or from the AI's own targeting logic. Keeping that boundary clean meant the AI opponent is really just another player working through the same shot interface everyone else uses, not a special-cased shortcut bolted on separately. It's a cleaner architecture, and it also means any future improvement to the AI's decision-making automatically plays through the exact same physics everyone else's shots do, with no separate code path that could quietly drift out of sync with the real rules over time. If the AI ever needs to get smarter, it gets smarter by making better decisions through the same interface, not by cheating with information or precision a human opponent doesn't also have access to. That constraint is a feature, not a limitation — the day this AI stops feeling beatable in a fair, learnable way is the day it's stopped being fun to play against. A pool game that's technically unbeatable isn't a better pool game, it's just a worse reason to keep opening it.
More from the Devlog