sagar007 commited on
Commit
596ac16
·
verified ·
1 Parent(s): cc2fb6d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +120 -158
app.py CHANGED
@@ -1,165 +1,127 @@
1
  import gradio as gr
2
- import numpy as np
3
  import time
4
- from PIL import Image, ImageDraw
5
- import io
6
- import base64
7
 
8
- # Game state class
9
- class SpaceShooter:
 
10
  def __init__(self):
11
- self.width = 480
12
- self.height = 640
13
- self.score = 0
14
- self.lives = 3
15
-
16
- # Player
17
- self.player = {
18
- "x": self.width / 2,
19
- "y": self.height - 60,
20
- "width": 40,
21
- "height": 40,
22
- "speed": 5
23
- }
24
-
25
- self.bullets = []
26
- self.enemies = []
27
- self.last_enemy_spawn = time.time()
28
- self.enemy_spawn_rate = 1.5 # seconds
29
- self.last_shot = 0
30
- self.shoot_cooldown = 0.3 # seconds
31
-
32
- def spawn_enemy(self, current_time):
33
- if current_time - self.last_enemy_spawn > self.enemy_spawn_rate:
34
- size = np.random.uniform(20, 40)
35
- self.enemies.append({
36
- "x": np.random.uniform(size/2, self.width - size/2),
37
- "y": 0,
38
- "width": size,
39
- "height": size,
40
- "speed": np.random.uniform(1, 3)
41
- })
42
- self.last_enemy_spawn = current_time
43
-
44
- def shoot(self, current_time):
45
- if current_time - self.last_shot > self.shoot_cooldown:
46
- self.bullets.append({
47
- "x": self.player["x"],
48
- "y": self.player["y"] - self.player["height"]/2,
49
- "width": 4,
50
- "height": 15,
51
- "speed": 10
52
- })
53
- self.last_shot = current_time
54
 
55
  def update(self):
 
 
 
56
  current_time = time.time()
57
-
58
- # Update bullets
59
- for bullet in self.bullets[:]:
60
- bullet["y"] -= bullet["speed"]
61
- if bullet["y"] < 0:
62
- self.bullets.remove(bullet)
63
-
64
- # Update enemies
65
- for enemy in self.enemies[:]:
66
- enemy["y"] += enemy["speed"]
67
- if enemy["y"] > self.height:
68
- self.enemies.remove(enemy)
69
- self.lives -= 1
70
-
71
- # Check collisions
72
- for bullet in self.bullets[:]:
73
- for enemy in self.enemies[:]:
74
- if (bullet["x"] < enemy["x"] + enemy["width"]/2 and
75
- bullet["x"] + bullet["width"] > enemy["x"] - enemy["width"]/2 and
76
- bullet["y"] < enemy["y"] + enemy["height"]/2 and
77
- bullet["y"] + bullet["height"] > enemy["y"] - enemy["height"]/2):
78
- self.bullets.remove(bullet)
79
- self.enemies.remove(enemy)
80
- self.score += int(enemy["width"])
81
- break
82
-
83
- # Spawn new enemies
84
- self.spawn_enemy(current_time)
85
-
86
- def draw(self):
87
- # Create image
88
- img = Image.new('RGB', (self.width, self.height), color='black')
89
- draw = ImageDraw.Draw(img)
90
-
91
- # Draw player
92
- draw.polygon([
93
- (self.player["x"], self.player["y"] - self.player["height"]/2),
94
- (self.player["x"] - self.player["width"]/2, self.player["y"] + self.player["height"]/2),
95
- (self.player["x"] + self.player["width"]/2, self.player["y"] + self.player["height"]/2)
96
- ], fill='#3498db')
97
-
98
- # Draw bullets
99
- for bullet in self.bullets:
100
- draw.rectangle([
101
- (bullet["x"] - bullet["width"]/2, bullet["y"]),
102
- (bullet["x"] + bullet["width"]/2, bullet["y"] + bullet["height"])
103
- ], fill='#ff0')
104
-
105
- # Draw enemies
106
- for enemy in self.enemies:
107
- draw.ellipse([
108
- (enemy["x"] - enemy["width"]/2, enemy["y"] - enemy["height"]/2),
109
- (enemy["x"] + enemy["width"]/2, enemy["y"] + enemy["height"]/2)
110
- ], fill='#ff5555')
111
-
112
- return img
113
-
114
- # Game instance
115
- game = SpaceShooter()
116
-
117
- def move_player(direction):
118
- if game.lives <= 0:
119
- return game.draw(), f"Game Over! Score: {game.score}"
120
-
121
- if direction == "left" and game.player["x"] > game.player["width"]/2:
122
- game.player["x"] -= game.player["speed"]
123
- elif direction == "right" and game.player["x"] < game.width - game.player["width"]/2:
124
- game.player["x"] += game.player["speed"]
125
- elif direction == "shoot":
126
- game.shoot(time.time())
127
-
128
- game.update()
129
- status = f"Score: {game.score} | Lives: {game.lives}"
130
- if game.lives <= 0:
131
- status = f"Game Over! Score: {game.score}"
132
-
133
- return game.draw(), status
134
-
135
- def reset_game():
136
- global game
137
- game = SpaceShooter()
138
- return game.draw(), f"Score: {game.score} | Lives: {game.lives}"
139
-
140
- # Gradio interface
141
- with gr.Blocks(title="Space Shooter") as demo:
142
- gr.Markdown("# Space Shooter")
143
- gr.Markdown("Use the buttons to move left, right, and shoot. Game updates after each action.")
144
-
145
- with gr.Row():
146
- game_output = gr.Image(label="Game", width=480, height=640)
147
- status_output = gr.Textbox(label="Status")
148
-
149
- with gr.Row():
150
- left_btn = gr.Button("Left")
151
- right_btn = gr.Button("Right")
152
- shoot_btn = gr.Button("Shoot")
153
- reset_btn = gr.Button("Reset")
154
-
155
- # Initial state
156
- game_output.value = game.draw()
157
- status_output.value = f"Score: {game.score} | Lives: {game.lives}"
158
-
159
- # Event handlers
160
- left_btn.click(move_player, inputs=gr.State(value="left"), outputs=[game_output, status_output])
161
- right_btn.click(move_player, inputs=gr.State(value="right"), outputs=[game_output, status_output])
162
- shoot_btn.click(move_player, inputs=gr.State(value="shoot"), outputs=[game_output, status_output])
163
- reset_btn.click(reset_game, inputs=None, outputs=[game_output, status_output])
164
-
165
- demo.launch()
 
