@iagows/3d-dice-ts
v0.1.7
Published
A 3D environment for rolling game dice using threejs and cannon-es
Downloads
636
Maintainers
Readme
@iagows/3d-dice-tsflo
Physics-based 3D dice rolling for the web - Three.js + Cannon-ES.
Demo
https://iagows.gitlab.io/3d-dice-ts/
Install
npm install @iagows/3d-dice-ts three cannon-esthree and cannon-es are peer dependencies and must be installed alongside the library.
Assets
The library loads textures and sounds at runtime from a static folder. Copy the public/ directory from this package into your app's static assets, then set assetPath to point at it:
cp -r node_modules/@iagows/3d-dice-ts/public ./public/dice-boxQuick start
import DiceBox from "@iagows/3d-dice-ts";
const box = new DiceBox("#scene-container", {
assetPath: "/dice-box/",
});
await box.initialize();
const result = await box.roll("2d20+1d6");
// { notation: "2d20+1d6", sets: [...], modifier: 0, total: 27 }The container element must have a defined size. The library renders a <canvas> inside it.
Getting results
Three ways - pick what fits your architecture:
Promise
const result = await box.roll("4d6");
console.log(result.total);Callback
const box = new DiceBox("#scene-container", {
assetPath: "/dice-box/",
onRollComplete: (result) => console.log(result),
});DOM event
document.addEventListener("rollComplete", (e) => {
console.log((e as CustomEvent).detail);
});Predetermined outcomes
Append @ with a comma-separated list of forced face values:
box.roll("6d6@4,4,4,4,4,4"); // all six dice land on 4
box.roll("2d20@20,1"); // first → 20, second → 1The physics simulation runs freely; the geometry is swapped at settle time so the correct face ends up on top.
API
new DiceBox(container, config?)
| Parameter | Type | Description |
| ----------- | ------------------------ | --------------------------- |
| container | string \| HTMLElement | CSS selector or DOM element |
| config | Partial<DiceBoxConfig> | Optional - see Config below |
box.initialize(): Promise<void>
Sets up the Three.js scene, physics world, and renderer. Call once before rolling.
box.roll(notation): Promise<RollCompleteResult>
Clears existing dice and rolls a new set.
box.reroll(diceIds): Promise<RollResult[]>
Rerolls specific dice by ID (from a previous result).
const result = await box.roll("4d6");
const lowest = result.sets[0].rolls.sort((a, b) => a.value - b.value)[0];
await box.reroll([lowest.id]);box.add(notation): Promise<RollResult[]>
Adds dice to the current roll without clearing existing ones.
box.remove(diceIds): Promise<RollResult[]>
Removes specific dice from the scene by ID.
box.updateConfig(config): Promise<void>
Updates config at runtime and rebuilds the scene.
box.loadTheme(themeConfig): Promise<void>
Swaps the active theme without a full config reload.
await box.loadTheme({ colorset: "fire", texture: "", material: "glass" });Config
{
assetPath: "", // required - path to the copied /public assets
framerate: 1 / 60,
sounds: false,
volume: 100,
color_spotlight: 0xefdfd5,
shadows: true,
theme_surface: "green-felt",
sound_dieMaterial: "plastic",
theme_customColorset: null,
theme_colorset: "white",
theme_texture: "",
theme_material: "glass", // "none" | "metal" | "wood" | "glass"
gravity_multiplier: 400,
light_intensity: 0.7,
baseScale: 100,
strength: 1,
iterationLimit: 1000,
onRollComplete: () => {},
onRerollComplete: () => {},
onAddDiceComplete: () => {},
onRemoveDiceComplete: () => {},
}TypeScript
Types are bundled:
import DiceBox from "@iagows/3d-dice-ts";
import type { DiceBoxConfig, RollCompleteResult } from "@iagows/3d-dice-ts";License
MIT
Changelog
- 0.1.3 - Updated names from the forked project. No functional changes.
- 0.1.2 - Initial release.
