Entrada destacada

Como usar enums en Android, kotlin

Pygame y la programación orientada a objetos (animación de partículas)

Usado programación orientada a objetos con pygame para crear partículas.



Nota: Este no es un tutorial de programación orientada a objetos si no más bien un tutorial de cómo usar programación orientada a objetos en el desarrollo de videojuegos y específicamente con pygame.


La idea base de este tutorial es crear múltiples figuras de colores y tamaños aleatorios al hacer clic sobre la pantalla y que estos se desplacen en distintas direcciones, tomando como punto de partida la posición de la pantalla en la que se hizo clic.

Creando la clase Rectangulo.


class Rectangulo():
    def __init__(self):
        self.x = 0
        self.y = 0
        self.width = random.randrange(3, 10)
        self.height = self.width
        self.move_x = random.randrange(-3, 5)
        self.move_y = random.randrange(-3, 5)
        self.color = COLOR

Definimos una clase una clase base con las propiedades de un rectángulo por lo tanto en su constructor definimos dos variables para almacenar la posición de cada objeto (x, y), dos más para almacenar el ancho y el alto, el ancho de cada objeto será inicializado con valores aleatorios entre 3 y 10 y a la altura le pasamos el mismo valor que el valor de ancho así las medidas serán correspondiente a un cuadrado.

        self.move_x = random.randrange(-3, 5)
        self.move_y = random.randrange(-3, 5)

Las propiedades move_x y move_y controlaran la velocidad con se mueven los objetos en diagonal en caso que los ambos valores sean diferentes de 0. Los valores de estas propiedades pueden ser entre -3 y 5, se usan valores negativos para que el avance de los objetos en la pantalla puedan ser hacia la izquierda en x y hacia arriba en y.
Finalmente la última propiedad almacenara el color con el que se dibujará el cuadrado, inicialmente todos comienzan con el mismo color COLOR = (26, 150, 120)

Dentro de la clase Rectangulo definiremos dos métodos, una para dibujar el objeto y otra para modificar las posiciones del objeto.

    def mover(self):
        self.x += self.move_x
        self.y += self.move_y

    def draw(self, pantalla):
        pygame.draw.rect(pantalla, self.color, [self.x, self.y, self.width, self.height])

El método mover suma a las posiciones su correspondiente valor de movimiento (move_x y move_y) cada que se llama a dicho método que como ya mencionamos bien puede restar o sumar dependiendo que valor aleatorio se generó inicialmente.
El método draw dibuja un rectángulo con las propiedades que se le han dado al objeto.

Como la clase Rectangulo estará en un archivo separado (concepto que en python se le llama modulo), necesitamos importar las librerías que se ocupen en está clase. El siguiente sería el modulo completo.

Rectangulo.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import pygame
import random

COLOR = (26, 150, 120)

class Rectangulo():
    def __init__(self):
        self.x = 0
        self.y = 0
        self.width = random.randrange(3, 10)
        self.height = self.width
        self.move_x = random.randrange(-3, 5)
        self.move_y = random.randrange(-3, 5)
        self.color = COLOR

    def mover(self):
        self.x += self.move_x
        self.y += self.move_y

    def draw(self, pantalla):
        pygame.draw.rect(pantalla, self.color, [self.x, self.y, self.width, self.height])

Creando el programa principal

Comenzamos importando pygame, random para la generación de números aleatorios y el modulo Rectangulo, que ojo, no es el nombre de la clase si no del archivo. Después en la línea 5 se define el color de fondo y en la línea 6 almacenamos la cantidad de partículas que se generarán por cada clic.

1
2
3
4
5
6
import pygame
import random
import Rectangulo

FONDO = (14, 16, 30)
cantidad_particulas = 50

Para crear múltiples objetos de la clase Rectangulo usamos la función creaParticulas con la ayuda de un bucle for creamos el número de objetos deseados la variable cantidad_particulas nos ayuda a controlar ese número. Para crear objetos de la clase Rectangulo hacemos el llamado al modulo punto y seguido del método constructor, ver línea 11. Una vez creada la instancia se le asignan valores iniciales, como las coordenadas y color.

8
9
10
11
12
13
14
15
16
def creaParticulas(x, y):
    particulasLista = []
    for i in range(cantidad_particulas):
        rectangulo = Rectangulo.Rectangulo()
        rectangulo.x = x
        rectangulo.y = y
        rectangulo.color = colorAleatorio()
        particulasLista.append(rectangulo)
    return particulasLista

