myrpg / Dice.js
Dippergl231's picture
Rename Doce.js to Dice.js
34edf05 verified
Raw
History Blame Contribute Delete
1.59 kB
export class SensoryDiceRoller {
constructor(onRoll) {
this.onRoll = onRoll;
this.samples = [];
this.isSampling = false;
this.timer = null;
this.init();
}
mulberry32(a) {
return function() {
let t = a += 0x6D2B79F5;
t = Math.imul(t ^ t >>> 15, t | 1);
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
return ((t ^ t >>> 14) >>> 0) / 4294967296;
};
}
init() {
if (window.DeviceMotionEvent) {
window.addEventListener('devicemotion', (e) => this.handleMotion(e));
}
window.addEventListener('mousemove', (e) => this.handleMouse(e));
}
startSequence() {
this.samples = [];
this.isSampling = true;
this.timer = setTimeout(() => {
if (this.isSampling) {
this.triggerRoll(Math.floor(Math.random() * 0xFFFFFFFF));
}
}, 5000);
}
handleMotion(e) {
if (!this.isSampling) return;
const { x, y, z } = e.accelerationIncludingGravity || {};
if (x && y && z) {
this.samples.push(Math.sqrt(x*x + y*y + z*z));
this.check();
}
}
handleMouse(e) {
if (!this.isSampling) return;
const v = Math.sqrt(e.movementX**2 + e.movementY**2);
this.samples.push(v);
this.check();
}
check() {
if (this.samples.length >= 30) {
clearTimeout(this.timer);
const seed = this.samples.reduce((a, b) => a + Math.floor(b * 1000), 0);
this.triggerRoll(seed);
}
}
triggerRoll(seed) {
this.isSampling = false;
const rng = this.mulberry32(seed);
const result = Math.floor(rng() * 20) + 1;
this.onRoll(result);
}
}