Añadiendo meteoritos random y generación infinita - Curso Pygame - Capítulo 15


En este capítulo vamos a ver como crear meteoritos de tamaños aleatorios con velocidades aleatorias, spawn o generación infinita y con colisiones.

Puede parecer mucha cosa pero si has seguido el curso hasta aquí, la mayoría ya sabes como hacerlo.

La clase Meteoritos

Para empezar creamos una clase para los meteoritos.

Aquí tienes la imagen de meteorito: meteorito.png

Código

class Meteoritos(pygame.sprite.Sprite):
    def __init__(self):
        # Heredamos el init de la clase Sprite de Pygame
        super().__init__()
        # Rectángulo (enemigos)

Hasta aquí como siempre.
Ahora, en lugar de cargar una imagen para los meteoritos, voy a crear la posibilidad, de que se generen de forma aleatoria meteoritos de diferentes tamaños.
Lo que voy a hacer, se puede hacer de muchas formas. Si sabes hacerlo de una forma mejor o diferente, déjamelo en los comentarios y lo probaré con mucho gusto.
Lo primero es crear una variable con un randrange de 3 si quieres que haya 3 tipos de meteoritos o enemigos, porque esto pueden ser meteoritos o pueden ser enemigos o cualquier otro objeto de tu juego.

Código

self.img_aleatroria = random.randrange(3)

Lo siguiente son tres if, uno para cada caso posible.
La imagen la redimensiono a 100x100 píxeles.
Y finalmente un radio para las colisiones.

Código

if self.img_aleatroria == 0:
    self.image = pygame.transform.scale(pygame.image.load("principal/meteorito.png").convert(),(100,100))
    self.radius = 50

Escribo los otros dos posibles casos, y les especifico diferentes tamaños.
Imagen solo hay una, pero va a mostrarse en 3 posibles tamaños, así, ahorramos recursos.

Código

if self.img_aleatroria == 1:
    self.image = pygame.transform.scale(pygame.image.load("principal/meteorito.png").convert(),(50,50))
    self.radius = 25

if self.img_aleatroria == 2:
    self.image = pygame.transform.scale(pygame.image.load("principal/meteorito.png").convert(),(25,25))
    self.radius = 12

Aquí, lo que va a pasar es que cada ciclo del juego, va a tomar un valor distinto la variable img_aleatoria, del 0 al 2 y eso hará que unas veces se instancie un objeto con la imagen 0, otras con la 1 y otras con la 2.

Meteoritos de distintos tamaños en Pygame

Ponemos el set colorkey y obtenemos el rectángulo de la imagen.

Código

self.image.set_colorkey(NEGRO)
self.rect = self.image.get_rect()

Si queremos que los meteoritos aparezcan por todo el ancho de la pantalla:

Código

self.rect.x = random.randrange(ANCHO)

En Y que se generen por la parte de arriba antes del 0, es decir, que se generen según su ancho por fuera de la pantalla, para que vayan apareciendo de una forma más natural.
En este caso, te vale con rect.width y height, ya que en estos meteoritos los tamaños de alto y ancho son iguales (100x100, 50x50 o 25x25) y de esta forma, nos evitamos poner tres if más con los tamaños diferentes.

Código

self.rect.y = -self.rect.width

Le damos una velocidad inicial aleatoria de entre 1 y 15 o la que quieras.

Código

self.velocidad = random.randrange(1, 15)

El método update

Le añadimos el método update y en él incrementamos en Y con la velocidad aleatoria.

Código

def update(self):
    self.rect.y += self.velocidad

Y que cuando la parte superior del meteorito salga por la parte inferior de la pantalla, que genere más meteoritos. En estas posiciones, en X e Y, lo dejamos que sea igual que el estado inicial.

Código

self.rect.x = random.randrange(ANCHO)
self.rect.y = -100

Por último la velocidad igual que en el __init__.

Código

self.velocidad = random.randrange(1, 15)

Creación del grupo de sprites, instanciaciones, update y draw

Creamos grupo de sprites:

Código

meteoritos = pygame.sprite.Group()

Instanciamos hasta 10 meteoritos:

Código

for x in range(10):
    meteorito = Meteoritos()
    meteoritos.add(meteorito)

Añadimos el update y el draw en sus lugares correspondientes.

Código

meteoritos.update()
meteoritos.draw(pantalla)

Si lo ejecutas así, aparentemente está todo correcto, pero hay algunos meteoritos que en coordenadas X se generan un trozo fuera, dando un mal aspecto al juego. Esto es tan fácil de solucionar como darle un rango de ANCHO - el propio ancho del rectángulo, cosa que ya hemos visto en capítulos anteriores.

Añade la siguiente línea tanto en el __init__ de la clase Meteoritos como en su método update.

Código

self.rect.x = random.randrange(ANCHO - self.rect.width)

Código

self.rect.x = random.randrange(ANCHO - self.rect.width)

Colisiones

Para terminar con el capítulo añadamos las colisiones a estos meteoritos.
He añadido dos if con un print para poder probar de manera fácil y rápida las colisiones, así no tienes que estar ejecutando el juego múltiples veces para hacer pruebas.

Código

colision_nave = pygame.sprite.spritecollide(jugador, meteoritos, False, pygame.sprite.collide_circle)
colision_disparos = pygame.sprite.groupcollide(meteoritos, balas, False, False, pygame.sprite.collide_circle)

if colision_nave:
    print("Colisión de la nave...")
if colision_disparos:
    print("Colisión por disparo...")

Y hasta aquí este capítulo número 15.
Como recomendación, tendrás que ir ajustando los diferentes radius de cada tipo de meteorito según los tamaños de tus imágenes y dejarlos lo más ajustados posible para crear una mejor experiencia de juego.


Suscríbete a mi canal de YouTube para apoyarme

Si te ha gustado este curso y crees que el trabajo merece la pena, te agradeceré eternamente que te suscribas a mi canal de YouTube para apoyarme y que pueda seguir haciendo cursos gratuitos.

Además, si te encanta la programación, tienes un montón más de cursos gratuitos para ver.

No solo eso, podrás participar enviándome comentarios con tus sugerencias para temas específicos o cursos completos o incluso las dudas que tengas y las intentaré ir resolviendo en los cursos que estén todavía abiertos.


Comentarios

Si te quedan dudas sobre el temario, sobre Python, o cualquier otra cosa relacionada o simplemente quieres agradecer, aquí tienes tu sitio para dejar tu granito de arena. Gracias por tus comentarios y por darle vida a este sitio web.