Incluimos sonido 'al vuelo'

This commit is contained in:
luisgulo 2026-10-04 15:29:54 +02:00
parent af11922320
commit 101699b4a6
2 changed files with 64 additions and 7 deletions

View File

@ -1,9 +1,13 @@
import math
import os
import sys
import array
import random
import pygame
# Inicialización de Pygame y el mezclador de audio
pygame.init()
pygame.mixer.init(frequency=22050, size=-16, channels=1)
# Configuración de Pantalla
SCREEN_WIDTH = 800
@ -31,6 +35,56 @@ COLOR_ORANGE = (255, 140, 0)
COLOR_CYAN = (0, 200, 255)
def generate_sound(sound_type):
"""Genera efectos de sonido retro de forma sintética sin archivos externos."""
sample_rate = 22050
buffer = array.array("h")
if sound_type == "shoot":
# Disparo: Tono descendente agudo rápido
duration = 0.1
total_samples = int(sample_rate * duration)
for i in range(total_samples):
t = i / total_samples
freq = 800 * (1 - t * 0.7)
val = math.sin(2 * math.pi * freq * (i / sample_rate))
env = 1 - t
sample = int(val * env * 12000)
buffer.append(sample)
elif sound_type == "hit":
# Choque: Golpe sordo de baja frecuencia
duration = 0.15
total_samples = int(sample_rate * duration)
for i in range(total_samples):
t = i / total_samples
freq = 150 * (1 - t * 0.5)
noise = (random.random() * 2 - 1) * 0.3
val = math.sin(2 * math.pi * freq * (i / sample_rate)) + noise
env = (1 - t) ** 2
sample = int(val * env * 15000)
buffer.append(max(-32768, min(32767, sample)))
elif sound_type == "destroy":
# Destrucción: Ruido de explosión corta
duration = 0.2
total_samples = int(sample_rate * duration)
for i in range(total_samples):
t = i / total_samples
noise = random.random() * 2 - 1
env = (1 - t) ** 1.5
sample = int(noise * env * 14000)
buffer.append(sample)
return pygame.mixer.Sound(buffer=buffer)
# Cargar sonidos sintéticos
SOUND_SHOOT = generate_sound("shoot")
SOUND_HIT = generate_sound("hit")
SOUND_DESTROY = generate_sound("destroy")
def grid_to_iso(gx, gy, gz=0):
"""Convierte coordenadas 3D de rejilla a coordenadas 2D de pantalla."""
iso_x = (gx - gy) * (TILE_WIDTH // 2)
@ -204,10 +258,10 @@ class Bullet(Entity):
and abs(entity.gy - self.gy) < 0.5
):
self.alive = False
SOUND_HIT.play()
if isinstance(entity, WhiteBlock):
entity.health -= 1
elif isinstance(entity, PurpleBlock):
# El bloque morado es empujado por el disparo
entity.push_by_bullet(self.dir_x, self.dir_y, entities)
elif isinstance(entity, Enemy) and entity.destructible:
entity.take_damage()
@ -250,7 +304,6 @@ class PurpleBlock(Entity):
)
def push_by_bullet(self, dir_x, dir_y, entities):
"""Se desplaza 1 casilla entera en la dirección del impacto del disparo."""
step_x = 1 if dir_x > 0.3 else (-1 if dir_x < -0.3 else 0)
step_y = 1 if dir_y > 0.3 else (-1 if dir_y < -0.3 else 0)
@ -386,7 +439,6 @@ class Player(Entity):
abs(entity.gx - target_gx) < 0.5
and abs(entity.gy - target_gy) < 0.5
):
# Bloque Blanco: Se empuja caminando
if isinstance(entity, WhiteBlock):
push_dx = (
0.15 if dx > 0 else (-0.15 if dx < 0 else 0)
@ -396,7 +448,6 @@ class Player(Entity):
)
if not entity.push(push_dx, push_dy, entities):
blocked = True
# Bloque Morado y otros elementos: Bloquean el movimiento del jugador
else:
blocked = True
if not blocked:
@ -412,6 +463,7 @@ class Player(Entity):
bullets.append(
Bullet(spawn_x, spawn_y, self.facing_x, self.facing_y)
)
SOUND_SHOOT.play()
self.shoot_cooldown = 15
@ -420,6 +472,7 @@ class Vortex(Entity):
def __init__(self, gx, gy):
super().__init__(gx, gy, "vortex", "vortex.png", is_solid=True)
self.speed = 0.012
self.was_blocked = False
def update(self, entities):
target_gy = self.gy - self.speed
@ -434,6 +487,11 @@ class Vortex(Entity):
blocked = True
break
if blocked and not self.was_blocked:
SOUND_HIT.play()
self.was_blocked = blocked
if not blocked and target_gy >= 0:
self.gy = target_gy
@ -472,9 +530,7 @@ class Game:
)
self.spares.append(spare)
# Generar mapa balanceado con bloques blancos y morados
for y in range(10, GRID_SIZE_Y - 12):
# Alternar entre bloques Blancos (empujables) y Morados (desplazados por disparos)
if y % 6 == 0:
lane = (y * 3) % GRID_SIZE_X
if (y // 6) % 2 == 0:
@ -504,12 +560,13 @@ class Game:
)
if player_hit or vortex_hit:
SOUND_DESTROY.play()
return True
# Eliminar bloques blancos destruidos y enemigos abatidos
for entity in self.entities[:]:
if hasattr(entity, "health") and entity.health <= 0:
self.entities.remove(entity)
SOUND_DESTROY.play()
self.score += 200
return False

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB