sagar007 commited on
Commit
9d6876b
·
verified ·
1 Parent(s): c8d18e3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +51 -212
app.py CHANGED
@@ -1,71 +1,18 @@
1
  import gradio as gr
2
- import tempfile
3
- import os
4
 
5
- # Create a temporary HTML file with the game
6
- def create_game_html():
7
- html_content = """
8
  <!DOCTYPE html>
9
  <html>
10
  <head>
11
  <title>Bird Shooter Game</title>
12
  <style>
13
- body {
14
- margin: 0;
15
- padding: 0;
16
- overflow: hidden;
17
- background-color: #87CEEB;
18
- display: flex;
19
- justify-content: center;
20
- align-items: center;
21
- height: 100vh;
22
- font-family: Arial, sans-serif;
23
- }
24
- #game-container {
25
- position: relative;
26
- width: 800px;
27
- height: 600px;
28
- border: 2px solid black;
29
- background-color: #87CEEB;
30
- overflow: hidden;
31
- }
32
- #score {
33
- position: absolute;
34
- top: 10px;
35
- left: 10px;
36
- font-size: 24px;
37
- color: white;
38
- text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
39
- }
40
- #game-over {
41
- position: absolute;
42
- top: 50%;
43
- left: 50%;
44
- transform: translate(-50%, -50%);
45
- font-size: 48px;
46
- color: red;
47
- text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
48
- display: none;
49
- }
50
- #restart-button {
51
- position: absolute;
52
- top: 60%;
53
- left: 50%;
54
- transform: translate(-50%, -50%);
55
- padding: 10px 20px;
56
- font-size: 24px;
57
- background-color: #4CAF50;
58
- color: white;
59
- border: none;
60
- border-radius: 5px;
61
- cursor: pointer;
62
- display: none;
63
- }
64
- .cloud {
65
- position: absolute;
66
- fill: white;
67
- opacity: 0.8;
68
- }
69
  </style>
70
  </head>
71
  <body>
@@ -75,21 +22,17 @@ def create_game_html():
75
  <div id="game-over">GAME OVER</div>
76
  <button id="restart-button">Restart</button>
77
  </div>
78
-
79
  <script>
80
- // Wait for window to fully load before initializing game
81
- window.onload = function() {
82
  const gameCanvas = document.getElementById('game-canvas');
83
  const scoreDisplay = document.getElementById('score');
84
  const gameOverDisplay = document.getElementById('game-over');
85
  const restartButton = document.getElementById('restart-button');
86
-
87
  let score = 0;
88
  let gameRunning = true;
89
  let birds = [];
90
  let explosions = [];
91
-
92
- // Create clouds in the background
93
  function createClouds() {
94
  const cloudCount = 5;
95
  for (let i = 0; i < cloudCount; i++) {
@@ -102,8 +45,6 @@ def create_game_html():
102
  cloud.setAttribute("opacity", "0.8");
103
  cloud.classList.add("cloud");
104
  gameCanvas.appendChild(cloud);
105
-
106
- // Create smaller ellipse attached to the cloud
107
  const cloudPart = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
108
  cloudPart.setAttribute("cx", parseFloat(cloud.getAttribute("cx")) + 30);
109
  cloudPart.setAttribute("cy", parseFloat(cloud.getAttribute("cy")) - 5);
@@ -114,8 +55,7 @@ def create_game_html():
114
  gameCanvas.appendChild(cloudPart);
115
  }
116
  }
117
-
118
- // Bird class
119
  class Bird {
120
  constructor() {
121
  this.x = -50;
@@ -124,12 +64,10 @@ def create_game_html():
124
  this.size = 30 + Math.random() * 20;
125
  this.element = this.createBirdElement();
126
  gameCanvas.appendChild(this.element);
 
127
  }
128
-
129
  createBirdElement() {
130
  const group = document.createElementNS("http://www.w3.org/2000/svg", "g");
131
-
132
- // Bird body
133
  const body = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
134
  body.setAttribute("cx", "0");
135
  body.setAttribute("cy", "0");
@@ -137,33 +75,22 @@ def create_game_html():
137
  body.setAttribute("ry", this.size / 3);
138
  body.setAttribute("fill", this.getRandomColor());
139
  group.appendChild(body);
140
-
141
- // Bird head
142
  const head = document.createElementNS("http://www.w3.org/2000/svg", "circle");
143
  head.setAttribute("cx", this.size / 2);
144
  head.setAttribute("cy", -this.size / 6);
145
  head.setAttribute("r", this.size / 4);
146
  head.setAttribute("fill", this.getRandomColor());
147
  group.appendChild(head);
148
-
149
- // Bird eye
150
  const eye = document.createElementNS("http://www.w3.org/2000/svg", "circle");
151
  eye.setAttribute("cx", this.size / 2 + this.size / 8);
152
  eye.setAttribute("cy", -this.size / 6 - this.size / 8);
153
  eye.setAttribute("r", this.size / 10);
154
  eye.setAttribute("fill", "black");
155
  group.appendChild(eye);
156
-
157
- // Bird beak
158
  const beak = document.createElementNS("http://www.w3.org/2000/svg", "polygon");
159
- beak.setAttribute("points",
160
- `${this.size / 2 + this.size / 4},-${this.size / 6}
161
- ${this.size},0
162
- ${this.size / 2 + this.size / 4},${this.size / 10}`);
163
  beak.setAttribute("fill", "orange");
164
  group.appendChild(beak);
165
-
166
- // Bird wings
167
  const wing = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
168
  wing.setAttribute("cx", "0");
169
  wing.setAttribute("cy", this.size / 4);
@@ -172,40 +99,32 @@ def create_game_html():
172
  wing.setAttribute("fill", this.getRandomColor());
173
  wing.setAttribute("class", "wing");
174
  group.appendChild(wing);
175
-
176
  return group;
177
  }
178
-
179
  getRandomColor() {
180
  const colors = ["#FF5733", "#33FF57", "#3357FF", "#F3FF33", "#FF33F3", "#33FFF3"];
181
  return colors[Math.floor(Math.random() * colors.length)];
182
  }
183
-
184
  update() {
185
  this.x += this.speed;
186
  this.element.setAttribute("transform", `translate(${this.x}, ${this.y})`);
187
-
188
- // Animate wings
189
  const wing = this.element.querySelector(".wing");
190
  if (wing) {
191
  const wingAngle = 15 * Math.sin(Date.now() / 100);
192
  wing.setAttribute("transform", `rotate(${wingAngle})`);
193
  }
194
-
195
- // Check if bird has left the screen
196
  if (this.x > 850) {
197
  this.remove();
 
198
  return false;
199
  }
200
  return true;
201
  }
202
-
203
  remove() {
204
  if (this.element.parentNode) {
205
  gameCanvas.removeChild(this.element);
206
  }
207
  }
208
-
209
  checkHit(x, y) {
210
  const birdX = this.x;
211
  const birdY = this.y;
@@ -213,8 +132,7 @@ def create_game_html():
213
  return distance < this.size;
214
  }
215
  }
216
-
217
- // Explosion class
218
  class Explosion {
219
  constructor(x, y, size) {
220
  this.x = x;
@@ -226,14 +144,10 @@ def create_game_html():
226
  gameCanvas.appendChild(this.element);
227
  this.playSound();
228
  }
229
-
230
  createExplosionElement() {
231
  const group = document.createElementNS("http://www.w3.org/2000/svg", "g");
232
-
233
- // Create explosion particles
234
  const colors = ["#FF0000", "#FF7700", "#FFFF00"];
235
  const particleCount = 12;
236
-
237
  for (let i = 0; i < particleCount; i++) {
238
  const angle = (i / particleCount) * 2 * Math.PI;
239
  const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
@@ -245,8 +159,6 @@ def create_game_html():
245
  circle.setAttribute("data-angle", angle);
246
  group.appendChild(circle);
247
  }
248
-
249
- // Add central explosion
250
  const center = document.createElementNS("http://www.w3.org/2000/svg", "circle");
251
  center.setAttribute("cx", 0);
252
  center.setAttribute("cy", 0);
@@ -254,210 +166,137 @@ def create_game_html():
254
  center.setAttribute("fill", "#FF0000");
255
  center.setAttribute("class", "center");
256
  group.appendChild(center);
257
-
258
  group.setAttribute("transform", `translate(${this.x}, ${this.y})`);
259
  return group;
260
  }
261
-
262
  playSound() {
263
- try {
264
- // Create explosion sound
265
- const explosion = new Audio();
266
- explosion.src = "data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=";
267
- explosion.volume = 0.3;
268
- explosion.play();
269
- } catch (e) {
270
- console.log("Sound error:", e);
271
- }
272
  }
273
-
274
  update() {
275
  this.frame++;
276
-
277
- // Update explosion size and opacity
278
  const center = this.element.querySelector(".center");
279
  const sizeMultiplier = 1 + this.frame / 5;
280
  center.setAttribute("r", (this.size / 2) * sizeMultiplier);
281
  center.setAttribute("opacity", 1 - (this.frame / this.maxFrames));
282
-
283
- // Update particles
284
  const particles = this.element.querySelectorAll(".particle");
285
  particles.forEach(particle => {
286
  const angle = parseFloat(particle.getAttribute("data-angle"));
287
  const distance = (this.size / 3) + (this.frame * 2);
288
-
289
  const x = Math.cos(angle) * distance;
290
  const y = Math.sin(angle) * distance;
291
-
292
  particle.setAttribute("cx", x);
293
  particle.setAttribute("cy", y);
294
  particle.setAttribute("opacity", 1 - (this.frame / this.maxFrames));
295
  particle.setAttribute("r", this.size / 8 * (1 - this.frame / this.maxFrames));
296
  });
297
-
298
- // Check if explosion is finished
299
  if (this.frame >= this.maxFrames) {
300
  this.remove();
301
  return false;
302
  }
303
  return true;
304
  }
305
-
306
  remove() {
307
  if (this.element.parentNode) {
308
  gameCanvas.removeChild(this.element);
309
  }
310
  }
311
  }
312
-
313
- // Initialize the game
314
  function initGame() {
315
- console.log("Initializing game...");
316
  score = 0;
317
  gameRunning = true;
318
  scoreDisplay.textContent = `Score: ${score}`;
319
  gameOverDisplay.style.display = 'none';
320
  restartButton.style.display = 'none';
321
-
322
- // Remove all birds and explosions
323
  birds.forEach(bird => bird.remove());
324
  explosions.forEach(explosion => explosion.remove());
325
  birds = [];
326
  explosions = [];
327
-
328
- // Clear any existing elements
329
  while (gameCanvas.firstChild) {
330
  gameCanvas.removeChild(gameCanvas.firstChild);
331
  }
332
-
333
- // Create clouds
334
  createClouds();
335
-
336
- // Immediately create first bird to make sure something appears
337
- birds.push(new Bird());
338
-
339
- // Start game loop
340
  gameLoop();
341
- console.log("Game loop started");
342
  }
343
-
344
- // Game loop
345
  function gameLoop() {
346
- if (!gameRunning) return;
347
-
348
- // Create new birds randomly
349
- if (Math.random() < 0.02) {
 
 
350
  birds.push(new Bird());
 
351
  }
352
-
353
- // Update birds
354
  for (let i = birds.length - 1; i >= 0; i--) {
355
  if (!birds[i].update()) {
356
  birds.splice(i, 1);
357
  }
358
  }
359
-
360
- // Update explosions
361
  for (let i = explosions.length - 1; i >= 0; i--) {
362
  if (!explosions[i].update()) {
363
  explosions.splice(i, 1);
364
  }
365
  }
366
-
367
- requestAnimationFrame(gameLoop);
368
  }
369
-
370
- // Handle mouse clicks
371
  gameCanvas.addEventListener('click', (e) => {
372
  if (!gameRunning) return;
373
-
374
  const rect = gameCanvas.getBoundingClientRect();
375
  const x = e.clientX - rect.left;
376
  const y = e.clientY - rect.top;
377
-
378
  let hit = false;
379
-
380
- // Check if any bird was hit
381
  for (let i = birds.length - 1; i >= 0; i--) {
382
  if (birds[i].checkHit(x, y)) {
383
- // Create explosion
384
  const birdX = birds[i].x;
385
  const birdY = birds[i].y;
386
  const birdSize = birds[i].size;
387
-
388
- // Remove the bird
389
  birds[i].remove();
390
  birds.splice(i, 1);
391
-
392
- // Create explosion
393
  explosions.push(new Explosion(birdX, birdY, birdSize * 2));
394
-
395
- // Increment score
396
  score += 10;
397
  scoreDisplay.textContent = `Score: ${score}`;
398
-
399
  hit = true;
 
400
  }
401
  }
402
-
403
- // Play miss sound if no bird was hit
404
  if (!hit) {
405
- try {
406
- const miss = new Audio();
407
- miss.src = "data:audio/wav;base64,UklGRiQDAABXQVZFZm10IBAAAAABAAEAESsAABErAAABAAgAZGF0YQADAABkAGQAZABkAGQAfACEAJwAsAC8AMgA1ADsAOQA7ADkANQA0AC8AKgAnACMAHQAXABMAEQAPABEADwANAA0ADQALAAsACQAHAAUAAwABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAA8AFgAaAB8AIQAnACsAMAAyADMANwA3ADcAMgA0ADAALAApACQAIQAbABYAEQAMAAUAAAAAAAAAAAAAAAAAAAAAAAAAAP//9//x//X/9f/4/wAABwANABYAHAAnADIAOABDAEsAVABdAGQAbQBzAH4AhQCKAJEAlQCYAJ4AnwCgAKIAoQCgAJwAmgCXAJIAjwCIAIMAfQB2AG4AZgBeAFQATABGAD4ANQAvACgAIgAaABUADAAIAAQAAQD+//r/9//0//H/7//u/+z/6//r/+r/6v/p/+n/6v/q/+v/7P/u/+//8f/z//X/+P/7//7/AQADAAYACQALABAAEQAUABYAGAAZAB0AHQAfACEAIgAkACUAJQAmACcAJwAoACkAKQAqACsAKwAsACwALQAtAC0ALQAuAC4ALgAuAC4ALgAtAC0ALQAsACwALAAqACkAKQAnACYAJgAkACMAIgAgAB8AHgAcABoAGQAYABYAFAAQAA4ADAAJAAcABQADAAEA//89//7//f/8//v/+v/5//j/9//2//X/9P/z//P/8v/x//D/8P/v/+7/7v/t/+3/7P/s/+v/6//q/+r/6v/p/+n/6f/p/+n/6f/p/+n/6f/p/+n/6v/q/+v/6//s/+z/7f/u/+7/7//w//H/8v/z//T/9f/2//f/+P/5//v//P/9/wAAAgADAAUABgAIAAkACwAMAA4AEAARACMACwAEAP//+//4//X/8v/v/+v/6P/l/+L/4P/e/9v/2f/X/9X/1P/S/9H/z//O/83/zf/M/8v/y//K/8r/yv/K/8v/y//L/8z/zf/O/8//0P/S/9P/1f/X/9j/2v/c/97/4f/j/+X/6P/q/+3/8P/z//X/+P/7//7/AQA=";
408
- miss.volume = 0.2;
409
- miss.play();
410
- } catch (e) {
411
- console.log("Sound error:", e);
412
- }
413
  }
414
  });
415
-
416
- // Restart game when button is clicked
417
  restartButton.addEventListener('click', () => {
418
  initGame();
 
419
  });
420
-
421
- // Initialize the game
422
- initGame();
423
- };
424
  </script>
425
  </body>
426
  </html>
427
  """
