silphius/app/react/components/dom/damage.jsx
2024-07-26 18:05:24 -05:00

73 lines
1.9 KiB
JavaScript

import {useEffect, useState} from 'react';
import {useRadians} from '@/react/context/radians.js';
import styles from './damage.module.css';
export default function Damage({
camera,
damage,
scale,
}) {
const [hue, setHue] = useState(0);
const [opacity, setOpacity] = useState(0.5);
const [growth, setGrowth] = useState(0.25);
const [offset, setOffset] = useState({x: 0, y: 0});
const [randomness] = useState({
hue: Math.random() * 10,
x: 1 * (Math.random() - 0.5),
y: 150 * (Math.random()),
rotation: Math.random() * (Math.PI / 8) - (Math.PI / 16),
});
const radians = useRadians();
useEffect(() => {
setHue(15 + (Math.cos(radians * 4) * (5 + randomness.hue)));
}, [radians, randomness.hue]);
useEffect(() => {
let handle;
let accumulated = 0;
let last = Date.now();
function float() {
const elapsed = (Date.now() - last) / 1000;
accumulated += elapsed;
last = Date.now();
if (accumulated < 0.25) {
setOpacity(0.5 + accumulated * 2)
}
if (accumulated < 0.5) {
setGrowth(0.25 + (accumulated * 1.5))
setOffset({
x: 80 * (accumulated * randomness.x),
y: -((80 + randomness.y) * (accumulated)),
});
}
if (accumulated >= 1.5) {
damage.onClose();
}
handle = requestAnimationFrame(float);
}
handle = requestAnimationFrame(float);
return () => {
cancelAnimationFrame(handle);
};
}, [damage, randomness.x, randomness.y]);
const {amount, position} = damage;
const left = position.x * scale - camera.x + offset.x;
const top = position.y * scale - camera.y + offset.y;
return (
<div
className={styles.damage}
style={{
color: `hsl(${hue} 100% 50%)`,
left: `${left}px`,
opacity,
top: `${top}px`,
transform: `scale(${growth}) rotate(${randomness.rotation}rad)`,
}}
>
<p>{amount}</p>
</div>
);
}