Lukeetah commited on
Commit
1a07fc9
·
verified ·
1 Parent(s): 31b5a07

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +249 -98
app.py CHANGED
@@ -1,163 +1,314 @@
1
- # app.py - Versión corregida para HuggingFace Spaces
2
  import gradio as gr
3
  import time
4
  import math
5
- from PIL import Image, ImageDraw
6
  import io
 
7
  from game_engine import GauchoCharacter, PhysicsEngine, WorldGenerator, Vector2D
8
 
9
- # Clase base del juego
10
- class CosmicGauchoGame:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  def __init__(self):
12
  self.player = GauchoCharacter()
 
13
  self.physics = PhysicsEngine()
14
- self.world = WorldGenerator()
15
- self.current_chunk = None
16
- self.game_width = 800
17
- self.game_height = 600
18
- self.load_initial_world()
19
-
20
- def load_initial_world(self):
21
- self.current_chunk = self.world.generate_chunk('pampa', 16)
 
 
 
 
 
 
 
 
 
 
22
 
23
  def update_game_state(self, movement: str = "none"):
24
- # Sistema de movimiento simplificado
25
  acceleration = Vector2D(0, 0)
26
- speed = 3.0
27
 
28
  if movement == "left":
29
  acceleration.x = -speed
30
  elif movement == "right":
31
  acceleration.x = speed
32
  elif movement == "up":
33
- acceleration.y = -speed
34
  elif movement == "down":
35
  acceleration.y = speed
36
-
 
 
37
  self.player.velocity = self.physics.apply_momentum(
38
- self.player.velocity,
39
- acceleration,
40
- dt=0.1
41
  )
42
 
43
- # Actualizar posición con límites de pantalla
44
- new_x = self.player.position.x + self.player.velocity.x
45
- new_y = self.player.position.y + self.player.velocity.y
46
 
47
- self.player.position.x = max(50, min(new_x, self.game_width - 50))
48
- self.player.position.y = max(50, min(new_y, self.game_height - 50))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
- def render_frame(self) -> Image.Image:
51
- # Crear canvas del juego
52
- img = Image.new('RGB', (self.game_width, self.game_height), (20, 40, 60))
53
  draw = ImageDraw.Draw(img)
54
 