1
  import gradio as gr
2
+ import random
3
  import time
4
+ import base64 # For audio encoding
 
 
5
 
6
+ # --- Game Logic (Adapted from your HTML/JS) ---
7
+
8
+ class Bird:
9
  def __init__(self):
10
+ self.x = -50
11
+ self.y = 100 + random.random() * 300
12
+ self.speed = 2 + random.random() * 3
13
+ self.size = 30 + random.random() * 20
14
+ self.color = self.random_color()
15
+ self.wing_angle = 0 # Initial wing angle
16
+ self.last_wing_update = time.time()
17
+
18
+
19
+ def random_color(self):
20
+ colors = ["#FF5733", "#33FF57", "#3357FF", "#F3FF33", "#FF33F3", "#33FFF3"]
21
+ return random.choice(colors)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
  def update(self):
24
+ self.x += self.speed
25
+
26
+ # Animate wings (simplified for Gradio, update every 0.1 seconds)
27
  current_time = time.time()
28
+ if current_time - self.last_wing_update > 0.1:
29
+ self.wing_angle = 15 * (1 if (int(current_time * 10) % 2 == 0) else -1) # simpler flapping
30
+ self.last_wing_update = current_time
31
+
32
+
33
+ if self.x > 850:
34
+ return False # Bird left the screen
35
+ return True
36
+
37
+ def check_hit(self, click_x, click_y):
38
+ distance = ((self.x - click_x) ** 2 + (self.y - click_y) ** 2) ** 0.5
39
+ return distance < self.size
40
+
41
+ def to_svg(self):
42
+ # Bird body (ellipse)
43
+ body = f'<ellipse cx="{self.x}" cy="{self.y}" rx="{self.size / 2}" ry="{self.size / 3}" fill="{self.color}" />'
44
+
45
+ # Bird head (circle)
46
+ head = f'<circle cx="{self.x + self.size / 2}" cy="{self.y - self.size / 6}" r="{self.size / 4}" fill="{self.color}" />'
47
+
48
+ # Bird eye (circle)
49
+ eye = f'<circle cx="{self.x + self.size / 2 + self.size / 8}" cy="{self.y - self.size / 6 - self.size / 8}" r="{self.size / 10}" fill="black" />'
50
+
51
+ # Bird beak (polygon)
52
+ beak = f'<polygon points="{self.x + self.size / 2 + self.size / 4},{self.y - self.size / 6} {self.x + self.size},{self.y} {self.x + self.size / 2 + self.size / 4},{self.y + self.size / 10}" fill="orange" />'
53
+
54
+ # Bird wing (ellipse with rotation)
55
+ wing = f'<ellipse cx="{self.x}" cy="{self.y + self.size/4}" rx="{self.size / 3}" ry="{self.size / 6}" fill="{self.color}" transform="rotate({self.wing_angle} {self.x} {self.y + self.size/4})" />'
56
+
57
+
58
+ return f'<g>{body}{head}{eye}{beak}{wing}</g>'
59
+
60
+
61
+ class Explosion:
62
+ def __init__(self, x, y, size):
63
+ self.x = x
64
+ self.y = y
65
+ self.size = size
66
+ self.frame = 0
67
+ self.max_frames = 20
68
+ self.sound_played = False # Prevent sound repetition
69
+
70
+
71
+ def update(self):
72
+ self.frame += 1
73
+ if self.frame >= self.max_frames:
74
+ return False
75
+ return True
76
+
77
+ def to_svg(self):
78
+ group = f'<g transform="translate({self.x}, {self.y})">'
79
+ colors = ["#FF0000", "#FF7700", "#FFFF00"]
80
+ particle_count = 12
81
+
82
+ for i in range(particle_count):
83
+ angle = (i / particle_count) * 2 * 3.14159 # Use a close approximation of PI
84
+ distance = (self.size / 3) + (self.frame * 2)
85
+ x = (self.size/3 + self.frame *2) * (1 if i%2 == 0 else -1)
86
+ y = (self.size/3 + self.frame*2) * (1 if i%3 ==0 else -1)
87
+ radius = self.size / 8 * (1 - self.frame / self.max_frames)
88
+ opacity = 1 - (self.frame / self.max_frames)
89
+ particle = f'<circle cx="{x}" cy="{y}" r="{radius}" fill="{random.choice(colors)}" opacity="{opacity}" />'
90
+ group += particle
91
+
92
+ center_radius = (self.size / 2) * (1 + self.frame / 5)
93
+ center_opacity = 1 - (self.frame / self.max_frames)
94
+ center = f'<circle cx="0" cy="0" r="{center_radius}" fill="#FF0000" opacity="{center_opacity}" />'
95
+ group += center + '</g>'
96
+ return group
97
+
98
+
99
+ def create_clouds():
100
+ clouds_svg = ""
101
+ cloud_count = 5
102
+ for _ in range(cloud_count):
103
+ cx = random.random() * 800
104
+ cy = 50 + random.random() * 100
105
+ rx = 50 + random.random() * 50
106
+ ry = 20 + random.random() * 20
107
+ clouds_svg += f'<ellipse cx="{cx}" cy="{cy}" rx="{rx}" ry="{ry}" fill="white" opacity="0.8" />'
108
+ # Smaller ellipse
109
+ cloud_part_cx = cx + 30
110
+ cloud_part_cy = cy - 5
111
+ clouds_svg += f'<ellipse cx="{cloud_part_cx}" cy="{cloud_part_cy}" rx="30" ry="15" fill="white" opacity="0.8" />'
112
+ return clouds_svg
113
+
114
+ # --- Gradio App ---
115
+
116
+ def play_game(click_data, game_state):
117
+ if game_state is None: # Initialize game state
118
+ game_state = {"score": 0, "birds": [], "explosions": [], "game_running": True}
119
+
120
+ score = game_state["score"]
121
+ birds = game_state["birds"]
122
+ explosions = game_state["explosions"]
123
+ game_running = game_state["game_running"]
124
+
125
+ # Sounds (Base64 encoded for embedding)
126
+ explosion_sound = "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="
127
+ miss_sound = "data:audio/wav;base64,UklGRiQDAABXQVZFZm10IBAAAAABAAEAESsAABErAAABAAgAZGF0YQADAABkAGQAZABkAGQAfACEAJwAsAC8AMgA1ADsAOQA7ADkANQA0AC8AKgAnACMAHQAX