A cada objeto se le asigna un color diferente que obtenemos con la función colorAleatorio() la cual básicamente devuelve una tupla de tres números aleatorios entre 0 y 255.

18
19
20
21
22
def colorAleatorio():
    r = random.randrange(255)
    g = random.randrange(255)
    b = random.randrange(255)
    return (r, g, b)

Los objetos son dibujados iniciando en la posición que sea hace click con el ratón, pero inicialmente se crean en una posición aleatoria, de igual forma cada que todos los objetos de una lista salen de la pantalla se vuelve a regenerar en una posición aleatoria.

24
25
def posicionAleatoria():
    return [random.randrange(700), random.randrange(500)]

En la función principal iniciamos las configuraciones básicas para el funcionamiento de pygame. Las líneas 35, 36 y 37 inician un conjunto de partículas en una posición aleatoria, lista_particulas es una lista de listas, digamos que lista_particulas es la lista que contiene explosiones y cada explosión está compuesta por n partículas.

35
36
37
    lista_particulas = []
    x, y = posicionAleatoria()
    lista_particulas.append(creaParticulas(x, y))

Cada que se detecta un click dentro de la pantalla se agrega una lista de partículas a la lista principal.

44
45
46
           elif evento.type == pygame.MOUSEBUTTONDOWN and evento.button == 1:
               x, y = evento.pos
               lista_particulas.append(creaParticulas(x, y))

Finalmente para dibujar cada una de las explosiones y a cada una de las partículas recorremos la lista con dos ciclos for, cada partícula es dibujada llamando a su método draw()  y lo movemos de posición con mover(). El if de la línea 55 comprueba si la partícula ah salido de la ventana, si ha salido la partícula es eliminada de la sub_lista. En la lista 58 se comprueba si la sub_lista aún contiene partículas,  en caso de que esté vacía sea rellena el espacio con una nueva lista de particulas que inician en una posición aleatoria.


 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
        for sub_lista in lista_particulas:
            j = 0
            for particula in sub_lista:
                particula.draw(pantalla)
                particula.mover()
                if particula.x > dimensiones[0] or particula.x < 0 or particula.y > dimensiones[1] or particula.y < 0 or particula.move_x == 0 or particula.move_y == 0:
                    lista_particulas[i].pop(j)
                j += 1
            if(len(sub_lista) == 0):
                x, y = posicionAleatoria()
                lista_particulas[i] = creaParticulas(x, y)
            i += 1

Código fuente.


Particulas.py


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import pygame
import random
import Rectangulo

FONDO = (14, 16, 30)
cantidad_particulas = 50

def creaParticulas(x, y):
    particulasLista = []
    for i in range(cantidad_particulas):
        rectangulo = Rectangulo.Rectangulo()
        rectangulo.x = x
        rectangulo.y = y
        rectangulo.color = colorAleatorio()
        particulasLista.append(rectangulo)
    return particulasLista

def colorAleatorio():
    r = random.randrange(255)
    g = random.randrange(255)
    b = random.randrange(255)
    return (r, g, b)

def posicionAleatoria():
    return [random.randrange(700), random.randrange(500)]

def main():
    """Funcion Principal"""
    pygame.init()
    dimensiones = [700, 500]
    pantalla = pygame.display.set_mode(dimensiones)
    pygame.display.set_caption("Particulas")
    hecho = False

    lista_particulas = []
    x, y = posicionAleatoria()
    lista_particulas.append(creaParticulas(x, y))

    reloj = pygame.time.Clock()
    while not hecho:
        for evento in pygame.event.get():
           if evento.type == pygame.QUIT:
               hecho = True
           elif evento.type == pygame.MOUSEBUTTONDOWN and evento.button == 1:
               x, y = evento.pos
               lista_particulas.append(creaParticulas(x, y))
        pantalla.fill(FONDO)

        i = 0
        for sub_lista in lista_particulas:
            j = 0
            for particula in sub_lista:
                particula.draw(pantalla)
                particula.mover()
                if particula.x > dimensiones[0] or particula.x < 0 or particula.y > dimensiones[1] or particula.y < 0 or particula.move_x == 0 or particula.move_y == 0:
                    lista_particulas[i].pop(j)
                j += 1
            if(len(sub_lista) == 0):
                x, y = posicionAleatoria()
                lista_particulas[i] = creaParticulas(x, y)
            i += 1
        pygame.display.flip()
        reloj.tick(60)

    pygame.quit()

if __name__ == "__main__":
    main()

Comenta tus dudas en la sección de comentarios.




Comentarios