428
-
429
- # Create a temporary file to serve the HTML
430
- temp_dir = tempfile.mkdtemp()
431
- html_path = os.path.join(temp_dir, "game.html")
432
-
433
- with open(html_path, "w") as f:
434
- f.write(html_content)
435
-
436
- # Return the path to be used in the iframe
437
- return html_path
438
 
439
- def create_game():
440
- html_path = create_game_html()
441
- iframe_html = f'<iframe src="file://{html_path}" width="820" height="650" frameborder="0"></iframe>'
442
- return gr.HTML(iframe_html)
443
 
444
- # Create Gradio interface
445
  with gr.Blocks(title="Bird Shooter Game") as demo:
446
- gr.Markdown("# 🎮 Bird Shooter Game")
447
- gr.Markdown("Click on the birds to shoot them and score points!")
448
-
449
- game_interface = create_game()
450
-
451
- gr.Markdown("""
452
- ## How to Play
453
- - Click on birds to shoot them
454
- - Each hit earns you 10 points
455
- - Try to get the highest score possible!
456
-
457
- ## About
458
- This is a simple bird shooter game created with SVG and JavaScript, embedded in a Gradio app for Hugging Face Spaces.
459
- """)
460
 
461
  # Launch the app
462
- if __name__ == "__main__":
463
- demo.launch()
 
