billiards
This is an open-source project bringing unsophisticated billiards physics written in TypeScript to the browser.
Online Demo
Demos run in all major desktop and mobile browsers and use WebGL
- Nine ball ⬀ make a break and share replay link with friends
- Three cushion billiards ⬀ the ultimate test of physics and player (average on both counts). You need the beginner mode ⬀. Try the practice mode ⬀ to drill specific shots.
- Sagu ⬀ Korean four-ball carom game. Try sagu on a 5ft table ⬀.
- Snooker ⬀ we await the first 147 submission to the leaderboard.
- 8-Ball ⬀ try it in Hi-Res mode!
- Play vs the Claw ⬀ and TheFarJaw ⬀.
- Try two player online lobby using nchan
- Try to get on the leaderboard of highest breaks hosted on Vercel.
- Inspect physics and tweak constants using diagrams.
- Set up trick shots and practice ⬀.
- Tune three cushion physics ⬀ and optimise ⬀ parameters
- Parallel parameter ⬀ tuning using Web Workers ⬀.
- Three cushion trainer and sensitivity analysis ⬀ from an excellent fork ⬀ of this project.
Features
- Backspin, sidespin and cushion bounces well modeled.
- Presentation using WebGL in any modern browser on mobile, linux, mac or windows.
- Record and playback breaks.
- Two player online mode with nchan nginx server.
- Nine ball, snooker, three cushion and Sagu billiards rules.
- Deploys to GitHub Pages, Vercel and Render with GitHub Actions.
- Runs on and was developed mostly on a potato e.g. Raspberry Pi 4.
Reference material
- Papers on ball mechanics Han 2005 with important corrections by Kiefl.
- cushions, max spin, simulation and constants 1 2 3 4 5
- 3D graphics uses three.js
- Inline LaTeX editor for equations in README.md
Key equations
Based on Han 2005 paper
surface velocity
$$\vec{v}_a = \vec{v} + (\vec{up} \times R\vec{\omega})$$
sliding motion
$$\dot{v} = -\mu g \frac{\vec{v}_a}{|\vec{v}_a|}$$
$$\dot{\omega} = -\frac{5}{2}\frac{\mu g}{R} \frac{\vec{v}_a}{|\vec{v}_a|}$$
$$\dot{\omega}_z = -\frac{5}{2}\frac{M_z}{mR^2} \text{sgn}(\omega_z)$$
rolling motion
$$\dot{v} = -\frac{5}{7}\frac{M_{xy}}{mR} \frac{\vec{up} \times \vec{\omega}}{|\vec{\omega}|}$$
$$\dot{\omega} = -\frac{5}{7}\frac{M_{xy}}{mR^2} \frac{\vec{\omega}}{|\vec{\omega}|}$$
where
$M_{xy} = \frac{7}{5\sqrt{2}} R \mu m g$ , $M_z = \frac{2}{3} \mu m g \rho$
collisions
Based on paper by Alciatore incorporating throw effect due to the small amount of friction between balls. Figures to prove consistency between the code and paper here.
For ball $a$:
$$\vec{v}_a \leftarrow \vec{v}_a + \frac{J_{\text{normal}}}{m}\hat{n} + \frac{J_{\text{tangential}}}{m}\hat{t}$$
$$\vec{\omega}_a \leftarrow \vec{\omega}_a + \frac{1}{I} (\vec{r}_a \times \vec{J}_{\text{tangential}})$$
For ball $b$:
$$\vec{v}_b \leftarrow \vec{v}_b - \frac{J_{\text{normal}}}{m}\hat{n} - \frac{J_{\text{tangential}}}{m}\hat{t}$$
$$\vec{\omega}_b \leftarrow \vec{\omega}_b + \frac{1}{I} (\vec{r}_b \times \vec{J}_{\text{tangential}})$$
Where:
The relative velocity at the point of contact is computed as:
$$\vec{v}_{\text{rel}} = (\vec{v}_a - \vec{v}_b) + \vec{r}_a \times \vec{\omega}_a - \vec{r}_b \times \vec{\omega}_b$$
$$\vec{v}_{\text{slip}} = \vec{v}_{\text{rel}} - (\vec{v}_{\text{rel}} \cdot \hat{n}) \hat{n}$$
$\vec{r}_a = -R \cdot \hat{n}$ and $\vec{r}_b = R \cdot \hat{n}$
$J_{\text{normal}} = \frac{-(1 + e)v_{\text{rel,normal}}}{(2/m)}$
$J_{\text{tangential}} = \min\left( \frac{\mu J_{\text{normal}}}{v_{\text{rel}}}, \frac{1}{7} \right)(-v_{\text{rel,tangential}})$
$\hat{n}$: normal unit vector along the line of centers.
$\hat{t}$: tangential unit vector perpendicular to $\hat{n}$.
cushion bounce
This is based on a paper by Mathavan. Many of the figures from the paper are recreated to confirm correctness.
Slip velocity at cushion contact point I
$$ ẋ_I = \dot{v_x} + \dot{\omega_y} R \sin \theta - \dot{\omega_z} R \cos \theta \qquad ẏ'_I = -\dot{v_y} \sin \theta + \dot{\omega_x} R $$
$$ \phi = \arctan\left(\frac{ẏ'_I}{ẋ_I}\right) \qquad s = \sqrt{(ẋ_I)^2 + (ẏ'_I)^2} $$
Slip velocity at table contact point C
$$ ẋ_C = \dot{v_x} - \dot{\omega_y} R \qquad ẏ_C = \dot{v_y} + \dot{\omega_x} R $$
$$ \phi' = \arctan\left(\frac{ẏ_C}{ẋ_C}\right) \qquad s' = \sqrt{(ẋ_C)^2 + (ẏ_C)^2} $$
Numerical solutions for the centroid velocity of the ball during compression and restitution phases.
$$ (\dot{v_x})_{n+1} - (\dot{v_x})_n = - \frac{1}{M} \left[\mu_w \cos(\phi) + \mu_s \cos(\phi') \cdot (\sin \theta + \mu_w \sin(\phi) \cos \theta)\right] \Delta P_I $$
$$ (\dot{v_y})_{n+1} - (\dot{v_y})_n = - \frac{1}{M} \left[ \cos \theta - \mu_w \sin \theta \sin \phi + \mu_s \sin \phi' \cdot \left( \sin \theta + \mu_w \sin \phi \cos \theta \right) \right] \Delta P_I $$
Numerical solutions for angular velocity of ball
$$ (\dot{\omega_x})_{n+1}−(\dot{\omega_x})_n = -\frac{5}{2MR}[\mu_w \sin(\phi) + \mu_s \sin(\phi') \times (\sin(\theta) + \mu_w \sin(\phi)\cos(\theta))]\Delta P_I $$
$$ (\dot{\omega_y})_{n+1}−(\dot{\omega_y})_n = -\frac{5}{2MR}[\mu_w \cos(\phi)\sin(\theta) - \mu_s \cos(\phi') \times (\sin(\theta) + \mu_w \sin(\phi)\cos(\theta))]\Delta P_I $$
$$ (\dot{\omega_z})_{n+1}−(\dot{\omega_z})_n = \frac{5}{2MR}(\mu_w \cos(\phi)\cos(\theta))\Delta P_I $$
$\theta$ is a constant of the angle of cushion contact above ball centre with $\sin(\theta) = 2/5$. $\mu_s$ is the coefficient of sliding friction between the ball and table surface. $\mu_w$ is the coefficient of sliding friction between the ball and the cushion.
Work done by the normal force at contact point $I$ along the $Z'$-axis which is aligned from the ball centre to I
$$ W_{Z'}^I(P_I^{(n+1)}) = W_{Z'}^I(P_I^{(n)}) + \frac{\Delta P_I}{2} \left( z'_I(P_I^{(n+1)}) + z'_I(P_I^{(n)}) \right) $$
The ball is assumed to be bouncing in the +y cushion. Compression phase iterates until
$$\dot{v}_y \le 0$$
For the restitution phase the iteration continues until the work done is
$$W_{Z'}^I \ge e_e^2 W_{\text{compression}}$$
Some of the Mathavan equations not supplied by the paper were inferred to bridge gaps for a complete numerical solution.
Stronge compliant cushion model
Based on the book Impact Mechanics by Stronge. This analytical model accounts for the compliant nature of cushion deformation and resolves the collision across three slip regimes.
Contact velocity at the cushion contact point:
$$\vec{V}_c = \vec{v} - (\vec{\omega} \times R \hat{n})$$
Regime classification is determined by the ratio $v_{\text{ratio}} = v_{t0} / v_{n0}$ and thresholds involving the friction coefficient $\mu$, restitution $e_n$, and mass-matrix coefficients $\beta$:
| Regime | Condition |
|---|---|
| Gross slip | $v_{\text{ratio}} > \mu \left( (1 + e_n) \beta_{\text{ratio}} - \frac{\eta^2}{e_n} \right)$ |
| Initial stick | $v_{\text{ratio}} < \mu \eta^2$ |
| Slip-stick-slip | neither of the above |
where $\eta^2$ is derived from the frequency ratio $\omega_t/\omega_n$.
Velocity reconstruction from scalar solver results $v_{nf}$ and $v_{tf}$:
$$\Delta v_n = \frac{v_{nf} - v_{n0}}{\beta_n} , \quad \Delta v_t = \frac{v_{tf} - v_{t0}}{\beta_t}$$
Final updates:
$$\vec{v} \leftarrow \vec{v} + \Delta v_n \hat{n} + \Delta v_t \hat{t}$$ $$\vec{\omega} \leftarrow \vec{\omega} + \frac{mR}{I} (-\hat{n} \times \Delta v_t \hat{t})$$
Useful commands
Install
nvm use v24.11.0 corepack enable yarn set version 4.9.1 yarn install yarn build yarn gltfpack
This generates artefacts in /dist for prod deployment (e.g. on github static pages)
Run
yarn serve
Then open http://localhost:8080/ in your browser to play
Test
yarn test yarn coverage
Maintain
yarn deps yarn upgrade -L yarn prettify
Two player
yarn serve
then open http://localhost:8080/multi.html to see options, message server is public nchan.
Controls
Use mouse, touch screen or keyboard:
⇦ ⇨ Aim
Control ⇦ ⇨ Fine aim
⇧ ⇩ Topspin and backspin
Shift ⇦ ⇨ Side spin
Space Hit - hold for more power
A Toggle aim helper
M Masse angle
O Camera view
F Full screen
C Chat
H Help
+ - Camera height
Mouse
scroll Shot power
dbl click Hit
Progress snapshots
July 2018
July 2019
March 2021
August 2023 (mobile)
| top | aim |
|---|---|
![]() |
![]() |
Star History
Licence
This project is open source and licensed under the GNU General Public License - see the LICENSE file for details. Contributions welcome.
more like this
Binderly
Open-source Markdown workbench: live preview, GitHub-accurate themes, Mermaid diagrams, and page-perfect PDF export. No…





