Spaces:
Running
Running
Okay, so I want a html based game that is like space invaders, but shooting the aliens causes a note to begin playing and looping. The location of the invader when shot should help inform the pitch and instrument that is added to the song. The song should always be in tune and in proper tempo (it can speed up as the invaders do, but it should always sound GOOD).
Browse files- README.md +7 -4
- index.html +348 -18
README.md
CHANGED
|
@@ -1,10 +1,13 @@
|
|
| 1 |
---
|
| 2 |
-
title: Cosmic Sound Invaders
|
| 3 |
-
emoji: š
|
| 4 |
colorFrom: green
|
| 5 |
-
colorTo:
|
|
|
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
|
|
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Cosmic Sound Invaders šµš¾
|
|
|
|
| 3 |
colorFrom: green
|
| 4 |
+
colorTo: pink
|
| 5 |
+
emoji: š³
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
| 8 |
+
tags:
|
| 9 |
+
- deepsite-v3
|
| 10 |
---
|
| 11 |
|
| 12 |
+
# Welcome to your new DeepSite project!
|
| 13 |
+
This project was created with [DeepSite](https://deepsite.hf.co).
|
index.html
CHANGED
|
@@ -1,19 +1,349 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
</html>
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Cosmic Sound Invaders</title>
|
| 7 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 8 |
+
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
| 9 |
+
<script src="https://unpkg.com/feather-icons"></script>
|
| 10 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.49/Tone.js"></script>
|
| 11 |
+
<style>
|
| 12 |
+
#gameCanvas {
|
| 13 |
+
background: linear-gradient(to bottom, #0f172a, #1e293b);
|
| 14 |
+
border-radius: 12px;
|
| 15 |
+
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
|
| 16 |
+
}
|
| 17 |
+
.music-note {
|
| 18 |
+
position: absolute;
|
| 19 |
+
font-size: 24px;
|
| 20 |
+
animation: float-up 1s ease-out forwards;
|
| 21 |
+
opacity: 0.8;
|
| 22 |
+
}
|
| 23 |
+
@keyframes float-up {
|
| 24 |
+
0% { transform: translateY(0); opacity: 0.8; }
|
| 25 |
+
100% { transform: translateY(-50px); opacity: 0; }
|
| 26 |
+
}
|
| 27 |
+
</style>
|
| 28 |
+
</head>
|
| 29 |
+
<body class="bg-slate-900 text-white min-h-screen flex flex-col items-center justify-center p-4">
|
| 30 |
+
<div class="max-w-4xl w-full text-center mb-8">
|
| 31 |
+
<h1 class="text-5xl font-bold mb-2 bg-clip-text text-transparent bg-gradient-to-r from-purple-400 via-pink-500 to-indigo-500">
|
| 32 |
+
Cosmic Sound Invaders
|
| 33 |
+
</h1>
|
| 34 |
+
<p class="text-xl text-slate-300 mb-6">
|
| 35 |
+
Shoot aliens to create an intergalactic symphony!
|
| 36 |
+
</p>
|
| 37 |
+
<div class="flex justify-center gap-4 mb-8">
|
| 38 |
+
<button id="startBtn" class="px-6 py-3 bg-green-600 hover:bg-green-700 rounded-lg font-medium transition-all shadow-lg hover:shadow-green-500/30 flex items-center gap-2">
|
| 39 |
+
<i data-feather="play"></i> Start Game
|
| 40 |
+
</button>
|
| 41 |
+
<button id="muteBtn" class="px-6 py-3 bg-slate-700 hover:bg-slate-600 rounded-lg font-medium transition-all flex items-center gap-2">
|
| 42 |
+
<i data-feather="volume-2"></i> Sound On
|
| 43 |
+
</button>
|
| 44 |
+
</div>
|
| 45 |
+
</div>
|
| 46 |
+
|
| 47 |
+
<div class="relative">
|
| 48 |
+
<canvas id="gameCanvas" width="800" height="500" class="w-full max-w-full"></canvas>
|
| 49 |
+
<div id="noteEffects" class="pointer-events-none"></div>
|
| 50 |
+
</div>
|
| 51 |
+
|
| 52 |
+
<div class="mt-8 w-full max-w-4xl">
|
| 53 |
+
<div class="bg-slate-800 bg-opacity-50 rounded-xl p-6 backdrop-blur-sm">
|
| 54 |
+
<h2 class="text-2xl font-semibold mb-4 text-indigo-300">Your Cosmic Composition</h2>
|
| 55 |
+
<div id="activeInstruments" class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6"></div>
|
| 56 |
+
<div class="h-24 bg-slate-900 rounded-lg p-4 flex items-center justify-center">
|
| 57 |
+
<p id="currentTempo" class="text-lg">Tempo: 120 BPM</p>
|
| 58 |
+
</div>
|
| 59 |
+
</div>
|
| 60 |
+
</div>
|
| 61 |
+
|
| 62 |
+
<div class="mt-12 text-slate-400 text-sm flex items-center gap-2">
|
| 63 |
+
<i data-feather="info"></i>
|
| 64 |
+
<span>Shoot aliens to add notes to your song! Higher aliens = higher pitch</span>
|
| 65 |
+
</div>
|
| 66 |
+
|
| 67 |
+
<script>
|
| 68 |
+
// Initialize Tone.js
|
| 69 |
+
await Tone.start();
|
| 70 |
+
const synth = new Tone.PolySynth(Tone.Synth).toDestination();
|
| 71 |
+
const fmSynth = new Tone.PolySynth(Tone.FMSynth).toDestination();
|
| 72 |
+
const amSynth = new Tone.PolySynth(Tone.AMSynth).toDestination();
|
| 73 |
+
const pluckSynth = new Tone.PolySynth(Tone.PluckSynth).toDestination();
|
| 74 |
+
|
| 75 |
+
const instruments = [synth, fmSynth, amSynth, pluckSynth];
|
| 76 |
+
const instrumentNames = ["Space Lead", "FM Waves", "AM Modulation", "Pluck Strings"];
|
| 77 |
+
const instrumentColors = ["text-purple-400", "text-blue-400", "text-pink-400", "text-green-400"];
|
| 78 |
+
|
| 79 |
+
// Game variables
|
| 80 |
+
const canvas = document.getElementById('gameCanvas');
|
| 81 |
+
const ctx = canvas.getContext('2d');
|
| 82 |
+
let gameRunning = false;
|
| 83 |
+
let isMuted = false;
|
| 84 |
+
let score = 0;
|
| 85 |
+
let lives = 3;
|
| 86 |
+
let tempo = 120;
|
| 87 |
+
|
| 88 |
+
// Player
|
| 89 |
+
const player = {
|
| 90 |
+
x: canvas.width / 2,
|
| 91 |
+
y: canvas.height - 30,
|
| 92 |
+
width: 60,
|
| 93 |
+
height: 20,
|
| 94 |
+
speed: 8,
|
| 95 |
+
color: '#ec4899'
|
| 96 |
+
};
|
| 97 |
+
|
| 98 |
+
// Bullets
|
| 99 |
+
const bullets = [];
|
| 100 |
+
const bulletSpeed = 8;
|
| 101 |
+
|
| 102 |
+
// Aliens
|
| 103 |
+
const aliens = [];
|
| 104 |
+
const alienWidth = 40;
|
| 105 |
+
const alienHeight = 30;
|
| 106 |
+
const alienPadding = 20;
|
| 107 |
+
const alienOffsetTop = 60;
|
| 108 |
+
const alienOffsetLeft = 60;
|
| 109 |
+
const alienRows = 4;
|
| 110 |
+
const alienCols = 8;
|
| 111 |
+
|
| 112 |
+
// Active notes (sounding notes)
|
| 113 |
+
const activeNotes = [];
|
| 114 |
+
|
| 115 |
+
// Initialize game
|
| 116 |
+
function initGame() {
|
| 117 |
+
bullets.length = 0;
|
| 118 |
+
aliens.length = 0;
|
| 119 |
+
activeNotes.length = 0;
|
| 120 |
+
document.getElementById('activeInstruments').innerHTML = '';
|
| 121 |
+
score = 0;
|
| 122 |
+
lives = 3;
|
| 123 |
+
tempo = 120;
|
| 124 |
+
document.getElementById('currentTempo').textContent = `Tempo: ${tempo} BPM`;
|
| 125 |
+
|
| 126 |
+
// Create aliens
|
| 127 |
+
for (let r = 0; r < alienRows; r++) {
|
| 128 |
+
for (let c = 0; c < alienCols; c++) {
|
| 129 |
+
aliens.push({
|
| 130 |
+
x: alienOffsetLeft + c * (alienWidth + alienPadding),
|
| 131 |
+
y: alienOffsetTop + r * (alienHeight + alienPadding),
|
| 132 |
+
width: alienWidth,
|
| 133 |
+
height: alienHeight,
|
| 134 |
+
alive: true,
|
| 135 |
+
row: r,
|
| 136 |
+
col: c
|
| 137 |
+
});
|
| 138 |
+
}
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
gameRunning = true;
|
| 142 |
+
animate();
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
// Draw player
|
| 146 |
+
function drawPlayer() {
|
| 147 |
+
ctx.fillStyle = player.color;
|
| 148 |
+
ctx.fillRect(player.x - player.width / 2, player.y - player.height / 2, player.width, player.height);
|
| 149 |
+
|
| 150 |
+
// Draw player ship details
|
| 151 |
+
ctx.fillStyle = '#f97316';
|
| 152 |
+
ctx.beginPath();
|
| 153 |
+
ctx.moveTo(player.x, player.y - player.height / 2);
|
| 154 |
+
ctx.lineTo(player.x + 10, player.y - player.height / 2 - 15);
|
| 155 |
+
ctx.lineTo(player.x - 10, player.y - player.height / 2 - 15);
|
| 156 |
+
ctx.closePath();
|
| 157 |
+
ctx.fill();
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
// Draw bullets
|
| 161 |
+
function drawBullets() {
|
| 162 |
+
ctx.fillStyle = '#facc15';
|
| 163 |
+
bullets.forEach(bullet => {
|
| 164 |
+
ctx.beginPath();
|
| 165 |
+
ctx.arc(bullet.x, bullet.y, 5, 0, Math.PI * 2);
|
| 166 |
+
ctx.fill();
|
| 167 |
+
});
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
// Draw aliens
|
| 171 |
+
function drawAliens() {
|
| 172 |
+
aliens.forEach(alien => {
|
| 173 |
+
if (alien.alive) {
|
| 174 |
+
// Alien body
|
| 175 |
+
ctx.fillStyle = r % 2 === 0 ? '#4ade80' : '#60a5fa';
|
| 176 |
+
ctx.fillRect(alien.x, alien.y, alien.width, alien.height);
|
| 177 |
+
|
| 178 |
+
// Alien details
|
| 179 |
+
ctx.fillStyle = '#1e293b';
|
| 180 |
+
ctx.beginPath();
|
| 181 |
+
ctx.arc(alien.x + 10, alien.y + 10, 4, 0, Math.PI * 2);
|
| 182 |
+
ctx.arc(alien.x + alien.width - 10, alien.y + 10, 4, 0, Math.PI * 2);
|
| 183 |
+
ctx.fill();
|
| 184 |
+
|
| 185 |
+
ctx.fillRect(alien.x + alien.width / 2 - 5, alien.y + 15, 10, 5);
|
| 186 |
+
}
|
| 187 |
+
});
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
// Update game state
|
| 191 |
+
function update() {
|
| 192 |
+
// Move bullets
|
| 193 |
+
for (let i = bullets.length - 1; i >= 0; i--) {
|
| 194 |
+
bullets[i].y -= bulletSpeed;
|
| 195 |
+
|
| 196 |
+
// Remove bullets that are off screen
|
| 197 |
+
if (bullets[i].y < 0) {
|
| 198 |
+
bullets.splice(i, 1);
|
| 199 |
+
continue;
|
| 200 |
+
}
|
| 201 |
+
|
| 202 |
+
// Check for collisions with aliens
|
| 203 |
+
for (let j = 0; j < aliens.length; j++) {
|
| 204 |
+
if (aliens[j].alive &&
|
| 205 |
+
bullets[i].x > aliens[j].x &&
|
| 206 |
+
bullets[i].x < aliens[j].x + aliens[j].width &&
|
| 207 |
+
bullets[i].y > aliens[j].y &&
|
| 208 |
+
bullets[i].y < aliens[j].y + aliens[j].height) {
|
| 209 |
+
|
| 210 |
+
// Alien hit!
|
| 211 |
+
aliens[j].alive = false;
|
| 212 |
+
bullets.splice(i, 1);
|
| 213 |
+
score += 10;
|
| 214 |
+
|
| 215 |
+
// Create a musical note based on alien position
|
| 216 |
+
createMusicNote(aliens[j].x, aliens[j].y, aliens[j].row, aliens[j].col);
|
| 217 |
+
break;
|
| 218 |
+
}
|
| 219 |
+
}
|
| 220 |
+
}
|
| 221 |
+
|
| 222 |
+
// Move aliens (simple left-right movement)
|
| 223 |
+
// In a real game this would be more sophisticated
|
| 224 |
+
const alienSpeed = 1 + score / 500;
|
| 225 |
+
|
| 226 |
+
// Check if any aliens have reached the bottom
|
| 227 |
+
aliens.forEach(alien => {
|
| 228 |
+
if (alien.alive && alien.y + alien.height > canvas.height - 20) {
|
| 229 |
+
lives--;
|
| 230 |
+
if (lives <= 0) {
|
| 231 |
+
gameRunning = false;
|
| 232 |
+
alert(`Game Over! Your cosmic score: ${score}`);
|
| 233 |
+
}
|
| 234 |
+
}
|
| 235 |
+
});
|
| 236 |
+
|
| 237 |
+
// Increase tempo based on score
|
| 238 |
+
tempo = Math.min(200, 120 + Math.floor(score / 100));
|
| 239 |
+
document.getElementById('currentTempo').textContent = `Tempo: ${tempo} BPM`;
|
| 240 |
+
Tone.Transport.bpm.value = tempo;
|
| 241 |
+
}
|
| 242 |
+
|
| 243 |
+
// Create a musical note when alien is hit
|
| 244 |
+
function createMusicNote(x, y, row, col) {
|
| 245 |
+
if (isMuted) return;
|
| 246 |
+
|
| 247 |
+
// Determine pitch based on vertical position (row)
|
| 248 |
+
const notes = ['C4', 'D4', 'E4', 'F4', 'G4', 'A4', 'B4', 'C5'];
|
| 249 |
+
const noteIndex = row % notes.length;
|
| 250 |
+
const note = notes[noteIndex];
|
| 251 |
+
|
| 252 |
+
// Choose instrument based on column
|
| 253 |
+
const instrumentIndex = col % instruments.length;
|
| 254 |
+
const instrument = instruments[instrumentIndex];
|
| 255 |
+
|
| 256 |
+
// Play the note
|
| 257 |
+
const now = Tone.now();
|
| 258 |
+
instrument.triggerAttackRelease(note, "8n", now);
|
| 259 |
+
|
| 260 |
+
// Add visual note effect
|
| 261 |
+
const noteEffect = document.createElement('div');
|
| 262 |
+
noteEffect.className = `music-note ${instrumentColors[instrumentIndex]}`;
|
| 263 |
+
noteEffect.style.left = `${x}px`;
|
| 264 |
+
noteEffect.style.top = `${y}px`;
|
| 265 |
+
noteEffect.textContent = note;
|
| 266 |
+
document.getElementById('noteEffects').appendChild(noteEffect);
|
| 267 |
+
|
| 268 |
+
// Remove after animation
|
| 269 |
+
setTimeout(() => {
|
| 270 |
+
noteEffect.remove();
|
| 271 |
+
}, 1000);
|
| 272 |
+
|
| 273 |
+
// Add to active instruments display if not already there
|
| 274 |
+
if (!activeNotes.includes(instrumentIndex)) {
|
| 275 |
+
activeNotes.push(instrumentIndex);
|
| 276 |
+
|
| 277 |
+
const instrumentCard = document.createElement('div');
|
| 278 |
+
instrumentCard.className = `bg-slate-700 bg-opacity-70 rounded-lg p-3 flex items-center gap-3 ${instrumentColors[instrumentIndex]}`;
|
| 279 |
+
instrumentCard.innerHTML = `
|
| 280 |
+
<i data-feather="music"></i>
|
| 281 |
+
<div>
|
| 282 |
+
<div class="font-medium">${instrumentNames[instrumentIndex]}</div>
|
| 283 |
+
<div class="text-xs">Playing: ${note}</div>
|
| 284 |
+
</div>
|
| 285 |
+
`;
|
| 286 |
+
document.getElementById('activeInstruments').appendChild(instrumentCard);
|
| 287 |
+
feather.replace();
|
| 288 |
+
}
|
| 289 |
+
}
|
| 290 |
+
|
| 291 |
+
// Main game loop
|
| 292 |
+
function animate() {
|
| 293 |
+
if (!gameRunning) return;
|
| 294 |
+
|
| 295 |
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
| 296 |
+
|
| 297 |
+
update();
|
| 298 |
+
drawPlayer();
|
| 299 |
+
drawBullets();
|
| 300 |
+
drawAliens();
|
| 301 |
+
|
| 302 |
+
requestAnimationFrame(animate);
|
| 303 |
+
}
|
| 304 |
+
|
| 305 |
+
// Event listeners
|
| 306 |
+
document.addEventListener('keydown', (e) => {
|
| 307 |
+
if (!gameRunning) return;
|
| 308 |
+
|
| 309 |
+
switch(e.key) {
|
| 310 |
+
case 'ArrowLeft':
|
| 311 |
+
player.x = Math.max(player.width / 2, player.x - player.speed);
|
| 312 |
+
break;
|
| 313 |
+
case 'ArrowRight':
|
| 314 |
+
player.x = Math.min(canvas.width - player.width / 2, player.x + player.speed);
|
| 315 |
+
break;
|
| 316 |
+
case ' ':
|
| 317 |
+
bullets.push({
|
| 318 |
+
x: player.x,
|
| 319 |
+
y: player.y - player.height / 2 - 15
|
| 320 |
+
});
|
| 321 |
+
break;
|
| 322 |
+
}
|
| 323 |
+
});
|
| 324 |
+
|
| 325 |
+
document.getElementById('startBtn').addEventListener('click', () => {
|
| 326 |
+
initGame();
|
| 327 |
+
});
|
| 328 |
+
|
| 329 |
+
document.getElementById('muteBtn').addEventListener('click', () => {
|
| 330 |
+
isMuted = !isMuted;
|
| 331 |
+
const btn = document.getElementById('muteBtn');
|
| 332 |
+
if (isMuted) {
|
| 333 |
+
btn.innerHTML = '<i data-feather="volume-x"></i> Sound Off';
|
| 334 |
+
Tone.Transport.stop();
|
| 335 |
+
} else {
|
| 336 |
+
btn.innerHTML = '<i data-feather="volume-2"></i> Sound On';
|
| 337 |
+
Tone.Transport.start();
|
| 338 |
+
}
|
| 339 |
+
feather.replace();
|
| 340 |
+
});
|
| 341 |
+
|
| 342 |
+
// Start with muted audio until user interaction
|
| 343 |
+
Tone.Transport.stop();
|
| 344 |
+
isMuted = true;
|
| 345 |
+
document.getElementById('muteBtn').innerHTML = '<i data-feather="volume-x"></i> Sound Off';
|
| 346 |
+
feather.replace();
|
| 347 |
+
</script>
|
| 348 |
+
</body>
|
| 349 |
</html>
|