diff --git a/package-lock.json b/package-lock.json index 0a9421f..f613223 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,10 +11,12 @@ "clsx": "^2.1.0", "next": "14.1.0", "react": "^18", + "react-confetti": "^6.1.0", "react-dom": "^18", "react-hot-toast": "^2.4.1", "socket.io": "^4.7.4", - "socket.io-client": "^4.7.4" + "socket.io-client": "^4.7.4", + "use-sound": "^4.0.1" }, "devDependencies": { "autoprefixer": "^10.0.1", @@ -2422,6 +2424,11 @@ "node": ">= 0.4" } }, + "node_modules/howler": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/howler/-/howler-2.2.4.tgz", + "integrity": "sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w==" + }, "node_modules/ignore": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", @@ -3823,6 +3830,20 @@ "node": ">=0.10.0" } }, + "node_modules/react-confetti": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-confetti/-/react-confetti-6.1.0.tgz", + "integrity": "sha512-7Ypx4vz0+g8ECVxr88W9zhcQpbeujJAVqL14ZnXJ3I23mOI9/oBVTQ3dkJhUmB0D6XOtCZEM6N0Gm9PMngkORw==", + "dependencies": { + "tween-functions": "^1.2.0" + }, + "engines": { + "node": ">=10.18" + }, + "peerDependencies": { + "react": "^16.3.0 || ^17.0.1 || ^18.0.0" + } + }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -4610,6 +4631,11 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, + "node_modules/tween-functions": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tween-functions/-/tween-functions-1.2.0.tgz", + "integrity": "sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4772,6 +4798,17 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sound": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/use-sound/-/use-sound-4.0.1.tgz", + "integrity": "sha512-hykJ86kNcu6y/FzlSHcQxhjSGMslZx2WlfLpZNoPbvueakv4OF3xPxEtGV2YmculrIaH0tPp9LtG4jgy17xMWg==", + "dependencies": { + "howler": "^2.1.3" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index 646951a..81be07c 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,12 @@ "clsx": "^2.1.0", "next": "14.1.0", "react": "^18", + "react-confetti": "^6.1.0", "react-dom": "^18", "react-hot-toast": "^2.4.1", "socket.io": "^4.7.4", - "socket.io-client": "^4.7.4" + "socket.io-client": "^4.7.4", + "use-sound": "^4.0.1" }, "devDependencies": { "autoprefixer": "^10.0.1", diff --git a/public/sounds/answersMusic.mp3 b/public/sounds/answersMusic.mp3 new file mode 100644 index 0000000..c182028 Binary files /dev/null and b/public/sounds/answersMusic.mp3 differ diff --git a/public/sounds/answersSound.mp3 b/public/sounds/answersSound.mp3 new file mode 100644 index 0000000..aa01044 Binary files /dev/null and b/public/sounds/answersSound.mp3 differ diff --git a/public/sounds/results.mp3 b/public/sounds/results.mp3 new file mode 100644 index 0000000..172af89 Binary files /dev/null and b/public/sounds/results.mp3 differ diff --git a/public/sounds/show.mp3 b/public/sounds/show.mp3 new file mode 100644 index 0000000..d11b30d Binary files /dev/null and b/public/sounds/show.mp3 differ diff --git a/socket/src/roles/player.js b/socket/src/roles/player.js index aed2b31..ae61221 100644 --- a/socket/src/roles/player.js +++ b/socket/src/roles/player.js @@ -32,6 +32,11 @@ const Player = { return } + if (game.players.find((p) => p.username === player.username)) { + socket.emit("game:errorMessage", "Username already exists") + return + } + if (game.started) { socket.emit("game:errorMessage", "Game already started") return diff --git a/src/components/game/states/Answers.jsx b/src/components/game/states/Answers.jsx index faa3149..a90c72d 100644 --- a/src/components/game/states/Answers.jsx +++ b/src/components/game/states/Answers.jsx @@ -2,7 +2,14 @@ import AnswerButton from "../../AnswerButton" import { useSocketContext } from "@/context/socket" import { useEffect, useRef, useState } from "react" import clsx from "clsx" -import { ANSWERS_COLORS, ANSWERS_ICONS } from "@/constants" +import { + ANSWERS_COLORS, + ANSWERS_ICONS, + SFX_ANSWERS_MUSIC, + SFX_ANSWERS_SOUND, + SFX_RESULTS_SOUND, +} from "@/constants" +import useSound from "use-sound" const calculatePercentages = (objectResponses) => { const keys = Object.keys(objectResponses) @@ -35,12 +42,32 @@ export default function Answers({ const [cooldown, setCooldown] = useState(time) const [totalAnswer, setTotalAnswer] = useState(0) + const [sfxPop] = useSound(SFX_ANSWERS_SOUND, { + volume: 0.1, + }) + + const [sfxResults] = useSound(SFX_RESULTS_SOUND, { + volume: 0.2, + }) + + const [playMusic, { stop: stopMusic }] = useSound(SFX_ANSWERS_MUSIC, { + volume: 0.2, + }) + useEffect(() => { if (!responses) { + playMusic() return } + stopMusic() + sfxResults() + setPercentages(calculatePercentages(responses)) + + return () => { + stopMusic() + } }, [responses]) useEffect(() => { @@ -50,6 +77,7 @@ export default function Answers({ socket.on("game:playerAnswer", (count) => { setTotalAnswer(count) + sfxPop() }) return () => { @@ -123,9 +151,3 @@ export default function Answers({ ) } - -/* OLD Timer -
- {top[1].username} -
-- 2 -
-- {top[1].points} -
-= 4 }, - )} - > - {top[0].username} -
-- 1 -
-- {top[0].points} -
-= 4, + }, + )} + > + {top[1].username} +
++ 2 +
++ {top[1].points} +
+- {top[2].username} +
= 4 }, + )} + > + {top[0].username}
- 3 +
+ 1
-- {top[2].points} + {top[0].points}
= 4, + }, + )} + > + {top[2].username} +
++ 3 +
+ ++ {top[2].points} +
+