Files
super-auto-pets-board-game/web/src/components/DiceRoll.tsx
T

61 lines
2.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useEffect, useState } from 'react'
import type { CSSProperties } from 'react'
// How long the dice scramble before settling, and how fast the faces flicker
// while they do. ROLL_MS is shared with BattlePhase so damage lands exactly
// when the dice settle. Both are the base (1×) durations; the battle speed
// multiplier divides them so the roll keeps pace with the rest of the replay.
export const ROLL_MS = 650
const TICK_MS = 70
// DiceRoll shows one rock die per rolled face in fixed slots under the
// thrower's side: they shake and flicker through faces in place, then settle
// on the values the server actually rolled. Faces carry rock icons (0, 1, or
// 2 rocks) — the same die the game uses, not a pip D6. Mount it with a `key`
// that changes per rock event so the scramble replays every time.
export function DiceRoll({
dice,
side,
speed = 1,
}: {
dice: number[]
side: 'top' | 'bottom'
speed?: number
}) {
const [display, setDisplay] = useState<number[]>(dice)
const [settled, setSettled] = useState(false)
useEffect(() => {
const flicker = window.setInterval(() => {
setDisplay(dice.map(() => Math.floor(Math.random() * 3)))
}, TICK_MS / speed)
const stop = window.setTimeout(() => {
window.clearInterval(flicker)
setDisplay(dice)
setSettled(true)
}, ROLL_MS / speed)
return () => {
window.clearInterval(flicker)
window.clearTimeout(stop)
}
// Runs once per mount; the caller remounts (via key) for each new roll.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
return (
<div className={`dice-roll dice-roll-${side}`} aria-hidden>
{display.map((v, i) => (
<div
key={i}
className={`droll droll-n-${v} ${settled ? 'is-settled' : 'is-rolling'}`}
style={{ '--i': i } as CSSProperties}
>
{Array.from({ length: v }, (_, r) => (
<span key={r} className="droll-rock" />
))}
</div>
))}
</div>
)
}