Ladrillitos (Python + pygame)

Versi贸n Python del cl谩sico Ladrillitos implementado con pygame. Barra controlada con el rat贸n, ladrillos de colores aleatorios y f铆sica de rebote con 谩ngulo variable seg煤n el punto de impacto. Autor: David Carrero Fernandez-Baillo (carrero.es). Requisitos: pip install pygame Ejecutar: python ladrillitos.py
				"""
ladrillitos.py 聴 Arkanoid en Python con pygame

Versi贸n Python del cl谩sico Ladrillitos originalmente escrito en Java (2003).
Barra controlada con el rat贸n, ladrillos de colores aleatorios y f铆sica de
rebote con 谩ngulo variable seg煤n el punto de impacto.

Autor: David Carrero Fernandez-Baillo
Web:   https://carrero.es
Version Java (Swing): https://programacion.net/codigo/ladrillitos_104

Requisitos: pip install pygame
Ejecutar:   python ladrillitos.py
"""

import sys
import random
import pygame

# ---------------------------------------------------------------------------
# Constantes
# ---------------------------------------------------------------------------
ANCHO, ALTO  = 510, 420
FPS          = 60
COLS         = 10
FILAS_LAD    = 3
W_LAD, H_LAD = 48, 15
W_BAR, H_BAR = 80, 12
R_PELOTA     = 10
VEL_BASE     = 4

NEGRO    = (  0,   0,   0)
BLANCO   = (255, 255, 255)
AMARILLO = (255, 220,   0)
ROJO     = (200,   0,   0)
VERDE    = ( 50, 200,  50)
GRIS     = (180, 180, 180)


# ---------------------------------------------------------------------------
# Clases
# ---------------------------------------------------------------------------

class Ladrillo:
    def __init__(self, x, y):
        self.rect  = pygame.Rect(x, y, W_LAD, H_LAD)
        self.color = (
            random.randint(100, 255),
            random.randint(100, 255),
            random.randint(100, 255),
        )

    def dibujar(self, pantalla):
        pygame.draw.rect(pantalla, self.color, self.rect)
        pygame.draw.rect(pantalla, BLANCO, self.rect, 1)


