diff --git a/src/components/GestureOverlay.tsx b/src/components/GestureOverlay.tsx
index 4e48aa1..08a9ff9 100644
--- a/src/components/GestureOverlay.tsx
+++ b/src/components/GestureOverlay.tsx
@@ -17,9 +17,11 @@ interface Props {
export function GestureOverlay({ gesture, calibrationStatus, framingHint }: Props) {
if (calibrationStatus === 'ready') return null
+ const showGesture = gesture === 'arms-out'
+
return (
<>
- {gesture && (
+ {showGesture && (
{GESTURE_LABELS[gesture]}
diff --git a/src/game/ArrowGame.tsx b/src/game/ArrowGame.tsx
index 51fcb06..d3c511e 100644
--- a/src/game/ArrowGame.tsx
+++ b/src/game/ArrowGame.tsx
@@ -60,6 +60,8 @@ export const ArrowGame = forwardRef(({ active = true, ch
const audioRef = useRef(null)
const songStartRef = useRef(null)
const spawnedUpToRef = useRef(0)
+ const onSongEndRef = useRef(onSongEnd)
+ onSongEndRef.current = onSongEnd
const showJudgment = useCallback((text: string) => {
if (judgmentTimer.current) clearTimeout(judgmentTimer.current)
@@ -140,16 +142,24 @@ export const ArrowGame = forwardRef(({ active = true, ch
useEffect(() => {
if (!active || !chartNotes || !audioUrl) return
+ // Reset state for fresh start
+ arrowsRef.current = []
+ setArrows([])
+ spawnedUpToRef.current = 0
+ comboRef.current = 0
+ setScore({ perfect: 0, good: 0, miss: 0, combo: 0 })
+
const audio = new Audio(audioUrl)
audioRef.current = audio
songStartRef.current = null
- spawnedUpToRef.current = 0
audio.play().then(() => {
songStartRef.current = performance.now()
- }).catch(() => {})
+ }).catch((e) => {
+ console.warn('Audio play failed:', e)
+ })
- audio.addEventListener('ended', () => onSongEnd?.())
+ audio.addEventListener('ended', () => onSongEndRef.current?.())
return () => {
audio.pause()
@@ -157,7 +167,7 @@ export const ArrowGame = forwardRef(({ active = true, ch
audioRef.current = null
songStartRef.current = null
}
- }, [active, chartNotes, audioUrl, onSongEnd])
+ }, [active, chartNotes, audioUrl]) // eslint-disable-line react-hooks/exhaustive-deps
// Chart mode: spawn arrows based on song time
useEffect(() => {