fun: das a lodda damage

This commit is contained in:
cha0s 2024-07-26 18:05:24 -05:00
parent 091e19c7de
commit 08dfe8ac29
8 changed files with 167 additions and 1 deletions

View File

@ -1,4 +1,24 @@
import Component from '@/ecs/component.js'; import Component from '@/ecs/component.js';
export default class Vulnerable extends Component { export default class Vulnerable extends Component {
mergeDiff(original, update) {
const merged = {};
if (update.damage) {
merged.damage = {
...original.damage,
...update.damage,
}
}
return merged;
}
instanceFromSchema() {
const Component = this;
return class VulnerableInstance extends super.instanceFromSchema() {
damages = {};
id = 0;
damage(specification) {
Component.markChange(this.entity, 'damage', {[this.id++]: specification});
}
};
}
} }

View File

@ -0,0 +1,72 @@
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>
);
}

View File

@ -0,0 +1,25 @@
.damage {
color: red;
overflow-wrap: break-word;
position: fixed;
margin: 0;
margin-right: -66%;
text-shadow:
0px -1px 0px black,
1px 0px 0px black,
0px 1px 0px black,
-1px 0px 0px black,
0px -2px 0px black,
2px 0px 0px black,
0px 2px 0px black,
-2px 0px 0px black
;
transform: translate(-50%, -50%);
user-select: none;
max-width: 66%;
p {
margin: 0;
}
}

View File

@ -0,0 +1,22 @@
import styles from './damages.module.css';
import Damage from './damage.jsx';
export default function Damages({camera, damages, scale}) {
const elements = [];
for (const key in damages) {
elements.push(
<Damage
camera={camera}
damage={damages[key]}
key={key}
scale={scale}
/>
);
}
if (0 === elements.length) {
return false;
}
return <div className={styles.damages}>{elements}</div>;
}

View File

@ -0,0 +1,4 @@
.damages {
font-family: Cookbook, Georgia, 'Times New Roman', Times, serif;
font-size: 40px;
}

View File

@ -88,6 +88,21 @@ export default function Entities({
}; };
} }
} }
const {damage} = update.Vulnerable || {};
if (damage) {
const {damages} = updating[id].Vulnerable;
for (const key in damage) {
damages[key] = damage[key];
damages[key].onClose = () => {
setEntities((entities) => ({
...entities,
[id]: ecs.rebuild(id),
}));
delete damages[key];
};
}
}
} }
setEntities((entities) => { setEntities((entities) => {
for (const id in deleting) { for (const id in deleting) {

View File

@ -1,6 +1,7 @@
import {memo} from 'react'; import {memo} from 'react';
import Dialogues from './dialogues.jsx'; import Dialogues from './dialogues.jsx';
import Damages from './damages.jsx';
function Entity({camera, entity, scale}) { function Entity({camera, entity, scale}) {
return ( return (
@ -12,6 +13,13 @@ function Entity({camera, entity, scale}) {
scale={scale} scale={scale}
/> />
)} )}
{entity.Vulnerable && (
<Damages
camera={camera}
damages={entity.Vulnerable.damages}
scale={scale}
/>
)}
</> </>
) )
} }

View File

@ -1,4 +1,4 @@
const playerEntity = ecs.lookupPlayerEntity(entity.Owned.owner); const playerEntity = ecs.lookupPlayerEntity(entity.Owned.owner);
if (playerEntity !== other && other.Vulnerable) { if (playerEntity !== other && other.Vulnerable) {
ecs.destroy(other.id); other.Vulnerable.damage({amount: Math.round(60 + Math.random() * 10), position: other.Position.toJSON()})
} }