From 101699b4a65d58ca95b7b558ee08eaecd47b8d66 Mon Sep 17 00:00:00 2001 From: luisgulo Date: Sun, 4 Oct 2026 15:29:54 +0200 Subject: [PATCH] Incluimos sonido 'al vuelo' --- highway_vector.py | 71 ++++++++++++++++++++++++++++++---- img-versiones/version_4.1.png | Bin 0 -> 18154 bytes 2 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 img-versiones/version_4.1.png diff --git a/highway_vector.py b/highway_vector.py index 8f0ad6b..171e888 100644 --- a/highway_vector.py +++ b/highway_vector.py @@ -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 diff --git a/img-versiones/version_4.1.png b/img-versiones/version_4.1.png new file mode 100644 index 0000000000000000000000000000000000000000..83bd81c04f1605e8a3d3204784fb9c9059c9dba1 GIT binary patch literal 18154 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 literal 0 HcmV?d00001