Skip to main content
Create nostalgic game experiences with classic 8-bit sound effects for player actions, collectibles, and achievements.

Character Jump

Add a satisfying jump sound to your game character:
import { useState } from "react"
import { useSound } from "@/hooks/use-sound"
import { jump8bit } from "@/sounds/jump-8bit"
import { Button } from "@/components/ui/button"

export function JumpButton() {
  const [isJumping, setIsJumping] = useState(false)
  const [playJump] = useSound(jump8bit)

  const handleJump = () => {
    if (isJumping) return
    
    setIsJumping(true)
    playJump()
    
    setTimeout(() => setIsJumping(false), 500)
  }

  return (
    <Button 
      onClick={handleJump}
      disabled={isJumping}
      className={isJumping ? "translate-y-[-10px] transition-transform" : ""}
    >
      🦘 Jump
    </Button>
  )
}

Coin Collection

Play a rewarding sound when collecting coins:
import { useState } from "react"
import { useSound } from "@/hooks/use-sound"
import { coinCollect } from "@/sounds/coin-collect"

export function CoinCollector() {
  const [coins, setCoins] = useState(0)
  const [playCoin] = useSound(coinCollect)

  const collectCoin = () => {
    playCoin()
    setCoins(coins + 1)
  }

  return (
    <div className="space-y-4">
      <div className="text-2xl font-bold">
        Coins: {coins} 🪙
      </div>
      <button
        onClick={collectCoin}
        className="text-4xl hover:scale-110 transition-transform"
      >
        🪙
      </button>
    </div>
  )
}

Complete Game Interface

Build a simple game with multiple sound effects:
import { useState, useEffect } from "react"
import { useSound } from "@/hooks/use-sound"
import { jump8bit } from "@/sounds/jump-8bit"
import { coinCollect } from "@/sounds/coin-collect"
import { successChime } from "@/sounds/success-chime"
import { click8bit } from "@/sounds/click-8bit"
import { Button } from "@/components/ui/button"

export function RetroGame() {
  const [score, setScore] = useState(0)
  const [level, setLevel] = useState(1)
  const [playerY, setPlayerY] = useState(0)
  
  const [playJump] = useSound(jump8bit)
  const [playCoin] = useSound(coinCollect)
  const [playLevelUp] = useSound(successChime)
  const [playClick] = useSound(click8bit)

  const jump = () => {
    playJump()
    setPlayerY(-50)
    setTimeout(() => setPlayerY(0), 400)
  }

  const collectCoin = () => {
    playCoin()
    const newScore = score + 10
    setScore(newScore)
    
    // Level up every 50 points
    if (newScore % 50 === 0) {
      playLevelUp()
      setLevel(level + 1)
    }
  }

  const reset = () => {
    playClick()
    setScore(0)
    setLevel(1)
  }

  return (
    <div className="p-8 space-y-4 border rounded-lg bg-gradient-to-b from-blue-50 to-blue-100 dark:from-slate-900 dark:to-slate-800">
      <div className="flex justify-between items-center">
        <div className="text-xl font-bold">Level {level}</div>
        <div className="text-xl font-bold">Score: {score}</div>
      </div>
      
      <div className="relative h-48 bg-white/50 dark:bg-black/20 rounded-lg overflow-hidden">
        <div 
          className="absolute bottom-4 left-4 text-4xl transition-transform duration-300"
          style={{ transform: `translateY(${playerY}px)` }}
        >
          🦘
        </div>
        
        <button
          onClick={collectCoin}
          className="absolute top-8 right-8 text-3xl hover:scale-110 transition-transform"
        >
          🪙
        </button>
      </div>
      
      <div className="flex gap-2">
        <Button onClick={jump} className="flex-1">
          Jump (Space)
        </Button>
        <Button onClick={reset} variant="outline">
          Reset
        </Button>
      </div>
    </div>
  )
}

Power-up Sequence

Create an ascending sound sequence for power-ups:
import { useSound } from "@/hooks/use-sound"
import { click8bit } from "@/sounds/click-8bit"
import { successChime } from "@/sounds/success-chime"
import { Button } from "@/components/ui/button"

export function PowerUpButton() {
  const [playSound] = useSound(click8bit)
  const [playSuccess] = useSound(successChime)

  const activatePowerUp = async () => {
    // Play ascending tones
    playSound({ playbackRate: 1.0 })
    await new Promise(resolve => setTimeout(resolve, 100))
    
    playSound({ playbackRate: 1.5 })
    await new Promise(resolve => setTimeout(resolve, 100))
    
    playSound({ playbackRate: 2.0 })
    await new Promise(resolve => setTimeout(resolve, 100))
    
    // Final success sound
    playSuccess()
  }

  return (
    <Button onClick={activatePowerUp}>
      ⚡ Power Up
    </Button>
  )
}

Game Menu

Create a retro game menu with sound effects:

Achievement System

Play celebratory sounds for achievements:
import { useState } from "react"
import { useSound } from "@/hooks/use-sound"
import { successChime } from "@/sounds/success-chime"
import { coinCollect } from "@/sounds/coin-collect"

type Achievement = {
  id: string
  title: string
  unlocked: boolean
}

