diff --git a/src/main/client/package-lock.json b/src/main/client/package-lock.json index 11ada52..8e49934 100644 --- a/src/main/client/package-lock.json +++ b/src/main/client/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "dependencies": { "@stomp/stompjs": "^7.0.0", + "howler": "^2.2.4", "immer": "^10.1.1", "react": "^18.2.0", "react-click-away-listener": "^2.2.3", @@ -3355,6 +3356,12 @@ "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==", + "license": "MIT" + }, "node_modules/human-signals": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", diff --git a/src/main/client/package.json b/src/main/client/package.json index d91311d..ddd959a 100644 --- a/src/main/client/package.json +++ b/src/main/client/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "@stomp/stompjs": "^7.0.0", + "howler": "^2.2.4", "immer": "^10.1.1", "react": "^18.2.0", "react-click-away-listener": "^2.2.3", diff --git a/src/main/client/public/stone1.wav b/src/main/client/public/stone1.wav new file mode 100644 index 0000000..4c58417 Binary files /dev/null and b/src/main/client/public/stone1.wav differ diff --git a/src/main/client/src/feature/game/Game.jsx b/src/main/client/src/feature/game/Game.jsx index f28cc04..325c723 100644 --- a/src/main/client/src/feature/game/Game.jsx +++ b/src/main/client/src/feature/game/Game.jsx @@ -23,6 +23,7 @@ import { import { useAuthStore, useGameStore, + useMuteStore, } from "../../store.js" import { useLayoutStore, @@ -37,6 +38,16 @@ import { import { GamePanel, } from "./GamePanel.jsx" +import { + Howl, +} from "howler" +import { + FaVolumeMute, + FaVolumeUp, +} from "react-icons/fa" +import { + IconContext, +} from "react-icons" export const Game = () => { let [cursor_x, setCursor_x] = useState(-1) @@ -65,6 +76,14 @@ export const Game = () => { let sidebarWidth = useLayoutStore(state => state.sidebarWidth.game) let vw = useLayoutStore(state => state.vw) let dragging = useLayoutStore(state => state.dragging) + let muted = useMuteStore(state => state.muted) + let setMuteState = useMuteStore((state) => state.setMuted) + let sound = useMemo(() => new Howl({ + src: ["/app/stone1.wav"], + onloaderror: function (id, error) { + throw new Error(id + ": " + error) + } + }),[]) let context = useMemo(() => { let dim = board.length @@ -184,11 +203,22 @@ export const Game = () => { if (!isSelfPlay()) { // myColor is 0 in self play addMove({...move, color: myColor}) } + if (!muted) { + sound.play(); + } stompClient.publish({ destination: "/app/game/move", body: JSON.stringify(move), }) - }, [context, currentPlayer, currentColor, auth, board, stompClient, counting, forbidden_x, forbidden_y, gameHasEnded, movesLength, addMove, isSelfPlay, myColor]) + }, [context, currentPlayer, currentColor, auth, board, stompClient, counting, forbidden_x, forbidden_y, gameHasEnded, movesLength, addMove, isSelfPlay, myColor, muted]) + + let onMuteClick = useCallback(() => { + if (muted) { + setMuteState(false) + } else { + setMuteState(true) + } + }, [setMuteState, muted]) useEffect(() => { if (!board.length) { @@ -256,22 +286,39 @@ export const Game = () => { } return ( -