class Barra:
    def __init__(self):
        self.rect = pygame.Rect((ANCHO - W_BAR) // 2, ALTO - 50, W_BAR, H_BAR)

    def mover(self, x):
        self.rect.centerx = x
        self.rect.clamp_ip(pygame.Rect(0, 0, ANCHO, ALTO))

    def dibujar(self, pantalla):
        pygame.draw.rect(pantalla, ROJO, self.rect)
        pygame.draw.rect(pantalla, BLANCO, self.rect, 1)


class Pelota:
    def __init__(self, barra):
        self.reiniciar(barra)

    def reiniciar(self, barra):
        self.x      = float(barra.rect.centerx - R_PELOTA // 2)
        self.y      = float(barra.rect.top - R_PELOTA - 2)
        self.vx     = VEL_BASE * random.choice((-1, 1))
        self.vy     = -VEL_BASE
        self.activa = False

    @property
    def rect(self):
        return pygame.Rect(int(self.x), int(self.y), R_PELOTA, R_PELOTA)

    def mover(self):
        if not self.activa:
            return
        self.x += self.vx
        self.y += self.vy

    def dibujar(self, pantalla):
        pygame.draw.ellipse(pantalla, AMARILLO, self.rect)
        pygame.draw.ellipse(pantalla, BLANCO, self.rect, 1)


# ---------------------------------------------------------------------------
# Juego principal
# ---------------------------------------------------------------------------

class Juego:
    def __init__(self):
        pygame.init()
        self.pantalla      = pygame.display.set_mode((ANCHO, ALTO))
        pygame.display.set_caption("Ladrillitos 聴 carrero.es")
        self.reloj         = pygame.time.Clock()
        self.fuente        = pygame.font.SysFont("monospace", 14)
        self.fuente_grande = pygame.font.SysFont("monospace", 28, bold=True)
        self.reiniciar()

    def reiniciar(self):
        self.vidas     = 3
        self.puntos    = 0
        self.barra     = Barra()
        self.pelota    = Pelota(self.barra)
        self.ladrillos = self._generar_ladrillos()
        self.estado    = "esperando"  # esperando | jugando | perdido | ganado

    def _generar_ladrillos(self):
        ladrillos = []
        margen_y  = 40
        for fila in range(FILAS_LAD):
            for col in range(COLS):
                x = col * (W_LAD + 2) + 3
                y = margen_y + fila * (H_LAD + 5)
                ladrillos.append(Ladrillo(x, y))
        return ladrillos

    # --- Actualizaci贸n ---

    def actualizar(self):
        self.pelota.mover()
        r = self.pelota.rect

        # Paredes laterales
        if r.left <= 0 or r.right >= ANCHO:
            self.pelota.vx *= -1

        # Techo
        if r.top <= 20:
            self.pelota.vy = abs(self.pelota.vy)

        # Barra: rebote con 谩ngulo variable
        if r.colliderect(self.barra.rect) and self.pelota.vy > 0:
            self.pelota.vy = -abs(self.pelota.vy)
            rel = (r.centerx - self.barra.rect.left) / W_BAR - 0.5
            self.pelota.vx = rel * 8

        # Pelota perdida
        if r.top > ALTO:
            self.vidas -= 1
            if self.vidas <= 0:
                self.estado = "perdido"
                return
            self.pelota.reiniciar(self.barra)
            self.estado = "esperando"
            return

        # Colisi贸n con ladrillos (primer impacto por frame)
        for ladrillo in self.ladrillos:
            if r.colliderect(ladrillo.rect):
                self.ladrillos.remove(ladrillo)
                self.pelota.vy *= -1
                self.puntos += 10
                break

        if not self.ladrillos:
            self.estado = "ganado"

    # --- Dibujo ---

    def dibujar(self):
        self.pantalla.fill(NEGRO)

        for ladrillo in self.ladrillos:
            ladrillo.dibujar(self.pantalla)
        self.barra.dibujar(self.pantalla)
        self.pelota.dibujar(self.pantalla)

        # HUD
        self._texto("Ladrillitos",       10,   5, VERDE,  self.fuente)
        self._texto(f"Vidas: {self.vidas}",   220,  5, BLANCO, self.fuente)
        self._texto(f"Puntos: {self.puntos}", 400,  5, BLANCO, self.fuente)

        if self.estado == "esperando":
            self._centrar("Haz clic para lanzar", ALTO // 2, GRIS, self.fuente)
        elif self.estado == "perdido":
            self._centrar("GAME OVER",              ALTO // 2 - 20, ROJO,   self.fuente_grande)
            self._centrar("Clic para volver a jugar", ALTO // 2 + 20, BLANCO, self.fuente)
        elif self.estado == "ganado":
            self._centrar("隆GANASTE!",              ALTO // 2 - 20, VERDE,  self.fuente_grande)
            self._centrar("Clic para volver a jugar", ALTO // 2 + 20, BLANCO, self.fuente)

        pygame.display.flip()

    def _texto(self, texto, x, y, color, fuente):
        self.pantalla.blit(fuente.render(texto, True, color), (x, y))

    def _centrar(self, texto, y, color, fuente):
        superficie = fuente.render(texto, True, color)
        x = (ANCHO - superficie.get_width()) // 2
        self.pantalla.blit(superficie, (x, y))

    # --- Bucle principal ---

    def ejecutar(self):
        while True:
            for evento in pygame.event.get():
                if evento.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()

                if evento.type == pygame.MOUSEMOTION:
                    self.barra.mover(evento.pos[0])
                    if self.estado == "esperando":
                        self.pelota.x = float(self.barra.rect.centerx - R_PELOTA // 2)
                        self.pelota.y = float(self.barra.rect.top - R_PELOTA - 2)

                if evento.type == pygame.MOUSEBUTTONDOWN:
                    if self.estado in ("perdido", "ganado"):
                        self.reiniciar()
                    elif self.estado == "esperando":
                        self.pelota.activa = True
                        self.estado = "jugando"

            if self.estado == "jugando":
                self.actualizar()

            self.dibujar()
            self.reloj.tick(FPS)


if __name__ == "__main__":
    Juego().ejecutar()

			
Descargar adjuntos
COMPARTE ESTE TUTORIAL

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
TUTORIAL ANTERIOR

SIGUIENTE TUTORIAL