Sistema de puntuaciones y mostrar texto en la pantalla - Curso Pygame - Capítulo 16


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

Código 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

Código 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

Código clase EnemigosAzules

class EnemigosVerdes(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

Código clase EnemigosRojos

class EnemigosVerdes(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 elimína su grupo de sprites de tu código y crea cuatro nuevos para los diferentes enemigos:

Código

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:

Código

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

Código

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, tan simple como especificarla en una variable:

Código

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.

Código

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.

Código

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.

Código

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.

Código

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.


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.