Curso de videojuegos con Pygame

Sistema de puntuación y texto con Pygame

Capítulo 16: Sistema de puntuaciones y mostrar texto en la pantalla

En este capítulo vas a ver como crear un pequeño sistema de puntuaciones que se va a mostrar en la pantalla. Esto también te servirá para aprender a mostrar cualquier texto en la pantalla.

La idea de este capítulo, es hacer que aparezcan diferentes tipos de naves enemigas y que cada una nos dé diferentes puntuaciones.
Para ello, he coloreado la imagen de la nave enemiga que utilizaba hasta ahora de diferentes colores.
En el vídeo te muestro cómo lo he hecho con Photoshop.

Una vez tenemos las imágenes listas, es hora de crear algunas clases para los nuevos enemigos.

Clases para los enemigos

En estas clases, puedes añadir todas las habilidades que quieras, para que se vayan diferenciando unos enemigos de otros. En mi caso los voy a dejar casi iguales, pero se pueden cambiar muchas cosas, solo hay que echarle imaginación. Yo solo he cambiado la imagen y el rango de velocidad posible de ellos.

Te dejo aquí las cuatro imágenes de los enemigos por si las quieres utilizar: enemigos.zip

Clase EnemigosAmarillos

class EnemigosAmarillos(pygame.sprite.Sprite):
	def __init__(self):
		super().__init__()
		self.image = pygame.image.load("principal/enemigo1.png").convert()
		self.rect = self.image.get_rect()
		self.image.set_colorkey(NEGRO)
		self.radius = 48
		self.rect.x = random.randrange(ANCHO - self.rect.width)
		self.rect.y = random.randrange(ALTO - self.rect.height)
		self.velocidad_x = random.randrange(1,3)
		self.velocidad_y = random.randrange(1,3)

	def update(self):
		# Actualiza la velocidad del enemigo
		self.rect.x += self.velocidad_x
		self.rect.y += self.velocidad_y

		# Limita el margen izquierdo
		if self.rect.left < 0:
			self.velocidad_x += 1

		# Limita el margen derecho
		if self.rect.right > ANCHO:
			self.velocidad_x -= 1

		# Limita el margen inferior
		if self.rect.bottom > ALTO:
			self.velocidad_y -= 1

		# Limita el margen superior
		if self.rect.top < 0:
			self.velocidad_y += 1

Clase EnemigosVerdes

class EnemigosVerdes(pygame.sprite.Sprite):
	def __init__(self):
		super().__init__()
		self.image = pygame.image.load("principal/enemigo2.png").convert()
		self.rect = self.image.get_rect()
		self.image.set_colorkey(NEGRO)
		self.radius = 48
		self.rect.x = random.randrange(ANCHO - self.rect.width)
		self.rect.y = random.randrange(ALTO - self.rect.height)
		self.velocidad_x = random.randrange(3,5)
		self.velocidad_y = random.randrange(3,5)

	def update(self):
		# Actualiza la velocidad del enemigo
		self.rect.x += self.velocidad_x
		self.rect.y += self.velocidad_y

		# Limita el margen izquierdo
		if self.rect.left < 0:
			self.velocidad_x += 1

		# Limita el margen derecho
		if self.rect.right > ANCHO:
			self.velocidad_x -= 1

		# Limita el margen inferior
		if self.rect.bottom > ALTO:
			self.velocidad_y -= 1

		# Limita el margen superior
		if self.rect.top < 0:
			self.velocidad_y += 1

Clase EnemigosAzules

class EnemigosAzules(pygame.sprite.Sprite):
	def __init__(self):
		super().__init__()
		self.image = pygame.image.load("principal/enemigo3.png").convert()
		self.rect = self.image.get_rect()
		self.image.set_colorkey(NEGRO)
		self.radius = 48
		self.rect.x = random.randrange(ANCHO - self.rect.width)
		self.rect.y = random.randrange(ALTO - self.rect.height)
		self.velocidad_x = random.randrange(5,10)
		self.velocidad_y = random.randrange(5,10)

	def update(self):
		# Actualiza la velocidad del enemigo
		self.rect.x += self.velocidad_x
		self.rect.y += self.velocidad_y

		# Limita el margen izquierdo
		if self.rect.left < 0:
			self.velocidad_x += 1

		# Limita el margen derecho
		if self.rect.right > ANCHO:
			self.velocidad_x -= 1

		# Limita el margen inferior
		if self.rect.bottom > ALTO:
			self.velocidad_y -= 1

		# Limita el margen superior
		if self.rect.top < 0:
			self.velocidad_y += 1

Clase EnemigosRojos

class EnemigosRojos(pygame.sprite.Sprite):
	def __init__(self):
		super().__init__()
		self.image = pygame.image.load("principal/enemigo4.png").convert()
		self.rect = self.image.get_rect()
		self.image.set_colorkey(NEGRO)
		self.radius = 48
		self.rect.x = random.randrange(ANCHO - self.rect.width)
		self.rect.y = random.randrange(ALTO - self.rect.height)
		self.velocidad_x = random.randrange(10,15)
		self.velocidad_y = random.randrange(10,15)

	def update(self):
		# Actualiza la velocidad del enemigo
		self.rect.x += self.velocidad_x
		self.rect.y += self.velocidad_y

		# Limita el margen izquierdo
		if self.rect.left < 0:
			self.velocidad_x += 1

		# Limita el margen derecho
		if self.rect.right > ANCHO:
			self.velocidad_x -= 1

		# Limita el margen inferior
		if self.rect.bottom > ALTO:
			self.velocidad_y -= 1

		# Limita el margen superior
		if self.rect.top < 0:
			self.velocidad_y += 1

