Curso Python. Volumen XXI: Pygame, videojuegos en python. Parte IX

Curso Python. Volumen XXI: Pygame, videojuegos en python. Parte IX

Javier Ceballos Fernández

Bienvenidos un día más al curso de Python. En el capítulo anterior os enseñamos como crear un jugador ficticio para por lo menos poder jugar contra el ordenador. En este capítulo, vamos a agregar sonido al videojuego que estamos realizando con la popular librería “Pygame”. Así que pongámonos manos a la obra.

Sonido

Para agregar los sonidos tendremos que hacer las siguientes modificaciones al código:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# ---------------------------
# Importacion de los módulos
# ---------------------------

import pygame
from pygame.locals import *
import os
import sys

# -----------
# Constantes
# -----------

SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
IMG_DIR = "imagenes"
SONIDO_DIR = "sonidos"

# ------------------------------
# Clases y Funciones utilizadas
# ------------------------------

def load_image(nombre, dir_imagen, alpha=False):
# Encontramos la ruta completa de la imagen
ruta = os.path.join(dir_imagen, nombre)
try:
image = pygame.image.load(ruta)
except:
print("Error, no se puede cargar la imagen: " + ruta)
sys.exit(1)
# Comprobar si la imagen tiene "canal alpha" (como los png)
if alpha is True:
image = image.convert_alpha()
else:
image = image.convert()
return image

def load_sound(nombre, dir_sonido):
ruta = os.path.join(dir_sonido, nombre)
# Intentar cargar el sonido
try:
sonido = pygame.mixer.Sound(ruta)
except (pygame.error) as message:
print("No se pudo cargar el sonido:", ruta)
sonido = None
return sonido

# -----------------------------------------------
# Creamos los sprites (clases) de los objetos del juego:

class Pelota(pygame.sprite.Sprite):
"La bola y su comportamiento en la pantalla"

def __init__(self, sonido_golpe, sonido_punto):
pygame.sprite.Sprite.__init__(self)
self.image = load_image("bola.png", IMG_DIR, alpha=True)
self.rect = self.image.get_rect()
self.rect.centerx = SCREEN_WIDTH / 2
self.rect.centery = SCREEN_HEIGHT / 2
self.speed = [3, 3]
self.sonido_golpe = sonido_golpe
self.sonido_punto = sonido_punto

def update(self):
if self.rect.left < 0 or self.rect.right > SCREEN_WIDTH:
self.speed[0] = -self.speed[0]
self.sonido_punto.play() # Reproducir sonido de punto
if self.rect.top < 0 or self.rect.bottom > SCREEN_HEIGHT:
self.speed[1] = -self.speed[1]
self.rect.move_ip((self.speed[0], self.speed[1]))

def colision(self, objetivo):
if self.rect.colliderect(objetivo.rect):
self.speed[0] = -self.speed[0]
self.sonido_golpe.play() # Reproducir sonido de rebote

class Paleta(pygame.sprite.Sprite):
"Define el comportamiento de las paletas de ambos jugadores"

def __init__(self, x):
pygame.sprite.Sprite.__init__(self)
self.image = load_image("paleta.png", IMG_DIR, alpha=True)
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.centery = SCREEN_HEIGHT / 2

def humano(self):
# Controlar que la paleta no salga de la pantalla
if self.rect.bottom >= SCREEN_HEIGHT:
self.rect.bottom = SCREEN_HEIGHT
elif self.rect.top <= 0: self.rect.top = 0 def cpu(self, objetivo): self.rect.centery = objetivo.rect.centery if self.rect.bottom >= SCREEN_HEIGHT:
self.rect.bottom = SCREEN_HEIGHT
elif self.rect.top <= 0:
self.rect.top = 0

# ------------------------------
# Funcion principal del juego
# ------------------------------

def main():
pygame.init()
pygame.mixer.init()
# creamos la ventana y le indicamos un titulo:
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Pong")

