improved sound system 🔊
Created a volume control for all sfx on the application, and a custom hook to "connect" everthing.
This commit is contained in:
1
public/sw.js.map
Normal file
1
public/sw.js.map
Normal file
File diff suppressed because one or more lines are too long
1
public/workbox-9a89b1f8.js.map
Normal file
1
public/workbox-9a89b1f8.js.map
Normal file
File diff suppressed because one or more lines are too long
29
src/components/Menu/VolumePicker.tsx
Normal file
29
src/components/Menu/VolumePicker.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Slider } from '@mantine/core';
|
||||
import useSfx from '~hooks/useSfx';
|
||||
|
||||
export default function VolumePicker() {
|
||||
const { play, volume, setVolume } = useSfx('click.wav');
|
||||
|
||||
const steps = [
|
||||
{ value: 0, label: '0' },
|
||||
{ value: 25, label: '1' },
|
||||
{ value: 50, label: '2' },
|
||||
{ value: 75, label: '3' },
|
||||
{ value: 100, label: '4' },
|
||||
];
|
||||
|
||||
return (
|
||||
<Slider
|
||||
label={(v) => steps.find((s) => s.value == v)?.label}
|
||||
onChangeEnd={(value) => {
|
||||
setVolume(() =>
|
||||
Number.parseFloat(`0.${steps.find((s) => s.value == value)?.label}`)
|
||||
);
|
||||
}}
|
||||
defaultValue={steps.find((s) => s.label === `${volume * 10}`)?.value}
|
||||
step={25}
|
||||
marks={steps}
|
||||
styles={{ markLabel: { display: 'none' } }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,19 +1,23 @@
|
||||
import { IconMenu2, IconColorSwatch } from '@tabler/icons';
|
||||
import {
|
||||
IconMenu2,
|
||||
IconColorSwatch,
|
||||
IconVolume,
|
||||
IconVolume2,
|
||||
IconVolume3,
|
||||
} from '@tabler/icons';
|
||||
import { Menu as M, ActionIcon, Popover } from '@mantine/core';
|
||||
import { useState } from 'react';
|
||||
import { useSound } from 'use-sound';
|
||||
import { SwitchTheme } from '~components/MantineUI';
|
||||
import useSfx from '~hooks/useSfx';
|
||||
|
||||
import SchemePicker from './SchemePicker';
|
||||
export { SchemePicker };
|
||||
import VolumePicker from './VolumePicker';
|
||||
export { SchemePicker, VolumePicker };
|
||||
|
||||
export default function Menu() {
|
||||
const [opened, setOpened] = useState(false);
|
||||
|
||||
const [play] = useSound('/sounds/click.wav', {
|
||||
format: ['wav'],
|
||||
volume: 0.3,
|
||||
});
|
||||
const { play, volume } = useSfx('click.wav');
|
||||
|
||||
const playClick = (high: boolean) =>
|
||||
play({ playbackRate: (high ? 3 : 1) + Math.random() });
|
||||
@@ -37,6 +41,7 @@ export default function Menu() {
|
||||
|
||||
<M.Dropdown>
|
||||
<M.Label>Menu</M.Label>
|
||||
|
||||
<M.Item icon={<SwitchTheme onChange={playClick} />}>
|
||||
<p>Tema escuro</p>
|
||||
</M.Item>
|
||||
@@ -50,6 +55,22 @@ export default function Menu() {
|
||||
</Popover.Dropdown>
|
||||
</Popover>
|
||||
</M.Item>
|
||||
|
||||
<M.Divider />
|
||||
|
||||
<M.Item
|
||||
icon={
|
||||
volume == 0 ? (
|
||||
<IconVolume3 />
|
||||
) : volume < 0.3 ? (
|
||||
<IconVolume2 />
|
||||
) : (
|
||||
<IconVolume />
|
||||
)
|
||||
}
|
||||
>
|
||||
<VolumePicker />
|
||||
</M.Item>
|
||||
</M.Dropdown>
|
||||
</M>
|
||||
);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Text } from '@mantine/core';
|
||||
import { ReactNode, useEffect } from 'react';
|
||||
import { motion, HTMLMotionProps, useAnimationControls } from 'framer-motion';
|
||||
import useSound from 'use-sound';
|
||||
import { Heart } from '~components/Specials';
|
||||
import useSfx from '~hooks/useSfx';
|
||||
|
||||
import Handler from './Handler';
|
||||
export { Handler };
|
||||
@@ -39,8 +39,7 @@ export default function Message({
|
||||
|
||||
const animControls = useAnimationControls();
|
||||
|
||||
const [play] = useSound('/sounds/message_pop.wav', {
|
||||
format: ['wav'],
|
||||
const { play } = useSfx('message_pop.wav', {
|
||||
sprite: {
|
||||
pop0: [0, 300],
|
||||
pop1: [600, 300],
|
||||
@@ -48,7 +47,6 @@ export default function Message({
|
||||
pop3: [1850, 300],
|
||||
pop4: [2600, 300],
|
||||
},
|
||||
volume: 0.3,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import { IconHeart } from '@tabler/icons';
|
||||
import { motion } from 'framer-motion';
|
||||
import useSound from 'use-sound';
|
||||
import useSfx from '~hooks/useSfx';
|
||||
|
||||
export default function Heart() {
|
||||
const [play] = useSound('/sounds/heartbeat.wav', {
|
||||
format: ['wav'],
|
||||
volume: 0.3,
|
||||
});
|
||||
const { play } = useSfx('heartbeat.wav');
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
|
||||
39
src/hooks/useSfx.ts
Normal file
39
src/hooks/useSfx.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { useLocalStorage } from '@mantine/hooks';
|
||||
import { useSound } from 'use-sound';
|
||||
import { SpriteMap } from 'use-sound/dist/types';
|
||||
|
||||
/**
|
||||
* Custom hook to play sound effects.
|
||||
*
|
||||
* @param file The file name of the sound effect.
|
||||
*/
|
||||
export default function useSfx(
|
||||
file: string,
|
||||
config?: { format?: string[]; sprite?: SpriteMap }
|
||||
) {
|
||||
const [sfxVolume, setVolume] = useLocalStorage<number>({
|
||||
key: 'sfx-volume',
|
||||
defaultValue: 0.3,
|
||||
});
|
||||
|
||||
/**
|
||||
* Regex to extract the extension from file name.
|
||||
*
|
||||
* Thanks to Tomalak, on stackoverflow for the regex.
|
||||
* https://stackoverflow.com/a/680982
|
||||
* CC BY-SA 4.0
|
||||
*/
|
||||
const regExt = /(?:\.([^.]+))?$/;
|
||||
|
||||
const [play] = useSound(`/sounds/sfx/${file}`, {
|
||||
format: config?.format ?? [regExt.exec(file)?.[1] ?? file.split('.').pop()],
|
||||
volume: sfxVolume,
|
||||
sprite: config?.sprite,
|
||||
});
|
||||
|
||||
return {
|
||||
play,
|
||||
volume: sfxVolume,
|
||||
setVolume,
|
||||
};
|
||||
}
|
||||
@@ -33,7 +33,7 @@ export default function App(props: AppProps) {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>Page title</title>
|
||||
<title>Hello.Kei</title>
|
||||
<meta
|
||||
name='viewport'
|
||||
content='minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no, user-scalable=no, viewport-fit=cover'
|
||||
|
||||
Reference in New Issue
Block a user