<-- Back to list of examples

"""
 Muestra cómo rebotar una pelota usando una pala en Pygame.
 El programa asume que hay dos joysticks conectados.
 
 Sample Python/Pygame Programs
 Simpson College Computer Science
 http://programarcadegames.com/
 http://simpson.edu/computer-science/
"""
import pygame
import random

NEGRO = (0, 0, 0)
BLANCO = (255, 255, 255)
AZUL =  (0, 0, 255)

class Protagonista(pygame.sprite.Sprite):
    """ Esta clase representa sendas palas a cada lado de la pantalla.
        Deriva de la clase "Sprite" en Pygame """

    # Constructor. Pasa el color del bloque así como sus posiciones x e y
    def __init__(self, x, y, joystick_no):
        # Llama al constructor de la clase padre (Sprite)
        super().__init__() 
        

        # Variables que contienen el alto y largo del bloque
        self.largo = 10
        self.alto = 75
        self.mi_joystick = None

        # Crea una imagen de la pelota y rellénala de color.
        # También puedes usar una imagen guardada en el disco.
        self.image = pygame.Surface([self.largo, self.alto])
        self.image.fill(BLANCO)

        # Extrae el objeto rectángulo que posee las dimensiones de la imagen
        self.rect = self.image.get_rect()
        
        # Establece la ubicación inicial del sprite en las coordenadas 100,100
        self.rect.x = x
        self.rect.y = y
        
        # Cuenta el número de joysticks conectados al PC
        numero_de_joysticks = pygame.joystick.get_count()
        if numero_de_joysticks < joystick_no+1:
            # No hay joysticks!
            print("Error. No he encontrado suficientes joysticks. Solo hay ", numero_de_joysticks)
        else:
            # Usa joystick #0 e inicialízalo
            self.mi_joystick = pygame.joystick.Joystick(joystick_no)
            self.mi_joystick.init()
        

    def update(self):
        """ Actualiza la posición del protagonista. """
        # Mientras haya un joystick
        if self.mi_joystick != None:
        
            # Esto obtiene la posición del eje en el controlador de juego
            # Devuelve un número entre -1.0 y +1.0
            vert_axis_pos = self.mi_joystick.get_axis(1)   
            
            
            # Multiplicamos por 10 para acelerar el movimiento.
            self.rect.y = self.rect.y+vert_axis_pos*10
            
            # Si el jugador se mueve más allá de los límites de la pantalla, restablece la posición
            # sobre el borde.
            if self.rect.y < 0:
                self.rect.y = 0
            if self.rect.y > alto_pantalla - self.alto:
                self.rect.y = alto_pantalla - self.alto

class Pared(pygame.sprite.Sprite):
    """ Esta clase representa las paredes en la partes superior e inferior de la
        pantalla. """

    # Función constructor
    def __init__(self, x, y, largo, alto):
        # Llama al constructor padre
        super().__init__()

        # Crea una pared AZUL con el tamaño especificado por los parámetros
        self.image = pygame.Surface([largo, alto])
        self.image.fill((AZUL))

        # Determina que la esquina superior izquierda sea la ubicación inicial.
        self.rect = self.image.get_rect()
        self.rect.y = y
        self.rect.x = x
        
class Pelota(pygame.sprite.Sprite):
    """ Esta clase representa la pelota que rebota por ahí. """

    # Establece la velocidad del vector
    cambio_x = 0
    cambio_y = 0
    paredes = None
    
    # Función constructor
    def __init__(self, x, y, paredes):
        #  Llama al constructor de la clase padre
        super().__init__()
 
        # Establecemos el  alto, largo
        self.image = pygame.Surface([15, 15])
        self.image.fill(BLANCO)

        # Determina que la esquina superior izquierda sea la ubicación inicial.
        self.rect = self.image.get_rect()
        self.rect.y = y
        self.rect.x = x        
        self.paredes = paredes
        
    def update(self):
        """ Actualiza la posición de la pelota. """
        # Obtiene la posición anterior para el caso que necesitemos volver a ella
        x_anterior = self.rect.x
        x_nueva = x_anterior + self.cambio_x
        self.rect.x = x_nueva
        
        # ¿Es que la última actualización hizo que la pelota chocara contra la pared?
        colisionar = pygame.sprite.spritecollide(self, self.paredes, False)
        if colisionar:
            # Ups! hemos dado contra la pared. Volvamos a la posición anterior
            self.rect.x = x_anterior
            self.cambio_x *= -1

        y_anterior = self.rect.y
        y_nueva = y_anterior + self.cambio_y
        self.rect.y = y_nueva
        
        #  ¿Es que la última actualización hizo que la pelota chocara contra la pared?
        colisionar = pygame.sprite.spritecollide(self, self.paredes, False)
        if colisionar:
            # Ups! hemos dado contra la pared. Volvamos a la posición anterior
            self.rect.y = y_anterior
            self.cambio_y *= -1
            
        if self.rect.x < -20 or self.rect.x > largo_pantalla + 20:
            self.cambio_x = 0
            self.cambio_y = 0

            