# cargamos los objetos
fondo = load_image("fondo.jpg", IMG_DIR, alpha=False)
sonido_golpe = load_sound("tennis.ogg", SONIDO_DIR)
sonido_punto = load_sound("aplausos.ogg", SONIDO_DIR)

bola = Pelota(sonido_golpe, sonido_punto)
jugador1 = Paleta(40)
jugador2 = Paleta(SCREEN_WIDTH - 40)

clock = pygame.time.Clock()
pygame.key.set_repeat(1, 25) # Activa repeticion de teclas
pygame.mouse.set_visible(False)

# el bucle principal del juego
while True:
clock.tick(60)
# Obtenemos la posicion del raton
pos_mouse = pygame.mouse.get_pos()
mov_mouse = pygame.mouse.get_rel()

# Actualizamos los objetos en pantalla
jugador1.humano()
jugador2.cpu(bola)
bola.update()

# Comprobamos si colisionan los objetos
bola.colision(jugador1)
bola.colision(jugador2)

# Posibles entradas del teclado y raton
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit(0)
elif event.type == pygame.KEYDOWN:
if event.key == K_UP:
jugador1.rect.centery -= 5
elif event.key == K_DOWN:
jugador1.rect.centery += 5
elif event.key == K_ESCAPE:
sys.exit(0)
elif event.type == pygame.KEYUP:
if event.key == K_UP:
jugador1.rect.centery += 0
elif event.key == K_DOWN:
jugador1.rect.centery += 0
# Si el raton no esta quieto, mover la paleta a su posicion
elif mov_mouse[1] != 0:
jugador1.rect.centery = pos_mouse[1]

# actualizamos la pantalla
screen.blit(fondo, (0, 0))
screen.blit(bola.image, bola.rect)
screen.blit(jugador1.image, jugador1.rect)
screen.blit(jugador2.image, jugador2.rect)
pygame.display.flip()

if __name__ == "__main__":
main()

Lo primero que hemos realizado ha sido crear una función que cargue los sonidos “load_sound”, es muy parecida a la función de cargar imágenes. Para abrir el archivo usamos el módulo “pygame.mixer.Sound” abriendo el sonido de la forma “sonido = pygame.mixer.Sound(ruta)”

Después tenemos que iniciar el modulo “mixer”, que es el que se encarga de los sonidos, dentro del bucle principal haciendo “pygame.mixer.init()”. Una vez realizado esto, simplemente tenemos que cargar los sonidos usando la función que hemos creado anteriormente, es decir:

sonido_golpe = load_sound("tennis.ogg", SONIDO_DIR)
sonido_punto = load_sound("aplausos.ogg", SONIDO_DIR)

Estos sonidos se los tendremos que pasar a la clase “pelota” haciendo “bola = Pelota(sonido_golpe, sonido_punto)”. Dentro de la clase pelota estos sonidos se almacenan en “self.sonido_golpe” y “self.sonido_punto”.

En la clase de la pelota usaremos “Sound.play()” para que se reproduzcan los sonidos. Así en el método “colision()” se le indica que si la pelota colisiona con una paleta reproduzca el archivo «tennis.ogg», que fue guardado en “self.sonido_golpe”, haciendo “self.sonido_golpe.play()” y en el método “update()” al llegar a los bordes izquierdo y derecho de la pantalla se reproduce unos aplausos haciendo “self.sonido_punto.play()”.

Aquí lo dejamos por hoy, os recomendamos que hagáis un repaso de lo aprendido por el momento y que experimentéis.

En el próximo capítulo haremos unas mejoras en nuestro videojuego de modo que mejoremos su rendimiento y además haremos que el jugador ficticio que creamos en el capítulo anterior pueda perder.

Comentaros como siempre, que todos los que se acaban de incorporar al curso tienen un índice con todos los capítulos del curso, ya que nunca es tarde para empezar.