Curso de videojuegos con Pygame

Generación infinita de meteoritos aleatorios con Pygame

Capítulo 15: Añadiendo meteoritos random y generación infinita

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.

Creando una clase para Meteoritos con Pygame

Para empezar creamos una clase para los meteoritos.

Aquí tienes la imagen de meteorito: meteorito.png

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 tres tipos de meteoritos o enemigos, porque esto pueden ser meteoritos o pueden ser enemigos o cualquier otro objeto de tu juego.

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.

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 tres posibles tamaños, así, ahorramos recursos.

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.

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

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

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.

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

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

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.

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

Además, 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.

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

Por último la velocidad igual que en el __init__.

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

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

Creamos un grupo de sprites:

meteoritos = pygame.sprite.Group()

Instanciamos hasta 10 meteoritos:

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

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

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.

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

Crear colisiones para los meteoritos

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.

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 quince.
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.


Comentarios

Si te quedan dudas sobre el temario, sobre Python, Pygame 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.

Programación Fácil YouTube

Suscríbete

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.