export function AchievementSystem() {
  const [achievements, setAchievements] = useState<Achievement[]>([
    { id: "first-coin", title: "First Coin", unlocked: false },
    { id: "ten-coins", title: "Coin Collector", unlocked: false },
    { id: "fifty-coins", title: "Coin Master", unlocked: false },
  ])
  
  const [playUnlock] = useSound(successChime)
  const [playCoin] = useSound(coinCollect, { playbackRate: 1.5 })

  const unlockAchievement = (id: string) => {
    setAchievements(prev => 
      prev.map(a => 
        a.id === id ? { ...a, unlocked: true } : a
      )
    )
    playUnlock()
    
    // Play additional sound for coin achievements
    if (id.includes("coin")) {
      setTimeout(() => playCoin(), 200)
    }
  }

  return (
    <div className="space-y-2">
      <h3 className="font-bold text-lg">Achievements</h3>
      {achievements.map(achievement => (
        <div 
          key={achievement.id}
          className="flex items-center justify-between p-3 border rounded"
        >
          <span className={achievement.unlocked ? "" : "opacity-50"}>
            {achievement.unlocked ? "🏆" : "🔒"} {achievement.title}
          </span>
          {!achievement.unlocked && (
            <button
              onClick={() => unlockAchievement(achievement.id)}
              className="text-xs text-blue-500 hover:underline"
            >
              Unlock (debug)
            </button>
          )}
        </div>
      ))}
    </div>
  )
}

Combo System

Create a combo system with increasing pitch:
import { useState, useEffect } from "react"
import { useSound } from "@/hooks/use-sound"
import { click8bit } from "@/sounds/click-8bit"
import { successChime } from "@/sounds/success-chime"
import { Button } from "@/components/ui/button"

export function ComboCounter() {
  const [combo, setCombo] = useState(0)
  const [playHit] = useSound(click8bit, { interrupt: true })
  const [playCombo] = useSound(successChime)

  useEffect(() => {
    if (combo === 0) return
    
    const timer = setTimeout(() => {
      setCombo(0)
    }, 2000)
    
    return () => clearTimeout(timer)
  }, [combo])

  const hit = () => {
    const newCombo = combo + 1
    setCombo(newCombo)
    
    // Increase pitch with combo
    const playbackRate = Math.min(1 + (newCombo * 0.1), 2.5)
    playHit({ playbackRate })
    
    // Play special sound at combo milestones
    if (newCombo % 10 === 0) {
      setTimeout(() => playCombo(), 100)
    }
  }

  return (
    <div className="space-y-4">
      <div className="text-center">
        <div className="text-6xl font-bold">{combo}</div>
        <div className="text-sm text-muted-foreground">Combo</div>
      </div>
      
      <Button onClick={hit} className="w-full">
        Hit!
      </Button>
      
      {combo >= 10 && (
        <div className="text-center text-yellow-500 font-bold animate-pulse">
          🔥 COMBO x{combo}!
        </div>
      )}
    </div>
  )
}

Health System

Use different sounds for damage and healing:
import { useState } from "react"
import { useSound } from "@/hooks/use-sound"
import { errorBuzz } from "@/sounds/error-buzz"
import { successChime } from "@/sounds/success-chime"
import { Button } from "@/components/ui/button"

export function HealthBar() {
  const [health, setHealth] = useState(100)
  const [playDamage] = useSound(errorBuzz)
  const [playHeal] = useSound(successChime)

  const takeDamage = (amount: number) => {
    playDamage({ playbackRate: 0.8 })
    setHealth(Math.max(0, health - amount))
  }

  const heal = (amount: number) => {
    playHeal({ playbackRate: 1.2 })
    setHealth(Math.min(100, health + amount))
  }

  return (
    <div className="space-y-4">
      <div className="space-y-2">
        <div className="flex justify-between text-sm">
          <span>Health</span>
          <span>{health}/100</span>
        </div>
        <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
          <div 
            className="h-full bg-green-500 transition-all duration-300"
            style={{ 
              width: `${health}%`,
              backgroundColor: health < 30 ? '#ef4444' : health < 60 ? '#f59e0b' : '#22c55e'
            }}
          />
        </div>
      </div>
      
      <div className="flex gap-2">
        <Button 
          onClick={() => takeDamage(20)}
          variant="destructive"
          disabled={health === 0}
        >
          Take Damage (-20)
        </Button>
        <Button 
          onClick={() => heal(30)}
          variant="outline"
          disabled={health === 100}
        >
          Heal (+30)
        </Button>
      </div>
    </div>
  )
}
For game audio, consider using lower volumes (0.5-0.7) for background actions and higher volumes (0.8-1.0) for important events like achievements.

Troubleshooting

Use the interrupt option to stop previous sounds:
const [playJump] = useSound(jump8bit, { interrupt: true })
Cap the maximum playback rate:
const playbackRate = Math.min(1 + (combo * 0.1), 2.0) // Max 2x speed
playSound({ playbackRate })
Preload sounds and use a single hook instance:
// ✅ Good - one hook instance
const [playSound] = useSound(sound)

// ❌ Bad - creating new instances
buttons.map(() => {
  const [play] = useSound(sound) // Don't do this!
})

Available Game Sounds

  • jump-8bit - Classic 8-bit jump sound (467ms)
  • coin-collect - Cheerful coin collection (441ms)
  • click-8bit - Retro-style click (91ms)
  • arcade-mode - Arcade game start fanfare (1630ms)
  • battle-mode - Battle sequence intro (1507ms)
  • begin - Game/level start sound (1223ms)
Install all game sounds:
npx soundcn@latest add jump-8bit coin-collect click-8bit arcade-mode battle-mode begin

Build docs developers (and LLMs) love