Overlap detection

This commit is contained in:
LittleSheep 2024-02-15 23:08:48 +08:00
parent b42def99a0
commit 046f33b68e
2 changed files with 42 additions and 10 deletions

View File

@ -6,3 +6,11 @@
transform: rotate(calc(90deg + 360deg * var(--rotation-factor))); transform: rotate(calc(90deg + 360deg * var(--rotation-factor)));
} }
} }
.crystal--energy-indicator {
stroke-opacity: 1;
}
.crystal--powerless .crystal--energy-indicator {
stroke-opacity: 0;
}

View File

@ -1,6 +1,8 @@
import { styled } from "solid-styled-components"; import { styled } from "solid-styled-components";
import { vector2d } from "../vector"; import { vector2d } from "../vector";
import { createMemo, createSignal, onCleanup, onMount } from "solid-js"; import { createMemo, createSignal } from "solid-js";
import { useTimer } from "../providers/timer";
import { checkElementOverlap } from "./collision";
import "./crystal.css"; import "./crystal.css";
@ -23,14 +25,35 @@ export default function Crystal(props: { size?: number; position?: vector2d }) {
const rechargeProgress = createMemo(() => (energy() / maxEnergy()) * 100); const rechargeProgress = createMemo(() => (energy() / maxEnergy()) * 100);
function updateEnergy() { const isAlive = createMemo(() => energy() > 0);
setEnergy(energy() - 1);
function checkAnyPlayerUnderCrystal() {
const players = document.querySelectorAll<HTMLElement>(".player");
const crystal = document.querySelector<HTMLElement>(".crystal");
for (const player of players) {
if (crystal && checkElementOverlap(crystal, player)) {
return true;
}
}
return false;
} }
onMount(() => { function updateEnergy() {
const loop = setInterval(() => updateEnergy(), 100); const doRecharge = checkAnyPlayerUnderCrystal();
onCleanup(() => clearInterval(loop)); if (doRecharge) {
}); if (energy() < maxEnergy()) {
setEnergy(energy() + 1);
}
} else {
if (energy() > 0) {
setEnergy(energy() - 1);
}
}
}
const [{ subscribe }] = useTimer();
subscribe(() => updateEnergy());
// Renderer // Renderer
@ -61,9 +84,10 @@ export default function Crystal(props: { size?: number; position?: vector2d }) {
stroke-linecap: round; stroke-linecap: round;
animation: alternate 10s crystal--fill-wabble infinite ease-in-out; animation: alternate 10s crystal--fill-wabble infinite ease-in-out;
transform-origin: var(--half-size) var(--half-size); transform-origin: var(--half-size) var(--half-size);
stroke-dasharray: var(--dash) calc(var(--circumference) - var(--dash)); stroke-dasharray: var(--dash) calc(var(--circumference) - var(--dash));
transition: stroke-dasharray 0.3s linear 0s; transition: all 0.3s linear 0s;
stroke: var(--color-primary); stroke: var(--color-primary);
`; `;
@ -80,7 +104,7 @@ export default function Crystal(props: { size?: number; position?: vector2d }) {
return ( return (
<CrystalElement <CrystalElement
class="crystal" class={`crystal ${isAlive() ? `crystal--powerful` : `crystal--powerless`}`}
style={{ style={{
left: `${x()}px`, left: `${x()}px`,
top: `${y()}px`, top: `${y()}px`,
@ -91,7 +115,7 @@ export default function Crystal(props: { size?: number; position?: vector2d }) {
}} }}
> >
<CrystalCircleInactive /> <CrystalCircleInactive />
<CrystalCircleActive /> <CrystalCircleActive class="crystal--energy-indicator" />
</CrystalElement> </CrystalElement>
); );
} }