# Llamamos a esta función para que la biblioteca Pygame pueda inicializarse.
pygame.init()

# Creamos una pantalla de 800x600
largo_pantalla = 800
alto_pantalla = 600

pantalla = pygame.display.set_mode([largo_pantalla, alto_pantalla])

# Establecemos el título de la ventana
pygame.display.set_caption('Test')

# Creamos una superficie sobre la que podamos dibujar
fondo_pantalla = pygame.Surface(pantalla.get_size())

# Usado para convertir cosas como mapa de colores
fondo_pantalla = fondo_pantalla.convert()

# Rellenamos la pantalla con color NEGRO
fondo_pantalla.fill(NEGRO)

# Listas de todos los sprites
lista_paredes = pygame.sprite.Group()
todos_los_sprites = pygame.sprite.Group()
sprites_en_movimiento = pygame.sprite.Group()

# Creamos a los protagonistas
protagonista1 = Protagonista(10, alto_pantalla/2, 0)
todos_los_sprites.add(protagonista1)
lista_paredes.add(protagonista1)
sprites_en_movimiento.add(protagonista1)

protagonista2 = Protagonista(largo_pantalla - 20, alto_pantalla/2, 1)
todos_los_sprites.add(protagonista2)
lista_paredes.add(protagonista2)
sprites_en_movimiento.add(protagonista2)

# Construimos las paredes. (x_pos, y_pos, largo, alto)
# Pared superior
pared = Pared(0, 0, largo_pantalla, 10) 
lista_paredes.add(pared)
todos_los_sprites.add(pared)

# Pared inferior
pared = Pared(0, alto_pantalla - 10, largo_pantalla, alto_pantalla) 
lista_paredes.add(pared)
todos_los_sprites.add(pared)

# Creamos la pelota
pelota = Pelota(-50, -50, lista_paredes )
sprites_en_movimiento.add(pelota)
todos_los_sprites.add(pelota)

reloj = pygame.time.Clock()

hecho = False

# Bucle principal
while not hecho:
    
    # Itera a través de cualquier evento de la ventana
    for evento in pygame.event.get():
        # El usuario hizo click sobre 'cerrar' o apretó las teclas Alt-F4
        if evento.type == pygame.QUIT:
            hecho = True
            
        # El usuario apretó un botón del ratón
        # o presionó una tecla
        elif evento.type == pygame.MOUSEBUTTONDOWN or evento.type == pygame.KEYDOWN:
            
            # ¿No se está moviendo la pelota?
            if pelota.cambio_y == 0:
                
                # Empieza en la mitad de la pantalla sobre una ubicación y aleatoria
                pelota.rect.x = largo_pantalla/2
                pelota.rect.y = random.randrange(10, alto_pantalla - 0)
                
                # Establecemos un vector aleatorio
                pelota.cambio_y = random.randrange(-5, 6)
                pelota.cambio_x =  random.randrange(5, 10)
                
                # ¿La pelota se dirige a la izquierda o a la derecha? Selecciona aleatoriamente
                if( random.randrange(2) == 0 ):
                    pelota.cambio_x *= -1

                
    # Actualiza la posición de la pelota. Le pasamos la lista de objetos con los que puede rebotar
    sprites_en_movimiento.update()
    
    # Limpiamos la pantalla
    pantalla.fill(NEGRO)
    
    # Dibujamos los sprites
    todos_los_sprites.draw(pantalla)

    # Mostramos la pantalla
    pygame.display.flip()

    reloj.tick(30)

# Trabajo hecho, apagamos Pygame            
pygame.quit()