55
- # Dibujar fondo de pampa cósmica
56
- for i in range(0, self.game_width, 100):
57
- for j in range(0, self.game_height, 100):
58
- color = (30 + i//10, 50 + j//10, 80)
59
- draw.rectangle([i, j, i+90, j+90], fill=color, outline=(100, 150, 200))
 
 
60
 
61
- # Dibujar al gaucho (círculo simple por ahora)
62
- player_x = int(self.player.position.x)
63
- player_y = int(self.player.position.y)
64
- draw.ellipse([player_x-20, player_y-20, player_x+20, player_y+20],
65
- fill=(255, 200, 100), outline=(200, 150, 50), width=3)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
- # Dibujar sombrero gaucho
68
- draw.ellipse([player_x-15, player_y-25, player_x+15, player_y-15],
69
- fill=(100, 50, 0), outline=(80, 40, 0), width=2)
 
70
 
71
  return img
72
-
73
- # Clase mejorada con optimizaciones
74
- class EnhancedCosmicGaucho(CosmicGauchoGame):
75
- def __init__(self):
76
- super().__init__()
77
- self.last_frame_time = time.time()
78
 
79
- def get_game_status(self):
 
80
  return {
81
- "position": f"({self.player.position.x:.1f}, {self.player.position.y:.1f})",
82
- "velocity": f"({self.player.velocity.x:.1f}, {self.player.velocity.y:.1f})",
83
- "cristales": sum(self.player.inventory['cristales'].values()),
84
- "habilidades": sum(self.player.abilities.values())
 
85
  }
86
 
87
- def create_game_interface():
88
- game = EnhancedCosmicGaucho()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
 
90
  with gr.Blocks(
91
- title="🎮 El Gaucho Cósmico - Preservando la Identidad Argentina 🇦🇷",
92
- theme=gr.themes.Monochrome()
 
93
  ) as interface:
94
 
95
- gr.Markdown("""
96
- # 🌟 El Gaucho Cósmico
97
- ### Aventura Épica de Identidad Cultural Argentina
98
- *Año 2088 - La Pampa Cósmica te necesita, che!*
 
 
 
99
  """)
100
 
101
  with gr.Row():
102
- with gr.Column(scale=2):
103
  game_display = gr.Image(
104
- label="🌌 Pampa Cósmica",
105
  interactive=False,
106
  width=800,
107
  height=600
108
  )
109
 
110
  with gr.Row():
111
- left_btn = gr.Button("⬅️ Izquierda", variant="secondary")
112
- up_btn = gr.Button("⬆️ Arriba", variant="secondary")
113
- down_btn = gr.Button("⬇️ Abajo", variant="secondary")
114
- right_btn = gr.Button("➡️ Derecha", variant="secondary")
115
 
116
  with gr.Column(scale=1):
117
- gr.Markdown("### 🎯 Estado del Gaucho")
118
- status_display = gr.JSON(label="📊 Datos del Personaje")
 
 
 
 
 
 
 
 
 
119
 
120
- gr.Markdown("### 🗣️ Sabiduría Gaucha")
121
  wisdom_display = gr.Textbox(
122
- value="'Che, en esta pampa cósmica, la tradición y la tecnología van de la mano!'",
123
- label="💭 Reflexión Cultural",
124
- interactive=False
 
125
  )
126
 
127
- def move_and_update(direction):
128
  game.update_game_state(direction)
129
- return game.render_frame(), game.get_game_status()
130
 
131
- # Conectar botones de movimiento
132
- left_btn.click(
133
- fn=lambda: move_and_update("left"),
134
- outputs=[game_display, status_display]
135
- )
136
- right_btn.click(
137
- fn=lambda: move_and_update("right"),
138
- outputs=[game_display, status_display]
139
- )
140
- up_btn.click(
141
- fn=lambda: move_and_update("up"),
142
- outputs=[game_display, status_display]
143
- )
144
- down_btn.click(
145
- fn=lambda: move_and_update("down"),
146
- outputs=[game_display, status_display]
147
- )
148
 
149
- # Cargar estado inicial
150
  interface.load(
151
- fn=lambda: (game.render_frame(), game.get_game_status()),
152
  outputs=[game_display, status_display]
153
  )
154
 
155
  return interface
156
 
157
  if __name__ == "__main__":
158
- interface = create_game_interface()
159
- interface.launch(
160
- share=True,
161
- show_error=True,
162
- debug=True
163
- )
 
1
+ # app.py - VERSIÓN ÉPICA GAUCHO CÓSMICO
2
  import gradio as gr
3
  import time
4
  import math
5
+ from PIL import Image, ImageDraw, ImageFont
6
  import io
7
+ import numpy as np
8
  from game_engine import GauchoCharacter, PhysicsEngine, WorldGenerator, Vector2D
9
 
10
+ class EpicGauchoRenderer:
11
+ """Renderer épico para un gaucho que se respete"""
12
+ def __init__(self):
13
+ self.particle_systems = []
14
+ self.background_stars = self._generate_stars(200)
15
+ self.world_tiles = self._create_epic_tiles()
16
+
17
+ def _generate_stars(self, count):
18
+ return [(
19
+ np.random.randint(0, 800),
20
+ np.random.randint(0, 600),
21
+ np.random.choice([1, 2, 3]),
22
+ np.random.choice([(255, 255, 255), (200, 200, 255), (255, 255, 200)])
23
+ ) for _ in range(count)]
24
+
25
+ def _create_epic_tiles(self):
26
+ """Crea texturas épicas para cada tipo de terreno"""
27
+ tiles = {}
28
+
29
+ # Pampa cósmica con gradientes épicos
30
+ pampa_base = Image.new('RGB', (100, 100), (20, 40, 80))
31
+ draw = ImageDraw.Draw(pampa_base)
32
+
33
+ # Crear patrón de campo energético
34
+ for i in range(0, 100, 20):
35
+ for j in range(0, 100, 20):
36
+ intensity = int(50 * math.sin(i/10) * math.cos(j/10)) + 100
37
+ color = (20, 40 + intensity//3, 80 + intensity//2)
38
+ draw.rectangle([i, j, i+18, j+18], fill=color, outline=(0, 255, 150), width=1)
39
+
40
+ tiles['pampa'] = pampa_base
41
+ return tiles
42
+
43
+ def draw_epic_gaucho(self, draw, x, y, velocity):
44
+ """Dibuja al gaucho con toda la épica que se merece"""
45
+ # Estela de movimiento
46
+ trail_length = min(30, abs(velocity.x) + abs(velocity.y))
47
+ if trail_length > 5:
48
+ trail_x = x - velocity.x * 3
49
+ trail_y = y - velocity.y * 3
50
+ draw.ellipse([trail_x-10, trail_y-10, trail_x+10, trail_y+10],
51
+ fill=(100, 200, 255, 128))
52
+
53
+ # Cuerpo del gaucho (más épico)
54
+ draw.ellipse([x-25, y-25, x+25, y+25],
55
+ fill=(139, 69, 19), outline=(101, 67, 33), width=3)
56
+
57
+ # Poncho tecnológico
58
+ poncho_points = [
59
+ (x-30, y-10), (x-20, y-35), (x+20, y-35), (x+30, y-10),
60
+ (x+25, y+15), (x-25, y+15)
61
+ ]
62
+ draw.polygon(poncho_points, fill=(0, 100, 200), outline=(0, 150, 255), width=2)
63
+
64
+ # Patrón del poncho
65
+ for i in range(-20, 25, 10):
66
+ draw.line([(x+i, y-30), (x+i, y+10)], fill=(255, 255, 100), width=2)
67
+
68
+ # Sombrero gaucho épico
69
+ draw.ellipse([x-20, y-35, x+20, y-25], fill=(50, 25, 0), outline=(80, 40, 0), width=3)
70
+ draw.ellipse([x-35, y-30, x+35, y-28], fill=(40, 20, 0), outline=(60, 30, 0), width=2)
71
+
72
+ # Mate tecnológico
73
+ mate_x, mate_y = x + 15, y - 5
74
+ draw.ellipse([mate_x-8, mate_y-8, mate_x+8, mate_y+8],
75
+ fill=(150, 75, 0), outline=(255, 200, 0), width=2)
76
+ # Bombilla láser
77
+ draw.line([(mate_x, mate_y-8), (mate_x, mate_y-15)], fill=(0, 255, 0), width=3)
78
+
79
+ # Ojos determinados
80
+ draw.ellipse([x-8, y-8, x-3, y-3], fill=(255, 255, 255))
81
+ draw.ellipse([x+3, y-8, x+8, y-3], fill=(255, 255, 255))
82
+ draw.ellipse([x-6, y-6, x-5, y-5], fill=(0, 0, 0))
83
+ draw.ellipse([x+5, y-6, x+6, y-5], fill=(0, 0, 0))
84
+
85
+ class CosmicGauchoEpic:
86
  def __init__(self):
87
  self.player = GauchoCharacter()
88
+ self.player.position = Vector2D(400, 300) # Centro de la pantalla
89
  self.physics = PhysicsEngine()
90
+ self.renderer = EpicGauchoRenderer()
91
+ self.camera_offset = Vector2D(0, 0)
92
+ self.crystals = self._spawn_crystals()
93
+ self.enemies = []
94
+ self.particles = []
95
+
96
+ def _spawn_crystals(self):
97
+ """Genera cristales de valores argentinos"""
98
+ crystal_types = ['Solidaridad', 'Familia', 'Amistad', 'Respeto', 'Creatividad']
99
+ crystals = []
100
+ for i, crystal_type in enumerate(crystal_types):
101
+ crystals.append({
102
+ 'type': crystal_type,
103
+ 'position': Vector2D(200 + i * 150, 200 + (i % 2) * 200),
104
+ 'collected': False,
105
+ 'pulse': 0
106
+ })
107
+ return crystals
108
 
109
  def update_game_state(self, movement: str = "none"):
 
110
  acceleration = Vector2D(0, 0)
111
+ speed = 4.0
112
 
113
  if movement == "left":
114
  acceleration.x = -speed
115
  elif movement == "right":
116
  acceleration.x = speed
117
  elif movement == "up":
118
+ acceleration.y = -speed * 0.8 # Gravedad simulada
119
  elif movement == "down":
120
  acceleration.y = speed
121
+
122
+ # Momentum más fluido
123
+ self.player.velocity = self.player.velocity * 0.95 # Fricción
124
  self.player.velocity = self.physics.apply_momentum(
125
+ self.player.velocity, acceleration, dt=0.1
 
 
126
  )
127
 
128
+ self.player.position += self.player.velocity * 0.1
 
 
129
 
130
+ # Límites del mundo expandido
131
+ self.player.position.x = max(50, min(self.player.position.x, 1500))
132
+ self.player.position.y = max(50, min(self.player.position.y, 1200))
133
+
134
+ # Cámara que sigue al jugador
135
+ self.camera_offset.x = self.player.position.x - 400
136
+ self.camera_offset.y = self.player.position.y - 300
137
+
138
+ # Recolectar cristales
139
+ self._check_crystal_collection()
140
+
141
+ def _check_crystal_collection(self):
142
+ for crystal in self.crystals:
143
+ if not crystal['collected']:
144
+ distance = ((self.player.position.x - crystal['position'].x) ** 2 +
145
+ (self.player.position.y - crystal['position'].y) ** 2) ** 0.5
146
+ if distance < 40:
147
+ crystal['collected'] = True
148
+ self.player.inventory['cristales'][crystal['type']] = True
149
 
150
+ def render_epic_frame(self) -> Image.Image:
151
+ img = Image.new('RGB', (800, 600), (5, 5, 20))
 
152
  draw = ImageDraw.Draw(img)
153
 
154
+ # Fondo estrellado épico
155
+ for star_x, star_y, size, color in self.renderer.background_stars:
156
+ # Parallax scrolling
157
+ scroll_x = star_x - self.camera_offset.x * 0.3
158
+ scroll_y = star_y - self.camera_offset.y * 0.3
159
+ if 0 <= scroll_x <= 800 and 0 <= scroll_y <= 600:
160
+ draw.ellipse([scroll_x-size, scroll_y-size, scroll_x+size, scroll_y+size], fill=color)
161
 
162
+ # Grid energético de la pampa cósmica
163
+ grid_size = 100
164
+ for x in range(-200, 1000, grid_size):
165
+ for y in range(-200, 800, grid_size):
166
+ screen_x = x - self.camera_offset.x
167
+ screen_y = y - self.camera_offset.y
168
+ if -100 <= screen_x <= 900 and -100 <= screen_y <= 700:
169
+ # Campo energético
170
+ alpha = int(50 + 30 * math.sin(time.time() + x/100))
171
+ color = (0, 50 + alpha//2, 100 + alpha)
172
+ draw.rectangle([screen_x, screen_y, screen_x+90, screen_y+90],
173
+ fill=color, outline=(0, 150, 255), width=1)
174
+
175
+ # Cristales épicos
176
+ for crystal in self.crystals:
177
+ if not crystal['collected']:
178
+ crystal_x = crystal['position'].x - self.camera_offset.x
179
+ crystal_y = crystal['position'].y - self.camera_offset.y
180
+
181
+ if 0 <= crystal_x <= 800 and 0 <= crystal_y <= 600:
182
+ # Efecto de pulso
183
+ pulse = math.sin(time.time() * 3 + crystal['pulse']) * 10
184
+ size = 20 + pulse
185
+
186
+ # Aura del cristal
187
+ draw.ellipse([crystal_x-size-5, crystal_y-size-5,
188
+ crystal_x+size+5, crystal_y+size+5],
189
+ fill=(255, 255, 255, 50))
190
+
191
+ # Cristal
192
+ crystal_color = {
193
+ 'Solidaridad': (255, 100, 100),
194
+ 'Familia': (100, 255, 100),
195
+ 'Amistad': (100, 100, 255),
196
+ 'Respeto': (255, 255, 100),
197
+ 'Creatividad': (255, 100, 255)
198
+ }.get(crystal['type'], (255, 255, 255))
199
+
200
+ draw.polygon([
201
+ (crystal_x, crystal_y-size),
202
+ (crystal_x-size*0.7, crystal_y),
203
+ (crystal_x, crystal_y+size),
204
+ (crystal_x+size*0.7, crystal_y)
205
+ ], fill=crystal_color, outline=(255, 255, 255), width=2)
206
 
207
+ # Gaucho épico
208
+ player_screen_x = 400 # Siempre centrado
209
+ player_screen_y = 300
210
+ self.renderer.draw_epic_gaucho(draw, player_screen_x, player_screen_y, self.player.velocity)
211
 
212
  return img
 
 
 
 
 
 
213
 
214
+ def get_epic_status(self):
215
+ cristales_obtenidos = sum(self.player.inventory['cristales'].values())
216
  return {
217
+ "🗺️ Coordenadas": f"({self.player.position.x:.0f}, {self.player.position.y:.0f})",
218
+ "⚡ Momentum": f"({self.player.velocity.x:.1f}, {self.player.velocity.y:.1f})",
219
+ "💎 Cristales": f"{cristales_obtenidos}/7",
220
+ "🎯 Misión": "Recuperar la identidad argentina" if cristales_obtenidos < 7 else "¡MISIÓN CUMPLIDA!",
221
+ "🔥 Épica": "MÁXIMA"
222
  }
223
 
224
+ def create_epic_interface():
225
+ game = CosmicGauchoEpic()
226
+
227
+ custom_css = """
228
+ .epic-title {
229
+ background: linear-gradient(45deg, #FF6B6B, #4ECDC4, #45B7D1, #96CEB4, #FFEAA7);
230
+ -webkit-background-clip: text;
231
+ -webkit-text-fill-color: transparent;
232
+ font-size: 3em !important;
233
+ font-weight: bold;
234
+ text-align: center;
235
+ }
236
+ .epic-container {
237
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
238
+ border-radius: 15px;
239
+ padding: 20px;
240
+ }
241
+ """
242
 
243
  with gr.Blocks(
244
+ title="🚀 EL GAUCHO CÓSMICO ÉPICO 🇦🇷",
245
+ css=custom_css,
246
+ theme=gr.themes.Soft()
247
  ) as interface:
248
 
249
+ gr.HTML("""
250
+ <div class="epic-title">
251
+ 🌟 EL GAUCHO CÓSMICO 🌟<br>
252
+ <span style="font-size: 0.6em; color: #FFD700;">
253
+ AVENTURA ÉPICA DE IDENTIDAD CULTURAL ARGENTINA
254
+ </span>
255
+ </div>
256
  """)
257
 
258
  with gr.Row():
259
+ with gr.Column(scale=2, elem_classes="epic-container"):
260
  game_display = gr.Image(
261
+ label="🌌 LA PAMPA CÓSMICA ÉPICA",
262
  interactive=False,
263
  width=800,
264
  height=600
265
  )
266
 
267
  with gr.Row():
268
+ left_btn = gr.Button("⬅️ IZQUIERDA", variant="primary", size="lg")
269
+ up_btn = gr.Button("⬆️ SALTAR", variant="secondary", size="lg")
270
+ down_btn = gr.Button("⬇️ AGACHAR", variant="secondary", size="lg")
271
+ right_btn = gr.Button("➡️ DERECHA", variant="primary", size="lg")
272
 
273
  with gr.Column(scale=1):
274
+ gr.Markdown("### 🎯 ESTADO ÉPICO DEL GAUCHO")
275
+ status_display = gr.JSON(label="📊 DATOS DE MARTÍN 'EL MATE'", elem_classes="epic-container")
276
+
277
+ gr.Markdown("### 🗣️ FILOSOFÍA GAUCHA CÓSMICA")
278
+ wisdom_quotes = [
279
+ "¡La tradición no se negocia, che!",
280
+ "En esta pampa cósmica, somos resistencia pura",
281
+ "Cada cristal recuperado fortalece nuestra alma",
282
+ "El mate une dimensiones, hermano",
283
+ "¡Vamos a mostrarles qué es ser argentino!"
284
+ ]
285
 
286
+ import random
287
  wisdom_display = gr.Textbox(
288
+ value=random.choice(wisdom_quotes),
289
+ label="💭 Sabiduría del Gaucho",
290
+ interactive=False,
291
+ elem_classes="epic-container"
292
  )
293
 
294
+ def epic_move_and_update(direction):
295
  game.update_game_state(direction)
296
+ return game.render_epic_frame(), game.get_epic_status()
297
 
298
+ # Conectar controles épicos
299
+ left_btn.click(fn=lambda: epic_move_and_update("left"), outputs=[game_display, status_display])
300
+ right_btn.click(fn=lambda: epic_move_and_update("right"), outputs=[game_display, status_display])
301
+ up_btn.click(fn=lambda: epic_move_and_update("up"), outputs=[game_display, status_display])
302
+ down_btn.click(fn=lambda: epic_move_and_update("down"), outputs=[game_display, status_display])
 
 
 
 
 
 
 
 
 
 
 
 
303
 
304
+ # Estado inicial épico
305
  interface.load(
306
+ fn=lambda: (game.render_epic_frame(), game.get_epic_status()),
307
  outputs=[game_display, status_display]
308
  )
309
 
310
  return interface
311
 
312
  if __name__ == "__main__":
313
+ interface = create_epic_interface()
314
+ interface.launch(share=True, show_error=True, debug=True)