1
  import gradio as gr
 
 
2
 
3
+ # Updated HTML with fixes and debugging
4
+ game_html = """
 
5
  <!DOCTYPE html>
6
  <html>
7
  <head>
8
  <title>Bird Shooter Game</title>
9
  <style>
10
+ body { margin: 0; padding: 0; overflow: hidden; background-color: #87CEEB; display: flex; justify-content: center; align-items: center; height: 100vh; font-family: Arial, sans-serif; }
11
+ #game-container { position: relative; width: 800px; height: 600px; border: 2px solid black; background-color: #87CEEB; overflow: hidden; }
12
+ #score { position: absolute; top: 10px; left: 10px; font-size: 24px; color: white; text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5); }
13
+ #game-over { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 48px; color: red; text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5); display: none; }
14
+ #restart-button { position: absolute; top: 60%; left: 50%; transform: translate(-50%, -50%); padding: 10px 20px; font-size: 24px; background-color: #4CAF50; color: white; border: none; border-radius: 5px; cursor: pointer; display: none; }
15
+ .cloud { position: absolute; fill: white; opacity: 0.8; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  </style>
17
  </head>
18
  <body>
 
22
  <div id="game-over">GAME OVER</div>
23
  <button id="restart-button">Restart</button>
24
  </div>
 
25
  <script>
26
+ document.addEventListener('DOMContentLoaded', () => {
 
27
  const gameCanvas = document.getElementById('game-canvas');
28
  const scoreDisplay = document.getElementById('score');
29
  const gameOverDisplay = document.getElementById('game-over');
30
  const restartButton = document.getElementById('restart-button');
 
31
  let score = 0;
32
  let gameRunning = true;
33
  let birds = [];
34
  let explosions = [];
35
+
 
36
  function createClouds() {
37
  const cloudCount = 5;
38
  for (let i = 0; i < cloudCount; i++) {
 
45
  cloud.setAttribute("opacity", "0.8");
46
  cloud.classList.add("cloud");
47
  gameCanvas.appendChild(cloud);
 
 
48
  const cloudPart = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
49
  cloudPart.setAttribute("cx", parseFloat(cloud.getAttribute("cx")) + 30);
50
  cloudPart.setAttribute("cy", parseFloat(cloud.getAttribute("cy")) - 5);
 
55
  gameCanvas.appendChild(cloudPart);
56
  }
57
  }
58
+
 
59
  class Bird {
60
  constructor() {
61
  this.x = -50;
 
64
  this.size = 30 + Math.random() * 20;
65
  this.element = this.createBirdElement();
66
  gameCanvas.appendChild(this.element);
67
+ console.log('Bird created at x:', this.x, 'y:', this.y);
68
  }
 
69
  createBirdElement() {
70
  const group = document.createElementNS("http://www.w3.org/2000/svg", "g");
 
 
71
  const body = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
72
  body.setAttribute("cx", "0");
73
  body.setAttribute("cy", "0");
 
75
  body.setAttribute("ry", this.size / 3);
76
  body.setAttribute("fill", this.getRandomColor());
77
  group.appendChild(body);
 
 
78
  const head = document.createElementNS("http://www.w3.org/2000/svg", "circle");
79
  head.setAttribute("cx", this.size / 2);
80
  head.setAttribute("cy", -this.size / 6);
81
  head.setAttribute("r", this.size / 4);
82
  head.setAttribute("fill", this.getRandomColor());
83
  group.appendChild(head);
 
 
84
  const eye = document.createElementNS("http://www.w3.org/2000/svg", "circle");
85
  eye.setAttribute("cx", this.size / 2 + this.size / 8);
86
  eye.setAttribute("cy", -this.size / 6 - this.size / 8);
87
  eye.setAttribute("r", this.size / 10);
88
  eye.setAttribute("fill", "black");
89
  group.appendChild(eye);
 
 
90
  const beak = document.createElementNS("http://www.w3.org/2000/svg", "polygon");
91
+ beak.setAttribute("points", `${this.size / 2 + this.size / 4},-${this.size / 6} ${this.size},0 ${this.size / 2 + this.size / 4},${this.size / 10}`);
 
 
 
92
  beak.setAttribute("fill", "orange");
93
  group.appendChild(beak);
 
 
94
  const wing = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
95
  wing.setAttribute("cx", "0");
96
  wing.setAttribute("cy", this.size / 4);
 
99
  wing.setAttribute("fill", this.getRandomColor());
100
  wing.setAttribute("class", "wing");
101
  group.appendChild(wing);
 
102
  return group;
103
  }
 
104
  getRandomColor() {
105
  const colors = ["#FF5733", "#33FF57", "#3357FF", "#F3FF33", "#FF33F3", "#33FFF3"];
106
  return colors[Math.floor(Math.random() * colors.length)];
107
  }
 
108
  update() {
109
  this.x += this.speed;
110
  this.element.setAttribute("transform", `translate(${this.x}, ${this.y})`);
 
 
111
  const wing = this.element.querySelector(".wing");
112
  if (wing) {
113
  const wingAngle = 15 * Math.sin(Date.now() / 100);
114
  wing.setAttribute("transform", `rotate(${wingAngle})`);
115
  }
 
 
116
  if (this.x > 850) {
117
  this.remove();
118
+ console.log('Bird removed, remaining birds:', birds.length);
119
  return false;
120
  }
121
  return true;
122
  }
 
123
  remove() {
124
  if (this.element.parentNode) {
125
  gameCanvas.removeChild(this.element);
126
  }
127
  }
 
128
  checkHit(x, y) {
129
  const birdX = this.x;
130
  const birdY = this.y;
 
132
  return distance < this.size;
133
  }
134
  }
135
+
 
136
  class Explosion {
137
  constructor(x, y, size) {
138
  this.x = x;
 
144
  gameCanvas.appendChild(this.element);
145
  this.playSound();
146
  }
 
147
  createExplosionElement() {
148
  const group = document.createElementNS("http://www.w3.org/2000/svg", "g");
 
 
149
  const colors = ["#FF0000", "#FF7700", "#FFFF00"];
150
  const particleCount = 12;
 
151
  for (let i = 0; i < particleCount; i++) {
152
  const angle = (i / particleCount) * 2 * Math.PI;
153
  const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
 
159
  circle.setAttribute("data-angle", angle);
160
  group.appendChild(circle);
161
  }
 
 
162
  const center = document.createElementNS("http://www.w3.org/2000/svg", "circle");
163
  center.setAttribute("cx", 0);
164
  center.setAttribute("cy", 0);
 
166
  center.setAttribute("fill", "#FF0000");
167
  center.setAttribute("class", "center");
168
  group.appendChild(center);
 
169
  group.setAttribute("transform", `translate(${this.x}, ${this.y})`);
170
  return group;
171
  }
 
172
  playSound() {
173
+ const explosion = new Audio();
174
+ explosion.src = "data:audio/wav;base64,//uQRAAAAWMSLwUIYAAsYkXgoQwAEaYLWfkWgAI0wWs/ItAAAGDgYtAgAyN+QWaAAihwMWm4G8QQRDiMcCBcH3Cc+CDv/7xA4Tvh9Rz/y8QADBwMWgQAZG/ILNAARQ4GLTcDeIIIhxGOBAuD7hOfBB3/94gcJ3w+o5/5eIAIAAAVwWgQAVQ2ORaIQwEMAJiDg95G4nQL7mQVWI6GwRcfsZAcsKkJvxgxEjzFUgfHoSQ9Qq7KNwqHwuB13MA4a1q/DmBrHgPcmjiGoh//EwC5nGPEmS4RcfkVKOhJf+WOgoxJclFz3kgn//dBA+ya1GhurNn8zb//9NNutNuhz31f////9vt///z+IdAEAAAK4LQIAKobHItEIYCGAExBwe8jcToF9zIKrEdDYIuP2MgOWFSE34wYiR5iqQPj0JIeoVdlG4VD4XA67mAcNa1fhzA1jwHuTRxDUQ//iYBczjHiTJcIuPyKlHQkv/LHQUYkuSi57yQT//uggfZNajQ3Vmz+Zt//+mm3Wm3Q576v////+32///5/EOgAAADVghQAAAAA//uQZAUAB1WI0PZugAAAAAoQwAAAEk3nRd2qAAAAACiDgAAAAAAABCqEEQRLCgwpBGMlJkIz8jKhGvj4k6jzRnqasNKIeoh5gI7BJaC1A1AoNBjJgbyApVS4IDlZgDU5WUAxEKDNmmALHzZp0Fkz1FMTmGFl1FMEyodIavcCAUHDWrKAIA4aa2oCgILEBupZgHvAhEBcZ6joQBxS76AgccrFlczBvKLC0QI2cBoCFvfTDAo7eoOQInqDPBtvrDEZBNYN5xwNwxQRfw8ZQ5wQVLvO8OYU+mHvFLlDh05Mdg7BT6YrRPpCBznMB2r//xKJjyyOh+cImr2/4doscwD6neZjuZR4AgAABYAAAABy1xcdQtxYBYYZdifkUDgzzXaXn98Z0oi9ILU5mBjFANmRwlVJ3/6jYDAmxaiDG3/6xjQQCCKkRb/6kg/wW+kSJ5//rLobkLSiKmqP/0ikJuDaSaSf/6JiLYLEYnW/+kXg1WRVJL/9EmQ1YZIsv/6Qzwy5qk7/+tEU0nkls3/zIUMPKNX/6yZLf+kFgAfgGyLFAUwY//uQZAUABcd5UiNPVXAAAApAAAAAE0VZQKw9ISAAACgAAAAAVQIygIElVrFkBS+Jhi+EAuu+lKAkYUEIsmEAEoMeDmCETMvfSHTGkF5RWH7kz/ESHWPAq/kcCRhqBtMdokPdM7vil7RG98A2sc7zO6ZvTdM7pmOUAZTnJW+NXxqmd41dqJ6mLTXxrPpnV8avaIf5SvL7pndPvPpndJR9Kuu8fePvuiuhorgWjp7Mf/PRjxcFCPDkW31srioCExivv9lcwKEaHsf/7ow2Fl1T/9RkXgEhYElAoCLFtMArxwivDJJ+bR1HTKJdlEoTELCIqgEwVGSQ+hIm0NbK8WXcTEI0UPoa2NbG4y2K00JEWbZavJXkYaqo9CRHS55FcZTjKEk3NKoCYUnSQ0rWxrZbFKbKIhOKPZe1cJKzZSaQrIyULHDZmV5K4xySsDRKWOruanGtjLJXFEmwaIbDLX0hIPBUQPVFVkQkDoUNfSoDgQGKPekoxeGzA4DUvnn4bxzcZrtJyipKfPNy5w+9lnXwgqsiyHNeSVpemw4bWb9psYeq//uQZBoABQt4yMVxYAIAAAkQoAAAHvYpL5m6AAgAACXDAAAAD59jblTirQe9upFsmZbpMudy7Lz1X1DYsxOOSWpfPqNX2WqktK0DMvuGwlbNj44TleLPQ+Gsfb+GOWOKJoIrWb3cIMeeON6lz2umTqMXV8Mj30yWPpjoSa9ujK8SyeJP5y5mOW1D6hvLepeveEAEDo0mgCRClOEgANv3B9a6fikgUSu/DmAMATrGx7nng5p5iimPNZsfQLYB2sDLIkzRKZOHGAaUyDcpFBSLG9MCQALgAIgQs2YunOszLSAyQYPVC2YdGGeHD2dTdJk1pAHGAWDjnkcLKFymS3RQZTInzySoBwMG0QueC3gMsCEYxUqlrcxK6k1LQQcsmyYeQPdC2YfuGPASCBkcVMQQqpVJshui1tkXQJQV0OXGAZMXSOEEBRirXbVRQW7ugq7IM7rPWSZyDlM3IuNEkxzCOJ0ny2ThNkyRai1b6ev//3dzNGzNb//4uAvHT5sURcZCFcuKLhOFs8mLAAEAt4UWAAIABAAAAAB4qbHo0tIjVkUU//uQZAwABfSFz3ZqQAAAAAngwAAAE1HjMp2qAAAAACZDgAAAD5UkTE1UgZEUExqYynN1qZvqIOREEFmBcJQkwdxiFtw0qEOkGYfRDifBui9MQg4QAHAqWtAWHoCxu1Yf4VfWLPIM2mHDFsbQEVGwyqQoQcwnfHeIkNt9YnkiaS1oizycqJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=";
175
+ explosion.volume = 0.3;
176
+ explosion.play();
 
 
 
 
 
177
  }
 
178
  update() {
179
  this.frame++;
 
 
180
  const center = this.element.querySelector(".center");
181
  const sizeMultiplier = 1 + this.frame / 5;
182
  center.setAttribute("r", (this.size / 2) * sizeMultiplier);
183
  center.setAttribute("opacity", 1 - (this.frame / this.maxFrames));
 
 
184
  const particles = this.element.querySelectorAll(".particle");
185
  particles.forEach(particle => {
186
  const angle = parseFloat(particle.getAttribute("data-angle"));
187
  const distance = (this.size / 3) + (this.frame * 2);
 
188
  const x = Math.cos(angle) * distance;
189
  const y = Math.sin(angle) * distance;
 
190
  particle.setAttribute("cx", x);
191
  particle.setAttribute("cy", y);
192
  particle.setAttribute("opacity", 1 - (this.frame / this.maxFrames));
193
  particle.setAttribute("r", this.size / 8 * (1 - this.frame / this.maxFrames));
194
  });
 
 
195
  if (this.frame >= this.maxFrames) {
196
  this.remove();
197
  return false;
198
  }
199
  return true;
200
  }
 
201
  remove() {
202
  if (this.element.parentNode) {
203
  gameCanvas.removeChild(this.element);
204
  }
205
  }
206
  }
207
+
 
208
  function initGame() {
 
209
  score = 0;
210
  gameRunning = true;
211
  scoreDisplay.textContent = `Score: ${score}`;
212
  gameOverDisplay.style.display = 'none';
213
  restartButton.style.display = 'none';
 
 
214
  birds.forEach(bird => bird.remove());
215
  explosions.forEach(explosion => explosion.remove());
216
  birds = [];
217
  explosions = [];
 
 
218
  while (gameCanvas.firstChild) {
219
  gameCanvas.removeChild(gameCanvas.firstChild);
220
  }
 
 
221
  createClouds();
222
+ birds.push(new Bird()); // Start with one bird
223
+ console.log('Game initialized');
 
 
 
224
  gameLoop();
 
225
  }
226
+
 
227
  function gameLoop() {
228
+ if (!gameRunning) {
229
+ console.log('Game stopped');
230
+ return;
231
+ }
232
+ console.log('Game loop running, birds:', birds.length);
233
+ if (Math.random() < 0.1) { // Increased spawn rate for testing
234
  birds.push(new Bird());
235
+ console.log('New bird spawned');
236
  }
 
 
237
  for (let i = birds.length - 1; i >= 0; i--) {
238
  if (!birds[i].update()) {
239
  birds.splice(i, 1);
240
  }
241
  }
 
 
242
  for (let i = explosions.length - 1; i >= 0; i--) {
243
  if (!explosions[i].update()) {
244
  explosions.splice(i, 1);
245
  }
246
  }
247
+ requestAnimationFrame(gameLoop); // Ensure continuous looping
 
248
  }
249
+
 
250
  gameCanvas.addEventListener('click', (e) => {
251
  if (!gameRunning) return;
 
252
  const rect = gameCanvas.getBoundingClientRect();
253
  const x = e.clientX - rect.left;
254
  const y = e.clientY - rect.top;
 
255
  let hit = false;
 
 
256
  for (let i = birds.length - 1; i >= 0; i--) {
257
  if (birds[i].checkHit(x, y)) {
 
258
  const birdX = birds[i].x;
259
  const birdY = birds[i].y;
260
  const birdSize = birds[i].size;
 
 
261
  birds[i].remove();
262
  birds.splice(i, 1);
 
 
263
  explosions.push(new Explosion(birdX, birdY, birdSize * 2));
 
 
264
  score += 10;
265
  scoreDisplay.textContent = `Score: ${score}`;
 
266
  hit = true;
267
+ console.log('Bird hit, score:', score);
268
  }
269
  }
 
 
270
  if (!hit) {
271
+ const miss = new Audio();
272
+ miss.src = "data:audio/wav;base64,UklGRiQDAABXQVZFZm10IBAAAAABAAEAESsAABErAAABAAgAZGF0YQADAABkAGQAZABkAGQAfACEAJwAsAC8AMgA1ADsAOQA7ADkANQA0AC8AKgAnACMAHQAXABMAEQAPABEADwANAA0ADQALAAsACQAHAAUAAwABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAA8AFgAaAB8AIQAnACsAMAAyADMANwA3ADcAMgA0ADAALAApACQAIQAbABYAEQAMAAUAAAAAAAAAAAAAAAAAAAAAAAAAAP//9//x//X/9f/4/wAABwANABYAHAAnADIAOABDAEsAVABdAGQAbQBzAH4AhQCKAJEAlQCYAJ4AnwCgAKIAoQCgAJwAmgCXAJIAjwCIAIMAfQB2AG4AZgBeAFQATABGAD4ANQAvACgAIgAaABUADAAIAAQAAQD+//r/9//0//H/7//u/+z/6//r/+r/6v/p/+n/6v/q/+v/7P/u/+//8f/z//X/+P/7//7/AQADAAYACQALABAAEQAUABYAGAAZAB0AHQAfACEAIgAkACUAJQAmACcAJwAoACkAKQAqACsAKwAsACwALQAtAC0ALQAuAC4ALgAuAC4ALgAtAC0ALQAsACwALAAqACkAKQAnACYAJgAkACMAIgAgAB8AHgAcABoAGQAYABYAFAAQAA4ADAAJAAcABQADAAEA//89//7//f/8//v/+v/5//j/9//2//X/9P/z//P/8v/x//D/8P/v/+7/7v/t/+3/7P/s/+v/6//q/+r/6v/p/+n/6f/p/+n/6f/p/+n/6f/p/+n/6v/q/+v/6//s/+z/7f/u/+7/7//w//H/8v/z//T/9f/2//f/+P/5//v//P/9/wAAAgADAAUABgAIAAkACwAMAA4AEAARACMACwAEAP//+//4//X/8v/v/+v/6P/l/+L/4P/e/9v/2f/X/9X/1P/S/9H/z//O/83/zf/M/8v/y//K/8r/yv/K/8v/y//L/8z/zf/O/8//0P/S/9P/1f/X/9j/2v/c/97/4f/j/+X/6P/q/+3/8P/z//X/+P/7//7/AQA=";
273
+ miss.volume = 0.2;
274
+ miss.play();
275
+ console.log('Missed shot');
 
 
 
276
  }
277
  });
278
+
 
279
  restartButton.addEventListener('click', () => {
280
  initGame();
281
+ console.log('Game restarted');
282
  });
283
+
284
+ initGame(); // Start the game
285
+ });
 
286
  </script>
287
  </body>
288
  </html>
289
  """
 
 
 
 
 
 
 
 
 
 
290
 
291
+ # Define the Gradio interface
292
+ def launch_game():
293
+ return game_html
 
294
 
295
+ # Create the Gradio app
296
  with gr.Blocks(title="Bird Shooter Game") as demo:
297
+ gr.Markdown("# Bird Shooter Game")
298
+ gr.Markdown("Click on the birds to shoot them and earn points! If birds stop appearing, check the browser console (F12) for errors.")
299
+ game_output = gr.HTML(label="Game", value=launch_game())
 
 
 
 
 
 
 
 
 
 
 
300
 
301
  # Launch the app
302
+ demo.launch()