|
@@ -2,6 +2,8 @@ import { useEffect, useState } from "react";
|
|
|
import { dispatch, useGameId, usePlayerName } from "../../../domain/gameStore";
|
|
|
import { usePlayers } from "../../../hooks/useGameInfo";
|
|
|
import styles from "./KillFeed.module.css";
|
|
|
+import hitmarker from "../../../assets/hitmarker.svg";
|
|
|
+import hitsound from "../../../assets/hitsound.wav";
|
|
|
|
|
|
// okay, in an ideal world this would be part of the game store or something
|
|
|
// and it would get properly managed by reactive state
|
|
@@ -36,28 +38,49 @@ const KillFeed = () => {
|
|
|
!shownItemsState.has(`${gameId}-${name}-${round}`)
|
|
|
) ?? [];
|
|
|
setDisplay(toDisplay);
|
|
|
- const timeouts = [];
|
|
|
- toDisplay.forEach(({ name, round }) => {
|
|
|
- timeouts.push(
|
|
|
- setTimeout(() => {
|
|
|
- shownItems.add(`${gameId}-${name}-${round}`);
|
|
|
- setShownItemsState(new Set(shownItems));
|
|
|
- }, 5000)
|
|
|
- );
|
|
|
- });
|
|
|
+ const timeout = setTimeout(() => {
|
|
|
+ toDisplay.forEach(({ name, round }) => {
|
|
|
+ shownItems.add(`${gameId}-${name}-${round}`);
|
|
|
+ });
|
|
|
+ setShownItemsState(new Set(shownItems));
|
|
|
+ }, 5000);
|
|
|
return () => {
|
|
|
- timeouts.forEach(t => clearTimeout(t));
|
|
|
+ clearTimeout(timeout);
|
|
|
};
|
|
|
}, [shownItemsState, gameId, players, playerName]);
|
|
|
+ useEffect(() => {
|
|
|
+ display.forEach(() => {
|
|
|
+ const audio = new Audio(hitsound);
|
|
|
+ audio.volume = 0.5;
|
|
|
+ const delay = Math.random() * 500; // delay up to half a second so overlapping sounds better
|
|
|
+ audio.addEventListener("canplaythrough", () =>
|
|
|
+ setTimeout(() => audio.play(), delay)
|
|
|
+ );
|
|
|
+ audio.addEventListener("ended", () => audio.remove()); // clean up after ourselves
|
|
|
+ });
|
|
|
+ }, [display]);
|
|
|
return (
|
|
|
- <div className={styles.feed}>
|
|
|
- {display.map(({ name, round, score }) => (
|
|
|
- <span key={`${name}-${round}`} className={styles.item}>
|
|
|
- <span className={styles.name}>{name}</span>{" "}
|
|
|
- {score >= 4950 ? "🎯" : "🖱️"} 🗺️ {round}
|
|
|
- </span>
|
|
|
+ <>
|
|
|
+ {display.map(() => (
|
|
|
+ <img
|
|
|
+ alt="hitmarker"
|
|
|
+ className={styles.hitmarker}
|
|
|
+ style={{
|
|
|
+ top: `${10 + Math.random() * 80}vh`,
|
|
|
+ left: `${10 + Math.random() * 80}vw`,
|
|
|
+ }}
|
|
|
+ src={hitmarker}
|
|
|
+ />
|
|
|
))}
|
|
|
- </div>
|
|
|
+ <div className={styles.feed}>
|
|
|
+ {display.map(({ name, round, score }) => (
|
|
|
+ <span className={styles.item}>
|
|
|
+ <span className={styles.name}>{name}</span>{" "}
|
|
|
+ {score >= 4950 ? "🎯" : "🖱️"} 🗺️ {round}
|
|
|
+ </span>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ </>
|
|
|
);
|
|
|
};
|
|
|
|