Enemigos y disparos
This commit is contained in:
parent
1b272ba47e
commit
ac215e0e37
@ -1,11 +1,11 @@
|
|||||||
import sys
|
|
||||||
import math
|
import math
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
import pygame
|
import pygame
|
||||||
|
|
||||||
# Inicialización de Pygame
|
|
||||||
pygame.init()
|
pygame.init()
|
||||||
|
|
||||||
# Configuración de pantalla
|
# Configuración de Pantalla
|
||||||
SCREEN_WIDTH = 800
|
SCREEN_WIDTH = 800
|
||||||
SCREEN_HEIGHT = 600
|
SCREEN_HEIGHT = 600
|
||||||
FPS = 60
|
FPS = 60
|
||||||
@ -16,106 +16,148 @@ TILE_HEIGHT = 32
|
|||||||
GRID_SIZE_X = 8
|
GRID_SIZE_X = 8
|
||||||
GRID_SIZE_Y = 120
|
GRID_SIZE_Y = 120
|
||||||
|
|
||||||
# Colores de apoyo
|
# Colores de Respaldo / Suelo
|
||||||
COLOR_BG = (15, 15, 25)
|
COLOR_BG = (15, 15, 25)
|
||||||
COLOR_ROAD = (50, 50, 65)
|
COLOR_ROAD = (50, 50, 65)
|
||||||
COLOR_GRID = (30, 30, 45)
|
COLOR_GRID = (30, 30, 45)
|
||||||
|
|
||||||
|
|
||||||
def grid_to_iso(gx, gy, gz=0):
|
def grid_to_iso(gx, gy, gz=0):
|
||||||
"""Convierte coordenadas 3D de rejilla en coordenadas 2D en pantalla."""
|
"""Convierte coordenadas de la cuadrícula a coordenadas isométricas de pantalla."""
|
||||||
iso_x = (gx - gy) * (TILE_WIDTH // 2)
|
iso_x = (gx - gy) * (TILE_WIDTH // 2)
|
||||||
iso_y = (gx + gy) * (TILE_HEIGHT // 2) - (gz * 16)
|
iso_y = (gx + gy) * (TILE_HEIGHT // 2) - (gz * 16)
|
||||||
return iso_x, iso_y
|
return iso_x, iso_y
|
||||||
|
|
||||||
|
|
||||||
# ==============================================================================
|
def create_placeholder_sprites():
|
||||||
# GENERADOR DE SPRITES AUTOMÁTICO (O Carga desde PNG si existen)
|
"""Genera sprites vectoriales en memoria si no existen archivos PNG locales."""
|
||||||
# ==============================================================================
|
sprites = {}
|
||||||
def load_or_create_sprite(filename, create_func):
|
|
||||||
"""Intenta cargar una imagen PNG. Si no existe, la crea dinámicamente."""
|
# 1. Jugador (Lasertron)
|
||||||
try:
|
surf_player = pygame.Surface((64, 64), pygame.SRCALPHA)
|
||||||
image = pygame.image.load(filename).convert_alpha()
|
pygame.draw.polygon(
|
||||||
return image
|
surf_player,
|
||||||
except (pygame.error, FileNotFoundError):
|
(255, 200, 0),
|
||||||
return create_func()
|
[(32, 8), (56, 24), (32, 56), (8, 24)],
|
||||||
|
)
|
||||||
|
pygame.draw.polygon(
|
||||||
|
surf_player,
|
||||||
|
(255, 255, 255),
|
||||||
|
[(32, 8), (56, 24), (32, 56), (8, 24)],
|
||||||
|
2,
|
||||||
|
)
|
||||||
|
pygame.draw.circle(surf_player, (0, 255, 255), (32, 28), 6)
|
||||||
|
sprites["player"] = surf_player
|
||||||
|
|
||||||
|
# 2. VORTEX
|
||||||
|
surf_vortex = pygame.Surface((64, 64), pygame.SRCALPHA)
|
||||||
|
pygame.draw.polygon(
|
||||||
|
surf_vortex,
|
||||||
|
(220, 50, 50),
|
||||||
|
[(32, 4), (60, 20), (52, 52), (12, 52)],
|
||||||
|
)
|
||||||
|
pygame.draw.polygon(
|
||||||
|
surf_vortex,
|
||||||
|
(255, 255, 255),
|
||||||
|
[(32, 4), (60, 20), (52, 52), (12, 52)],
|
||||||
|
2,
|
||||||
|
)
|
||||||
|
pygame.draw.circle(surf_vortex, (255, 255, 0), (32, 28), 10)
|
||||||
|
sprites["vortex"] = surf_vortex
|
||||||
|
|
||||||
|
# 3. Bloque empujable
|
||||||
|
surf_block = pygame.Surface((64, 64), pygame.SRCALPHA)
|
||||||
|
pygame.draw.polygon(
|
||||||
|
surf_block,
|
||||||
|
(180, 70, 40),
|
||||||
|
[(32, 12), (58, 26), (32, 40), (6, 26)],
|
||||||
|
)
|
||||||
|
pygame.draw.polygon(
|
||||||
|
surf_block,
|
||||||
|
(120, 40, 20),
|
||||||
|
[(6, 26), (32, 40), (32, 58), (6, 44)],
|
||||||
|
)
|
||||||
|
pygame.draw.polygon(
|
||||||
|
surf_block,
|
||||||
|
(150, 50, 30),
|
||||||
|
[(58, 26), (32, 40), (32, 58), (58, 44)],
|
||||||
|
)
|
||||||
|
sprites["block"] = surf_block
|
||||||
|
|
||||||
|
# 4. Enemigo Alienígena (Drone)
|
||||||
|
surf_enemy = pygame.Surface((64, 64), pygame.SRCALPHA)
|
||||||
|
pygame.draw.polygon(
|
||||||
|
surf_enemy,
|
||||||
|
(50, 200, 100),
|
||||||
|
[(32, 10), (54, 28), (32, 46), (10, 28)],
|
||||||
|
)
|
||||||
|
pygame.draw.polygon(
|
||||||
|
surf_enemy,
|
||||||
|
(255, 255, 255),
|
||||||
|
[(32, 10), (54, 28), (32, 46), (10, 28)],
|
||||||
|
2,
|
||||||
|
)
|
||||||
|
pygame.draw.circle(surf_enemy, (255, 0, 0), (32, 28), 5) # Ojo rojo
|
||||||
|
sprites["enemy"] = surf_enemy
|
||||||
|
|
||||||
|
# 5. Bala
|
||||||
|
surf_bullet = pygame.Surface((32, 32), pygame.SRCALPHA)
|
||||||
|
pygame.draw.circle(surf_bullet, (0, 255, 255), (16, 16), 5)
|
||||||
|
pygame.draw.circle(surf_bullet, (255, 255, 255), (16, 16), 2)
|
||||||
|
sprites["bullet"] = surf_bullet
|
||||||
|
|
||||||
|
return sprites
|
||||||
|
|
||||||
|
|
||||||
def create_player_sprite():
|
class SpriteManager:
|
||||||
surf = pygame.Surface((64, 64), pygame.SRCALPHA)
|
|
||||||
# Cuerpo principal Lasertron
|
def __init__(self):
|
||||||
pygame.draw.ellipse(surf, (255, 200, 0), (16, 20, 32, 28))
|
self.placeholders = create_placeholder_sprites()
|
||||||
pygame.draw.ellipse(surf, (255, 255, 200), (20, 12, 24, 20))
|
self.cache = {}
|
||||||
pygame.draw.circle(surf, (0, 200, 255), (32, 20), 6) # Visor
|
|
||||||
# Cañón de disparo
|
def get_sprite(self, name, filename):
|
||||||
pygame.draw.rect(surf, (150, 150, 150), (30, 6, 4, 10))
|
if name in self.cache:
|
||||||
return surf
|
return self.cache[name]
|
||||||
|
|
||||||
|
if os.path.exists(filename):
|
||||||
|
try:
|
||||||
|
img = pygame.image.load(filename).convert_alpha()
|
||||||
|
self.cache[name] = img
|
||||||
|
return img
|
||||||
|
except Exception as e:
|
||||||
|
print(
|
||||||
|
f"Error al cargar {filename}, usando respaldo vectorial: {e}"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.cache[name] = self.placeholders[name]
|
||||||
|
return self.cache[name]
|
||||||
|
|
||||||
|
|
||||||
def create_vortex_sprite():
|
|
||||||
surf = pygame.Surface((64, 64), pygame.SRCALPHA)
|
|
||||||
# Base pesada VORTEX
|
|
||||||
pygame.draw.ellipse(surf, (180, 40, 40), (8, 24, 48, 30))
|
|
||||||
pygame.draw.ellipse(surf, (220, 60, 60), (14, 16, 36, 22))
|
|
||||||
pygame.draw.circle(surf, (255, 255, 255), (32, 24), 8)
|
|
||||||
pygame.draw.circle(surf, (255, 0, 0), (32, 24), 4)
|
|
||||||
return surf
|
|
||||||
|
|
||||||
|
|
||||||
def create_block_sprite():
|
|
||||||
surf = pygame.Surface((64, 64), pygame.SRCALPHA)
|
|
||||||
# Cara superior
|
|
||||||
pts_top = [(32, 8), (56, 20), (32, 32), (8, 20)]
|
|
||||||
pygame.draw.polygon(surf, (210, 90, 50), pts_top)
|
|
||||||
# Cara izquierda
|
|
||||||
pts_left = [(8, 20), (32, 32), (32, 52), (8, 40)]
|
|
||||||
pygame.draw.polygon(surf, (150, 60, 30), pts_left)
|
|
||||||
# Cara derecha
|
|
||||||
pts_right = [(32, 32), (56, 20), (56, 40), (32, 52)]
|
|
||||||
pygame.draw.polygon(surf, (180, 75, 40), pts_right)
|
|
||||||
# Bordes
|
|
||||||
pygame.draw.polygon(surf, (255, 255, 255), pts_top, 1)
|
|
||||||
return surf
|
|
||||||
|
|
||||||
|
|
||||||
def create_enemy_sprite():
|
|
||||||
surf = pygame.Surface((64, 64), pygame.SRCALPHA)
|
|
||||||
# Dron Alienígena
|
|
||||||
pygame.draw.ellipse(surf, (50, 220, 100), (12, 16, 40, 32))
|
|
||||||
pygame.draw.circle(surf, (255, 0, 100), (32, 30), 8)
|
|
||||||
pygame.draw.line(surf, (50, 220, 100), (20, 48), (12, 58), 3)
|
|
||||||
pygame.draw.line(surf, (50, 220, 100), (44, 48), (52, 58), 3)
|
|
||||||
return surf
|
|
||||||
|
|
||||||
|
|
||||||
def create_bullet_sprite():
|
|
||||||
surf = pygame.Surface((32, 32), pygame.SRCALPHA)
|
|
||||||
pygame.draw.circle(surf, (0, 255, 255), (16, 16), 6)
|
|
||||||
pygame.draw.circle(surf, (255, 255, 255), (16, 16), 3)
|
|
||||||
return surf
|
|
||||||
|
|
||||||
|
|
||||||
# ==============================================================================
|
|
||||||
# CLASES DEL JUEGO
|
|
||||||
# ==============================================================================
|
|
||||||
class Entity:
|
class Entity:
|
||||||
def __init__(self, gx, gy, sprite, is_solid=True):
|
|
||||||
|
def __init__(self, gx, gy, sprite_name, filename, is_solid=True):
|
||||||
self.gx = float(gx)
|
self.gx = float(gx)
|
||||||
self.gy = float(gy)
|
self.gy = float(gy)
|
||||||
self.gz = 0
|
self.gz = 0
|
||||||
self.sprite = sprite
|
self.sprite_name = sprite_name
|
||||||
|
self.filename = filename
|
||||||
self.is_solid = is_solid
|
self.is_solid = is_solid
|
||||||
|
|
||||||
def draw(self, surface, camera_offset_x, camera_offset_y):
|
def draw(self, surface, camera_offset_x, camera_offset_y, sprite_mgr):
|
||||||
screen_x, screen_y = grid_to_iso(self.gx, self.gy, self.gz)
|
screen_x, screen_y = grid_to_iso(self.gx, self.gy, self.gz)
|
||||||
draw_x = screen_x + camera_offset_x - (self.sprite.get_width() // 2)
|
sprite = sprite_mgr.get_sprite(self.sprite_name, self.filename)
|
||||||
draw_y = screen_y + camera_offset_y - (self.sprite.get_height() // 2)
|
|
||||||
surface.blit(self.sprite, (draw_x, draw_y))
|
# Centrar la imagen con respecto a la casilla isométrica
|
||||||
|
draw_x = screen_x + camera_offset_x - (sprite.get_width() // 2)
|
||||||
|
draw_y = screen_y + camera_offset_y - (sprite.get_height() // 2)
|
||||||
|
|
||||||
|
surface.blit(sprite, (draw_x, draw_y))
|
||||||
|
|
||||||
|
|
||||||
class Bullet(Entity):
|
class Bullet(Entity):
|
||||||
def __init__(self, gx, gy, dir_x, dir_y, sprite):
|
|
||||||
super().__init__(gx, gy, sprite, is_solid=False)
|
def __init__(self, gx, gy, dir_x, dir_y):
|
||||||
|
super().__init__(gx, gy, "bullet", "bullet.png", is_solid=False)
|
||||||
self.dir_x = dir_x
|
self.dir_x = dir_x
|
||||||
self.dir_y = dir_y
|
self.dir_y = dir_y
|
||||||
self.speed = 0.25
|
self.speed = 0.25
|
||||||
@ -131,7 +173,10 @@ class Bullet(Entity):
|
|||||||
|
|
||||||
for entity in entities:
|
for entity in entities:
|
||||||
if entity != self and entity.is_solid:
|
if entity != self and entity.is_solid:
|
||||||
if abs(entity.gx - self.gx) < 0.5 and abs(entity.gy - self.gy) < 0.5:
|
if (
|
||||||
|
abs(entity.gx - self.gx) < 0.5
|
||||||
|
and abs(entity.gy - self.gy) < 0.5
|
||||||
|
):
|
||||||
self.alive = False
|
self.alive = False
|
||||||
if isinstance(entity, (PushBlock, Enemy)):
|
if isinstance(entity, (PushBlock, Enemy)):
|
||||||
entity.health -= 1
|
entity.health -= 1
|
||||||
@ -139,8 +184,9 @@ class Bullet(Entity):
|
|||||||
|
|
||||||
|
|
||||||
class PushBlock(Entity):
|
class PushBlock(Entity):
|
||||||
def __init__(self, gx, gy, sprite):
|
|
||||||
super().__init__(gx, gy, sprite, is_solid=True)
|
def __init__(self, gx, gy):
|
||||||
|
super().__init__(gx, gy, "block", "block.png", is_solid=True)
|
||||||
self.health = 2
|
self.health = 2
|
||||||
|
|
||||||
def push(self, dx, dy, entities):
|
def push(self, dx, dy, entities):
|
||||||
@ -152,7 +198,10 @@ class PushBlock(Entity):
|
|||||||
|
|
||||||
for entity in entities:
|
for entity in entities:
|
||||||
if entity != self and entity.is_solid:
|
if entity != self and entity.is_solid:
|
||||||
if abs(entity.gx - new_gx) < 0.5 and abs(entity.gy - new_gy) < 0.5:
|
if (
|
||||||
|
abs(entity.gx - new_gx) < 0.5
|
||||||
|
and abs(entity.gy - new_gy) < 0.5
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.gx = new_gx
|
self.gx = new_gx
|
||||||
@ -161,15 +210,18 @@ class PushBlock(Entity):
|
|||||||
|
|
||||||
|
|
||||||
class Enemy(Entity):
|
class Enemy(Entity):
|
||||||
def __init__(self, gx, gy, sprite):
|
|
||||||
super().__init__(gx, gy, sprite, is_solid=True)
|
def __init__(self, gx, gy):
|
||||||
self.speed = 0.03
|
super().__init__(gx, gy, "enemy", "enemy.png", is_solid=True)
|
||||||
|
self.speed = 0.04
|
||||||
self.direction = 1
|
self.direction = 1
|
||||||
self.health = 1
|
self.health = 1
|
||||||
|
|
||||||
def update(self, entities):
|
def update(self, entities):
|
||||||
|
# Movimiento de patrulla horizontal
|
||||||
target_gx = self.gx + (self.speed * self.direction)
|
target_gx = self.gx + (self.speed * self.direction)
|
||||||
|
|
||||||
|
# Rebotar en los bordes de la carretera
|
||||||
if target_gx <= 0.5 or target_gx >= GRID_SIZE_X - 0.5:
|
if target_gx <= 0.5 or target_gx >= GRID_SIZE_X - 0.5:
|
||||||
self.direction *= -1
|
self.direction *= -1
|
||||||
target_gx = self.gx + (self.speed * self.direction)
|
target_gx = self.gx + (self.speed * self.direction)
|
||||||
@ -178,9 +230,9 @@ class Enemy(Entity):
|
|||||||
|
|
||||||
|
|
||||||
class Player(Entity):
|
class Player(Entity):
|
||||||
def __init__(self, gx, gy, sprite, bullet_sprite):
|
|
||||||
super().__init__(gx, gy, sprite, is_solid=True)
|
def __init__(self, gx, gy):
|
||||||
self.bullet_sprite = bullet_sprite
|
super().__init__(gx, gy, "player", "player.png", is_solid=True)
|
||||||
self.speed = 0.09
|
self.speed = 0.09
|
||||||
self.facing_x = 0.0
|
self.facing_x = 0.0
|
||||||
self.facing_y = -1.0
|
self.facing_y = -1.0
|
||||||
@ -209,10 +261,17 @@ class Player(Entity):
|
|||||||
blocked = False
|
blocked = False
|
||||||
for entity in entities:
|
for entity in entities:
|
||||||
if entity != self and entity.is_solid:
|
if entity != self and entity.is_solid:
|
||||||
if abs(entity.gx - target_gx) < 0.5 and abs(entity.gy - target_gy) < 0.5:
|
if (
|
||||||
|
abs(entity.gx - target_gx) < 0.5
|
||||||
|
and abs(entity.gy - target_gy) < 0.5
|
||||||
|
):
|
||||||
if isinstance(entity, PushBlock):
|
if isinstance(entity, PushBlock):
|
||||||
push_dx = 0.15 if dx > 0 else (-0.15 if dx < 0 else 0)
|
push_dx = (
|
||||||
push_dy = 0.15 if dy > 0 else (-0.15 if dy < 0 else 0)
|
0.15 if dx > 0 else (-0.15 if dx < 0 else 0)
|
||||||
|
)
|
||||||
|
push_dy = (
|
||||||
|
0.15 if dy > 0 else (-0.15 if dy < 0 else 0)
|
||||||
|
)
|
||||||
if not entity.push(push_dx, push_dy, entities):
|
if not entity.push(push_dx, push_dy, entities):
|
||||||
blocked = True
|
blocked = True
|
||||||
else:
|
else:
|
||||||
@ -227,13 +286,16 @@ class Player(Entity):
|
|||||||
if keys[pygame.K_SPACE] and self.shoot_cooldown == 0:
|
if keys[pygame.K_SPACE] and self.shoot_cooldown == 0:
|
||||||
spawn_x = self.gx + (self.facing_x * 0.7)
|
spawn_x = self.gx + (self.facing_x * 0.7)
|
||||||
spawn_y = self.gy + (self.facing_y * 0.7)
|
spawn_y = self.gy + (self.facing_y * 0.7)
|
||||||
bullets.append(Bullet(spawn_x, spawn_y, self.facing_x, self.facing_y, self.bullet_sprite))
|
bullets.append(
|
||||||
|
Bullet(spawn_x, spawn_y, self.facing_x, self.facing_y)
|
||||||
|
)
|
||||||
self.shoot_cooldown = 15
|
self.shoot_cooldown = 15
|
||||||
|
|
||||||
|
|
||||||
class Vortex(Entity):
|
class Vortex(Entity):
|
||||||
def __init__(self, gx, gy, sprite):
|
|
||||||
super().__init__(gx, gy, sprite, is_solid=True)
|
def __init__(self, gx, gy):
|
||||||
|
super().__init__(gx, gy, "vortex", "vortex.png", is_solid=True)
|
||||||
self.speed = 0.012
|
self.speed = 0.012
|
||||||
|
|
||||||
def update(self, entities):
|
def update(self, entities):
|
||||||
@ -242,7 +304,10 @@ class Vortex(Entity):
|
|||||||
blocked = False
|
blocked = False
|
||||||
for entity in entities:
|
for entity in entities:
|
||||||
if entity != self and entity.is_solid:
|
if entity != self and entity.is_solid:
|
||||||
if abs(entity.gx - self.gx) < 0.6 and abs(entity.gy - target_gy) < 0.6:
|
if (
|
||||||
|
abs(entity.gx - self.gx) < 0.6
|
||||||
|
and abs(entity.gy - target_gy) < 0.6
|
||||||
|
):
|
||||||
blocked = True
|
blocked = True
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -251,53 +316,65 @@ class Vortex(Entity):
|
|||||||
|
|
||||||
|
|
||||||
class Game:
|
class Game:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
|
self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
|
||||||
pygame.display.set_caption("Highway Encounter - PNG Sprites Version")
|
pygame.display.set_caption("Highway Encounter - Full Sprites & Enemies")
|
||||||
self.clock = pygame.time.Clock()
|
self.clock = pygame.time.Clock()
|
||||||
self.font = pygame.font.SysFont("monospace", 18, bold=True)
|
self.font = pygame.font.SysFont("monospace", 18, bold=True)
|
||||||
|
self.sprite_mgr = SpriteManager()
|
||||||
# Carga o Generación de Sprites
|
|
||||||
self.spr_player = load_or_create_sprite("player.png", create_player_sprite)
|
|
||||||
self.spr_vortex = load_or_create_sprite("vortex.png", create_vortex_sprite)
|
|
||||||
self.spr_block = load_or_create_sprite("block.png", create_block_sprite)
|
|
||||||
self.spr_enemy = load_or_create_sprite("enemy.png", create_enemy_sprite)
|
|
||||||
self.spr_bullet = load_or_create_sprite("bullet.png", create_bullet_sprite)
|
|
||||||
|
|
||||||
self.lives = 4
|
self.lives = 4
|
||||||
self.score = 0
|
self.score = 0
|
||||||
|
|
||||||
self.reset_level()
|
self.reset_level()
|
||||||
|
|
||||||
def reset_level(self):
|
def reset_level(self):
|
||||||
self.vortex = Vortex(3.5, GRID_SIZE_Y - 5, self.spr_vortex)
|
self.vortex = Vortex(3.5, GRID_SIZE_Y - 5)
|
||||||
self.player = Player(3.5, GRID_SIZE_Y - 8, self.spr_player, self.spr_bullet)
|
self.player = Player(3.5, GRID_SIZE_Y - 8)
|
||||||
|
|
||||||
self.entities = [self.vortex, self.player]
|
self.entities = [self.vortex, self.player]
|
||||||
self.bullets = []
|
self.bullets = []
|
||||||
|
|
||||||
|
# Escuadrón de reserva (vidas)
|
||||||
self.spares = []
|
self.spares = []
|
||||||
for i in range(self.lives - 1):
|
for i in range(self.lives - 1):
|
||||||
spare = Entity(3.5, GRID_SIZE_Y - 3 + (i * 1.2), self.spr_player, is_solid=False)
|
spare = Entity(
|
||||||
|
3.5,
|
||||||
|
GRID_SIZE_Y - 3 + (i * 1.2),
|
||||||
|
"player",
|
||||||
|
"player.png",
|
||||||
|
is_solid=False,
|
||||||
|
)
|
||||||
self.spares.append(spare)
|
self.spares.append(spare)
|
||||||
|
|
||||||
for y in range(10, GRID_SIZE_Y - 15, 6):
|
# Generar bloques y enemigos alternados a lo largo de la autopista
|
||||||
self.entities.append(PushBlock(y % GRID_SIZE_X, y, self.spr_block))
|
for y in range(10, GRID_SIZE_Y - 15, 5):
|
||||||
if y % 12 == 0:
|
# Agregar bloques
|
||||||
self.entities.append(Enemy(3.5, y - 2, self.spr_enemy))
|
self.entities.append(PushBlock(y % GRID_SIZE_X, y))
|
||||||
|
|
||||||
|
# Agregar enemigos cada 10 casillas
|
||||||
|
if y % 10 == 0:
|
||||||
|
self.entities.append(Enemy(3.5, y - 2))
|
||||||
|
|
||||||
def handle_collisions(self):
|
def handle_collisions(self):
|
||||||
|
# Colisión con enemigos
|
||||||
for entity in self.entities:
|
for entity in self.entities:
|
||||||
if isinstance(entity, Enemy):
|
if isinstance(entity, Enemy):
|
||||||
if abs(entity.gx - self.player.gx) < 0.5 and abs(entity.gy - self.player.gy) < 0.5:
|
if (
|
||||||
|
abs(entity.gx - self.player.gx) < 0.5
|
||||||
|
and abs(entity.gy - self.player.gy) < 0.5
|
||||||
|
):
|
||||||
self.lives -= 1
|
self.lives -= 1
|
||||||
if self.lives > 0:
|
if self.lives > 0:
|
||||||
self.reset_level()
|
self.reset_level()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Limpiar entidades destruidas (bloques o enemigos con salud <= 0)
|
||||||
for entity in self.entities[:]:
|
for entity in self.entities[:]:
|
||||||
if hasattr(entity, "health") and entity.health <= 0:
|
if hasattr(entity, "health") and entity.health <= 0:
|
||||||
self.entities.remove(entity)
|
self.entities.remove(entity)
|
||||||
self.score += 100
|
self.score += 150
|
||||||
|
|
||||||
def draw_hud(self):
|
def draw_hud(self):
|
||||||
zone = int((GRID_SIZE_Y - self.vortex.gy) / 4)
|
zone = int((GRID_SIZE_Y - self.vortex.gy) / 4)
|
||||||
@ -317,8 +394,12 @@ class Game:
|
|||||||
|
|
||||||
if self.lives <= 0:
|
if self.lives <= 0:
|
||||||
self.screen.fill((0, 0, 0))
|
self.screen.fill((0, 0, 0))
|
||||||
msg = self.font.render("GAME OVER - Press R to Restart", True, (255, 50, 50))
|
msg = self.font.render(
|
||||||
self.screen.blit(msg, (SCREEN_WIDTH // 2 - 150, SCREEN_HEIGHT // 2))
|
"GAME OVER - Press R to Restart", True, (255, 50, 50)
|
||||||
|
)
|
||||||
|
self.screen.blit(
|
||||||
|
msg, (SCREEN_WIDTH // 2 - 150, SCREEN_HEIGHT // 2)
|
||||||
|
)
|
||||||
pygame.display.flip()
|
pygame.display.flip()
|
||||||
|
|
||||||
keys = pygame.key.get_pressed()
|
keys = pygame.key.get_pressed()
|
||||||
@ -328,6 +409,7 @@ class Game:
|
|||||||
self.reset_level()
|
self.reset_level()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Actualización
|
||||||
keys = pygame.key.get_pressed()
|
keys = pygame.key.get_pressed()
|
||||||
self.player.update(keys, self.entities, self.bullets)
|
self.player.update(keys, self.entities, self.bullets)
|
||||||
self.vortex.update(self.entities)
|
self.vortex.update(self.entities)
|
||||||
@ -343,32 +425,49 @@ class Game:
|
|||||||
|
|
||||||
self.handle_collisions()
|
self.handle_collisions()
|
||||||
|
|
||||||
|
# Desplazamiento de cámara centrado en el jugador
|
||||||
iso_x, iso_y = grid_to_iso(self.player.gx, self.player.gy)
|
iso_x, iso_y = grid_to_iso(self.player.gx, self.player.gy)
|
||||||
camera_offset_x = SCREEN_WIDTH // 2 - iso_x
|
camera_offset_x = SCREEN_WIDTH // 2 - iso_x
|
||||||
camera_offset_y = SCREEN_HEIGHT // 2 - iso_y + 100
|
camera_offset_y = SCREEN_HEIGHT // 2 - iso_y + 100
|
||||||
|
|
||||||
|
# Renderizado
|
||||||
self.screen.fill(COLOR_BG)
|
self.screen.fill(COLOR_BG)
|
||||||
|
|
||||||
|
# Dibujar mosaico de la carretera
|
||||||
for gy in range(0, GRID_SIZE_Y):
|
for gy in range(0, GRID_SIZE_Y):
|
||||||
for gx in range(0, GRID_SIZE_X):
|
for gx in range(0, GRID_SIZE_X):
|
||||||
sx, sy = grid_to_iso(gx, gy)
|
sx, sy = grid_to_iso(gx, gy)
|
||||||
draw_x = sx + camera_offset_x
|
draw_x = sx + camera_offset_x
|
||||||
draw_y = sy + camera_offset_y
|
draw_y = sy + camera_offset_y
|
||||||
|
|
||||||
if -100 < draw_x < SCREEN_WIDTH + 100 and -100 < draw_y < SCREEN_HEIGHT + 100:
|
if (
|
||||||
|
-100 < draw_x < SCREEN_WIDTH + 100
|
||||||
|
and -100 < draw_y < SCREEN_HEIGHT + 100
|
||||||
|
):
|
||||||
pts = [
|
pts = [
|
||||||
(draw_x, draw_y),
|
(draw_x, draw_y),
|
||||||
(draw_x + TILE_WIDTH // 2, draw_y + TILE_HEIGHT // 2),
|
(
|
||||||
|
draw_x + TILE_WIDTH // 2,
|
||||||
|
draw_y + TILE_HEIGHT // 2,
|
||||||
|
),
|
||||||
(draw_x, draw_y + TILE_HEIGHT),
|
(draw_x, draw_y + TILE_HEIGHT),
|
||||||
(draw_x - TILE_WIDTH // 2, draw_y + TILE_HEIGHT // 2),
|
(
|
||||||
|
draw_x - TILE_WIDTH // 2,
|
||||||
|
draw_y + TILE_HEIGHT // 2,
|
||||||
|
),
|
||||||
]
|
]
|
||||||
pygame.draw.polygon(self.screen, COLOR_ROAD, pts)
|
pygame.draw.polygon(self.screen, COLOR_ROAD, pts)
|
||||||
pygame.draw.polygon(self.screen, COLOR_GRID, pts, 1)
|
pygame.draw.polygon(self.screen, COLOR_GRID, pts, 1)
|
||||||
|
|
||||||
|
# Dibujar elementos ordenados por profundidad (Y descendente)
|
||||||
all_drawables = self.entities + self.bullets + self.spares
|
all_drawables = self.entities + self.bullets + self.spares
|
||||||
sorted_entities = sorted(all_drawables, key=lambda e: e.gy, reverse=True)
|
sorted_entities = sorted(
|
||||||
|
all_drawables, key=lambda e: e.gy, reverse=True
|
||||||
|
)
|
||||||
for entity in sorted_entities:
|
for entity in sorted_entities:
|
||||||
entity.draw(self.screen, camera_offset_x, camera_offset_y)
|
entity.draw(
|
||||||
|
self.screen, camera_offset_x, camera_offset_y, self.sprite_mgr
|
||||||
|
)
|
||||||
|
|
||||||
self.draw_hud()
|
self.draw_hud()
|
||||||
pygame.display.flip()
|
pygame.display.flip()
|
||||||
@ -378,4 +477,4 @@ class Game:
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
Game().run()
|
Game().run()
|
||||||
|
|||||||
BIN
img-versiones/version_1.1.png
Normal file
BIN
img-versiones/version_1.1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
Loading…
x
Reference in New Issue
Block a user