Curso Python. Volumen XXI: Pygame, videojuegos en python. Parte IV
Bienvenidos un día más al curso de Python. En este capítulo empezaremos la creación de nuestro primer videojuego completo con la librería Pygame. En el capítulo anterior ya fuimos capaces de mover nuestro “sprite” alrededor de la ventana. Hoy empezaremos creando el esqueleto de nuestro videojuego. Así que pongámonos manos a la obra.
Parte básica del videojuego
Lo primero es crear la ventana y una función para cargar las imágenes.
#!/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"
# ------------------------------
# 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
# ------------------------------
# Funcion principal del juego
# ------------------------------
def main():
pygame.init()
# creamos la ventana y le indicamos un titulo:
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Pong")
# cargamos el fondo
fondo = load_image("fondo.jpg", IMG_DIR, alpha=False)
# el bucle principal del juego
while True:
# actualizamos la pantalla
screen.blit(fondo, (0, 0))
pygame.display.flip()
# Posibles entradas del teclado y mouse
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if __name__ == "__main__":
main()
Hemos creado una función para cargar imágenes debido a que nos facilita la tarea, ya que es una funcionalidad muy utilizada. De este modo, podremos cargar distintos tipos de imágenes a la vez que realizamos los “convert()” según corresponda. Esta función actúa del siguiente modo:
Tiene como entrada tres parámetros: el nombre, el directorio donde se encuentra la imagen y si tiene o no un canal “alpha” (el color transparente de los .png). Luego con esa información (directorio + nombre imagen) crea la ruta de la imagen e intenta abrirla con un “try… except” por si hubiera algún error al abrir la imagen. Después de eso revisa si la imagen tiene un canal “alpha”, en ese caso realiza el “.convert_alpha()”, en caso contrario realiza un “.convert()”. Finalmente devuelve la superficie que se crea al cargar la imagen.
Luego en la función principal del juego se carga la imagen del fondo y se muestra en pantalla. Utilizamos una variable llamada “IMG_DIR” para indicar el nombre del directorio donde se encuentran las imágenes.
Creando “sprites”
En los capítulos anteriores hemos usado “sprites” pero no hemos definido qué son. Pues bien, un “sprite” es básicamente cualquier cosa que aparezca en nuestro juego (personajes, objetos, etc.) la cual tiene asociada información (como su posición, tamaño, etc.). En “Pygame” es costumbre hacer una clase para cada “sprite”, de tal manera que la clase contenga la información relevante de ese “sprite”.
Para nuestro juego vamos a crear la clase Pelota, que va a contener todos los datos de la pelota usada en el juego. Esta primera versión de la pelota, solo rebotará indistintamente en las cuatro murallas de nuestra pantalla. Veamos el 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"
# ------------------------------
# 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
# -----------------------------------------------
# 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):
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]
# ------------------------------
# Funcion principal del juego
# ------------------------------
def main():
pygame.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)
bola = Pelota()
# el bucle principal del juego
while True:
# actualizamos la pantalla
screen.blit(fondo, (0, 0))
screen.blit(bola.image, bola.rect)
pygame.display.flip()
# Posibles entradas del teclado y mouse
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if __name__ == "__main__":
main()
Ahora dentro de la clase “Pelota()” vemos que hereda los métodos de la clase padre “pygame.sprite.Sprite”, luego en el “def __init__(self)”, que es el constructor de la clase (Podéis recordar programación orientada a objetos aquí) definiremos que va hacer la clase cuando se crea una instancia de ésta. En nuestro caso se le dice primero que inicie “pygame.sprite.Sprite” (es obligatorio), luego cargamos la imagen en “self.image”.
Con “self.image.get_rect()” se obtiene un objeto rectángulo (rect) con las dimensiones y posición de la imagen y este rectángulo se lo asignamos a “self.rect”. Esto resulta bastante útil, ya que nos permite dejar de preocuparnos por las dimensiones de la imagen por si luego decidimos cambiarlas, además de obtener algunos extras que señalaremos a continuación:
Ahora el rectángulo creado con “get_rect()” nos permite usar varios atributos virtuales que se pueden usar para mover o alinear el rectángulo (y que usaremos a continuación). Entre ellos:
- top, left, bottom, right
- topleft, bottomleft, topright, bottomright
- midtop, midleft, midbottom, midright
- center, centerx, centery
- size, width, height
- w,h
Ahora con “self.rect.centerx” y “self.rect.centery” le indicamos a “Pygame” que el centro de nuestra imagen “(centerx, centery)” quede exactamente en la mitad de la pantalla, es decir le indicamos que nos centra la imagen en la ventana.
Por ultimo en “self.speed” estableceremos la velocidad con que se mueva la pelota en el eje x y en el eje y.
Aquí lo dejamos por hoy, os recomendamos que reviséis los capítulos de programación orientada a objetos, ya que como habréis podido comprobar vamos a estar utilizando este paradigma de programación.
En el próximo capítulo nos centraremos en el movimiento de la pelota por la pantalla. Comentaros que para todos los que se acaban de incorporar indicarles que tenemos un índice con todos los capítulos del curso, ya que nunca es tarde para empezar.
Via: www.redeszone.net