Ya no existe la clase Enemigos a secas, así que elimina su grupo de sprites de tu código y crea cuatro nuevos para los diferentes enemigos:

enemigos_amarillos = pygame.sprite.Group()
enemigos_verdes = pygame.sprite.Group()
enemigos_azules = pygame.sprite.Group()
enemigos_rojos = pygame.sprite.Group()

Los instanciamos y añadimos a sus correspondientes grupos de sprites:

enemigo1 = EnemigosAmarillos()
enemigos_amarillos.add(enemigo1)

enemigo2 = EnemigosVerdes()
enemigos_verdes.add(enemigo2)

enemigo3 = EnemigosAzules()
enemigos_azules.add(enemigo3)

enemigo4 = EnemigosRojos()
enemigos_rojos.add(enemigo4)

Y no te olvides de los update y los draw:

enemigos_amarillos.update()
enemigos_verdes.update()
enemigos_azules.update()
enemigos_rojos.update()
enemigos_amarillos.draw(pantalla)
enemigos_verdes.draw(pantalla)
enemigos_azules.draw(pantalla)
enemigos_rojos.draw(pantalla)

Mostrar texto en pantalla

Pasemos al objetivo principal de este capítulo, añadir texto a los juegos y un sistema de puntuación.

Para la puntuación, es tan simple como especificarla en una variable:

puntuacion = 0

Fuentes de letra en Pygame

Ahora, para mostrar texto, lo primero es especificar un pequeño catálogo de fuentes, las que vayas a necesitar.
Pygame buscará el nombre aproximado de la fuente en el equipo, así que basta con poner su nombre así tal cual.

consolas = pygame.font.match_font('consolas')
times = pygame.font.match_font('times')
arial = pygame.font.match_font('arial')
courier = pygame.font.match_font('courier')

Por el momento, Pygame no cuenta con un método o función específico para mostrar texto de forma fácil.

Por eso, te recomiendo que crees una función que te va a servir para todos tus juegos.
Esta función te va a facilitar mucho las cosas.

Le especificamos como argumentos pantalla (va a ser donde se va a mostrar el texto), fuente, color, dimensiones o tamaño y por último x e Y para posicionar el texto.
Una variable para especificar la fuente y su tamaño (tipo_letra).
También especificaré la forma en la que se va a mostrar el texto, el color del texto y el propio texto.
Pygame nos ofrece con anti-aliasing o sin él.

Antialiasing Pygame

Con antialiasing los bordes de las letras o números van a aparecer difuminados, dando un toque más atractivo. En cambio, si quieres algo más retro, las letras con bordes pixelados son una buena opción.

Además, cómo todo en Pygame, hay que obtener el rectángulo y le definimos x e y para posicionarlo por la pantalla con la variable rectangulo.

Y por último el blit que va a mostrar el texto en la pantalla.

Para que veas lo complicado que es mostrar un simple texto. Lo que pasa es que ahora, reutilizando esta función, podrás escribirlo con una sola línea en la llamada las veces que sea necesario.

def muestra_texto(pantalla,fuente,texto,color, dimensiones, x, y):
	tipo_letra = pygame.font.Font(fuente,dimensiones)
	superficie = tipo_letra.render(texto,True, color)
	rectangulo = superficie.get_rect()
	rectangulo.center = (x, y)
	pantalla.blit(superficie,rectangulo)

La llamada a la función la deberás hacer dentro del bucle del juego, para que se vaya actualizando.

muestra_texto(pantalla,consolas,str(puntuacion), ROJO, 40, 700, 50)

Sumar puntuación

Lo siguiente es hacer que cada enemigo nos sume una puntuación diferente según su color.
Para ello, he creado cuatro colisiones con los cuatro grupos de enemigos y cuatro if con un incremento diferente para cada uno de ellos.

colision_disparos_amarillos = pygame.sprite.groupcollide(enemigos_amarillos, balas, True, True, pygame.sprite.collide_circle)

colision_disparos_verdes = pygame.sprite.groupcollide(enemigos_verdes, balas, True, True, pygame.sprite.collide_circle)

colision_disparos_azules = pygame.sprite.groupcollide(enemigos_azules, balas, True, True, pygame.sprite.collide_circle)

colision_disparos_rojos = pygame.sprite.groupcollide(enemigos_rojos, balas, True, True, pygame.sprite.collide_circle)

if colision_disparos_amarillos:
	puntuacion += 10

if colision_disparos_verdes:
	puntuacion += 25

if colision_disparos_azules:
	puntuacion += 50

if colision_disparos_rojos:
	puntuacion += 100

Ejercicio para el próximo capítulo

Yo soy de los que considera que una puntuación estilo retro debe ir con varios ceros. Ahora, si cargamos el juego se muestra solo uno.
¿Cómo harías para mostrar varios ceros y que quedase de esta forma?

Puntuaciones en Pygame

La respuesta la daré en el siguiente capítulo, puedes dejarla en los comentarios y te diré si está bien o mal.


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.