diff --git a/src/App.jsx b/src/App.jsx
index 3df3569..e5b03c5 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -94,6 +94,24 @@ function AppMain() {
const scoreEndRef = useRef(0);
const scoreRafRef = useRef(null);
const [crowns, setCrowns] = useState({ bronze: 0, silver: 0, gold: 0 });
+ const [playingBgm, setPlayingBgm] = useState(null);
+ const bgmRef = useRef(null);
+
+ const toggleBgm = useCallback((tier) => {
+ if (bgmRef.current) {
+ bgmRef.current.pause();
+ bgmRef.current = null;
+ if (playingBgm === tier) { setPlayingBgm(null); return; }
+ }
+ if (volumeRef.current < 0.5) { handleVolumeChange(0.5); }
+ const audio = new Audio(`${BASE_URL}music/${tier}.mp3`);
+ audio.volume = volumeRef.current;
+ audio.loop = true;
+ audio.play().catch(() => {});
+ audio.onended = () => setPlayingBgm(null);
+ bgmRef.current = audio;
+ setPlayingBgm(tier);
+ }, [playingBgm]);
const langRef = useRef('en');
const volumeRef = useRef(0);
const voiceIndexRef = useRef(0);
@@ -122,6 +140,7 @@ function AppMain() {
setVolume(v);
volumeRef.current = v;
if (windRef.current) windRef.current.volume = v;
+ if (bgmRef.current) bgmRef.current.volume = v;
}, []);
useEffect(() => {
@@ -134,8 +153,7 @@ function AppMain() {
}, [view]);
const playSkillVoice = useCallback(() => {
- const type = voicePattern[voiceIndexRef.current % voicePattern.length];
- voiceIndexRef.current += 1;
+ const type = Math.random() < 1/6 ? 'skill' : 'normal';
const suffix = langRef.current === 'en' ? '_en' : '';
const file = `${import.meta.env.BASE_URL}voice/ai/${type}_1${suffix}.mp3`;
const audio = new Audio(file);
@@ -235,6 +253,9 @@ function AppMain() {
}, 4500);
// Damage number - show during blackhole phase
setTimeout(() => {
+ const burstEnd = new Audio(`${BASE_URL}sound/burst_end.mp3`);
+ burstEnd.volume = volumeRef.current;
+ burstEnd.play().catch(() => {});
const baseDmg = Math.floor(Math.random() * 100000) + 1;
// x2 if ai_mode
const modeMult = vrmModel === 'ai_mode.vrm' ? 2 : 1;
@@ -279,7 +300,8 @@ function AppMain() {
});
}, 2500);
const suffix = langRef.current === 'en' ? '_en' : '';
- const file = `${import.meta.env.BASE_URL}voice/ai/burst_1${suffix}.mp3`;
+ const burstType = Math.random() < 1/6 ? 'burst' : 'normal';
+ const file = `${import.meta.env.BASE_URL}voice/ai/${burstType}_1${suffix}.mp3`;
const audio = new Audio(file);
audio.volume = volumeRef.current;
audio.play().catch(() => {});
@@ -467,6 +489,11 @@ function AppMain() {
}}>
{crowns.gold}
+
toggleBgm('gold')}
+ style={{ width: 14, height: 14, filter: 'brightness(0) invert(1)', opacity: playingBgm === 'gold' ? 1 : 0.4, cursor: 'pointer' }}
+ />
)}
{crowns.silver > 0 && (
@@ -479,6 +506,11 @@ function AppMain() {
}}>
{crowns.silver}
+
toggleBgm('silver')}
+ style={{ width: 14, height: 14, filter: 'brightness(0) invert(1)', opacity: playingBgm === 'silver' ? 1 : 0.4, cursor: 'pointer' }}
+ />
)}
{crowns.bronze > 0 && (
@@ -491,6 +523,11 @@ function AppMain() {
}}>
{crowns.bronze}
+
toggleBgm('bronze')}
+ style={{ width: 14, height: 14, filter: 'brightness(0) invert(1)', opacity: playingBgm === 'bronze' ? 1 : 0.4, cursor: 'pointer' }}
+ />
)}