Skip to content

Commit 44dc1b4

Browse files
Hanaffiekzhang
andauthored
Add sound effects (#76)
* Rotate cards 90 deg * Fixed formats (Prettier) * Fix math calculations for layout * Added Sounds * Added sounds * Sound Effects On Successful Set * RotateSFX + FailSFX + Some Refactoring * Formatting * Trying to fix the conflict * Trying to solve conflict #2 * Attribution + Naming convention * Msg tab notification * Revert "Msg tab notification" This reverts commit e4bee487eea91ed04bf0104c0579fb81305bc794. * Edit about * Add volume toggle button, handled by React context Co-authored-by: Eric Zhang <[email protected]>
1 parent 1e12d57 commit 44dc1b4

13 files changed

+82
-22
lines changed

package-lock.json

+13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
"react-dom": "^16.14.0",
2323
"react-router-dom": "^5.2.0",
2424
"react-scripts": "4.0.2",
25-
"react-spring": "^8.0.27"
25+
"react-spring": "^8.0.27",
26+
"use-sound": "^2.0.1"
2627
},
2728
"devDependencies": {
2829
"cross-env": "^7.0.3",

src/App.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import CssBaseline from "@material-ui/core/CssBaseline";
77
import { ThemeProvider } from "@material-ui/core/styles";
88

99
import { generateColor, generateName } from "./util";
10-
import { UserContext, KeyboardContext } from "./context";
10+
import { UserContext, SettingsContext } from "./context";
1111
import useStorage from "./hooks/useStorage";
1212
import ConnectionsTracker from "./components/ConnectionsTracker";
1313
import WelcomeDialog from "./components/WelcomeDialog";
@@ -37,6 +37,7 @@ function App() {
3737
"keyboardLayout",
3838
"QWERTY"
3939
);
40+
const [volume, setVolume] = useStorage("volume", "on");
4041

4142
useEffect(() => {
4243
return firebase.auth().onAuthStateChanged((user) => {
@@ -120,8 +121,8 @@ function App() {
120121
<BannedPage time={user.banned} />
121122
) : (
122123
<UserContext.Provider value={user}>
123-
<KeyboardContext.Provider
124-
value={[keyboardLayout, setKeyboardLayout]}
124+
<SettingsContext.Provider
125+
value={{ keyboardLayout, setKeyboardLayout, volume, setVolume }}
125126
>
126127
<ConnectionsTracker />
127128
<WelcomeDialog />
@@ -143,7 +144,7 @@ function App() {
143144
<Route exact path="/profile/:id" component={ProfilePage} />
144145
<Route component={NotFoundPage} />
145146
</Switch>
146-
</KeyboardContext.Provider>
147+
</SettingsContext.Provider>
147148
</UserContext.Provider>
148149
)}
149150
</BrowserRouter>

src/assets/failedSetSound.mp3

11.4 KB
Binary file not shown.

src/assets/layoutChangeSound.mp3

27.8 KB
Binary file not shown.

src/assets/successfulSetSound.mp3

62.9 KB
Binary file not shown.

src/components/Game.js

+12-6
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ import Paper from "@material-ui/core/Paper";
55
import Typography from "@material-ui/core/Typography";
66
import { lightGreen } from "@material-ui/core/colors";
77
import { animated, useSprings } from "react-spring";
8+
import useSound from "use-sound";
89

910
import { generateCards, standardLayouts } from "../util";
1011
import ResponsiveSetCard from "../components/ResponsiveSetCard";
1112
import useDimensions from "../hooks/useDimensions";
1213
import useKeydown from "../hooks/useKeydown";
1314
import useStorage from "../hooks/useStorage";
14-
import { KeyboardContext } from "../context";
15+
import { SettingsContext } from "../context";
16+
import layoutSfx from "../assets/layoutChangeSound.mp3";
1517

1618
const gamePadding = 8;
1719
const cardArray = generateCards();
@@ -34,10 +36,12 @@ function Game({
3436
"orientation",
3537
"vertical"
3638
);
37-
const keyboardLayout = standardLayouts[useContext(KeyboardContext)[0]];
39+
const { keyboardLayout, volume } = useContext(SettingsContext);
40+
const keyboardLayoutDesc = standardLayouts[keyboardLayout];
3841
const isHorizontal = cardOrientation === "horizontal";
3942
const isLandscape = layoutOrientation === "landscape";
4043
const [gameDimensions, gameEl] = useDimensions();
44+
const [playLayout] = useSound(layoutSfx);
4145

4246
let board = deck.slice(0, boardSize);
4347
const unplayed = deck.slice(boardSize);
@@ -155,8 +159,8 @@ function Game({
155159

156160
// Keyboard shortcuts
157161
const shortcuts = isLandscape
158-
? keyboardLayout.horizontalLayout
159-
: keyboardLayout.verticalLayout;
162+
? keyboardLayoutDesc.horizontalLayout
163+
: keyboardLayoutDesc.verticalLayout;
160164
useKeydown((event) => {
161165
const { key } = event;
162166
if (key === "Escape") {
@@ -168,11 +172,13 @@ function Game({
168172
if (index < board.length) {
169173
onClick(board[index]);
170174
}
171-
} else if (key.toLowerCase() === keyboardLayout.orientationChangeKey) {
175+
} else if (key.toLowerCase() === keyboardLayoutDesc.orientationChangeKey) {
172176
event.preventDefault();
177+
if (volume === "on") playLayout();
173178
setCardOrientation(isHorizontal ? "vertical" : "horizontal");
174-
} else if (key.toLowerCase() === keyboardLayout.layoutChangeKey) {
179+
} else if (key.toLowerCase() === keyboardLayoutDesc.layoutChangeKey) {
175180
event.preventDefault();
181+
if (volume === "on") playLayout();
176182
setLayoutOrientation(isLandscape ? "portrait" : "landscape");
177183
}
178184
});

src/components/KeyboardLayoutDialog.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import DialogContentText from "@material-ui/core/DialogContentText";
1313
import { makeStyles } from "@material-ui/core/styles";
1414

1515
import { standardLayouts } from "../util";
16-
import { KeyboardContext } from "../context";
16+
import { SettingsContext } from "../context";
1717

1818
const useStyles = makeStyles({
1919
formControl: {
@@ -25,7 +25,7 @@ function KeyboardLayoutDialog(props) {
2525
const { open, onClose, title } = props;
2626
const classes = useStyles();
2727

28-
const [keyboardLayout, setKeyboardLayout] = useContext(KeyboardContext);
28+
const { keyboardLayout, setKeyboardLayout } = useContext(SettingsContext);
2929

3030
const handleChange = (event) => {
3131
setKeyboardLayout(event.target.value);

src/components/Navbar.js

+23-5
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ import Tooltip from "@material-ui/core/Tooltip";
88
import Typography from "@material-ui/core/Typography";
99
import IconButton from "@material-ui/core/IconButton";
1010
import SettingsIcon from "@material-ui/icons/Settings";
11-
import Brightness3Icon from "@material-ui/icons/Brightness3";
12-
import WbSunnyIcon from "@material-ui/icons/WbSunny";
11+
import Brightness4Icon from "@material-ui/icons/Brightness4";
12+
import Brightness7Icon from "@material-ui/icons/Brightness7";
13+
import VolumeOffIcon from "@material-ui/icons/VolumeOff";
14+
import VolumeUpIcon from "@material-ui/icons/VolumeUp";
1315

1416
import firebase from "../firebase";
15-
import { UserContext } from "../context";
17+
import { UserContext, SettingsContext } from "../context";
1618
import User from "./User";
1719
import InternalLink from "./InternalLink";
1820
import PromptDialog from "./PromptDialog";
@@ -27,6 +29,7 @@ function Navbar({
2729
handleCustomColors,
2830
}) {
2931
const user = useContext(UserContext);
32+
const settings = useContext(SettingsContext);
3033
const [anchorEl, setAnchorEl] = useState(null);
3134
const [changeName, setChangeName] = useState(false);
3235
const [changeColors, setChangeColors] = useState(false);
@@ -56,6 +59,10 @@ function Navbar({
5659
}
5760
}
5861

62+
function handleChangeVolume() {
63+
settings.setVolume((volume) => (volume === "on" ? "off" : "on"));
64+
}
65+
5966
return (
6067
<AppBar position="relative" color="transparent" elevation={0}>
6168
<Toolbar variant="dense">
@@ -80,14 +87,25 @@ function Navbar({
8087
/>
8188
</InternalLink>
8289
</Typography>
90+
<IconButton color="inherit" onClick={handleChangeVolume}>
91+
{settings.volume === "on" ? (
92+
<Tooltip title="Mute">
93+
<VolumeUpIcon />
94+
</Tooltip>
95+
) : (
96+
<Tooltip title="Unmute">
97+
<VolumeOffIcon />
98+
</Tooltip>
99+
)}
100+
</IconButton>
83101
<IconButton color="inherit" onClick={handleChangeTheme}>
84102
{themeType === "light" ? (
85103
<Tooltip title="Dark theme">
86-
<Brightness3Icon />
104+
<Brightness4Icon />
87105
</Tooltip>
88106
) : (
89107
<Tooltip title="Light theme">
90-
<WbSunnyIcon />
108+
<Brightness7Icon />
91109
</Tooltip>
92110
)}
93111
</IconButton>

src/context.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import { createContext } from "react";
22

33
export const UserContext = createContext(null);
44

5-
export const KeyboardContext = createContext(null);
5+
export const SettingsContext = createContext(null);

src/pages/AboutPage.js

+13
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,19 @@ function AboutPage() {
5151
.
5252
</Typography>
5353
</Paper>
54+
<Paper style={{ padding: "1rem", maxWidth: 720, margin: "12px auto" }}>
55+
<Typography variant="body2">
56+
Sounds used from{" "}
57+
<Link href="https://notificationsounds.com/terms-of-use">
58+
notificationsounds.com
59+
</Link>
60+
&nbsp;are provided under a{" "}
61+
<Link href="https://creativecommons.org/licenses/by/4.0/legalcode">
62+
Creative Commons Attribution license
63+
</Link>
64+
.
65+
</Typography>
66+
</Paper>
5467
<Typography
5568
variant="body1"
5669
align="center"

src/pages/GamePage.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Button from "@material-ui/core/Button";
99
import Box from "@material-ui/core/Box";
1010
import Snackbar from "@material-ui/core/Snackbar";
1111
import { Redirect } from "react-router-dom";
12+
import useSound from "use-sound";
1213

1314
import SnackContent from "../components/SnackContent";
1415
import firebase, { createGame, finishGame } from "../firebase";
@@ -21,7 +22,7 @@ import LoadingPage from "./LoadingPage";
2122
import GameSidebar from "../components/GameSidebar";
2223
import GameChat from "../components/GameChat";
2324
import DonateDialog from "../components/DonateDialog";
24-
import { UserContext } from "../context";
25+
import { SettingsContext, UserContext } from "../context";
2526
import {
2627
removeCard,
2728
checkSet,
@@ -30,6 +31,8 @@ import {
3031
computeState,
3132
hasHint,
3233
} from "../util";
34+
import foundSfx from "../assets/successfulSetSound.mp3";
35+
import failSfx from "../assets/failedSetSound.mp3";
3336

3437
const useStyles = makeStyles((theme) => ({
3538
sideColumn: {
@@ -70,6 +73,7 @@ const useStyles = makeStyles((theme) => ({
7073

7174
function GamePage({ match }) {
7275
const user = useContext(UserContext);
76+
const { volume } = useContext(SettingsContext);
7377
const gameId = match.params.id;
7478
const classes = useStyles();
7579

@@ -81,6 +85,8 @@ function GamePage({ match }) {
8185

8286
const [game, loadingGame] = useFirebaseRef(`games/${gameId}`);
8387
const [gameData, loadingGameData] = useFirebaseRef(`gameData/${gameId}`);
88+
const [playSuccess] = useSound(foundSfx);
89+
const [playFail] = useSound(failSfx);
8490

8591
// Reset card selection and number of hints on update to game data
8692
useEffect(() => {
@@ -214,12 +220,14 @@ function GamePage({ match }) {
214220
if (vals.length === 3) {
215221
if (checkSet(...vals)) {
216222
handleSet(vals);
223+
if (volume === "on") playSuccess();
217224
setSnack({
218225
open: true,
219226
variant: "success",
220227
message: "Found a set!",
221228
});
222229
} else {
230+
if (volume === "on") playFail();
223231
setSnack({
224232
open: true,
225233
variant: "error",

src/pages/HelpPage.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ import Paper from "@material-ui/core/Paper";
77

88
import InternalLink from "../components/InternalLink";
99
import SetCard from "../components/SetCard";
10-
import { KeyboardContext } from "../context";
10+
import { SettingsContext } from "../context";
1111
import { standardLayouts } from "../util";
1212

1313
function HelpPage() {
14-
const [keyboardLayout] = useContext(KeyboardContext);
14+
const { keyboardLayout } = useContext(SettingsContext);
1515

1616
return (
1717
<Container>

0 commit comments

Comments
 (0)