poingly commited on
Commit
a691bee
Ā·
verified Ā·
1 Parent(s): 8d2642e

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
Files changed (2) hide show
  1. README.md +7 -4
  2. index.html +348 -18
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Cosmic Sound Invaders
3
- emoji: šŸŒ
4
  colorFrom: green
5
- colorTo: yellow
 
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
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
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>