Contenidos

De WikiEducator
Saltar a: navegación, buscar





Pygame

Pygame es una librería multiplataforma diseñada para facilitar la creación de software multimedia, sobre todo juegos. Funciona como interfaz a las bibliotecas SDL Pygame se encarga de gestionar:

  • imágenes en distintos formatos (PNG, BMP, PCX, TGA, ...)
  • sistemas de sonido (MOD, OGG, MP3, ...)
  • operaciones relacionadas con el gestor de ventana.
  • eventos de aplicación y dispositivos de entrada (mouse, teclado, joystick)
  • temporizadores.
  • colisiones entre objetos

Instalación

Si todo ha ido bien puedes probar los juegos de ejemplos:

 python -m pygame.examples.aliens

Inicializar Pygame

  1. import pygame
  2. from pygame.locals import *
  3.  
  4. pygame.init()

Crear la ventana de juego

  1. import pygame
  2. from pygame.locals import *
  3.  
  4. ANCHO, ALTO = 640, 480
  5.  
  6. pygame.display.set_mode((ANCHO, ALTO))
  7. pygame.display.set_caption("Mi primer juego con pygame")


Bucle principal del juego

Como en toda aplicación multimedia, en un juego pygame el bucle principal tiene que:

  • comprobar los controles
  • evaluar los eventos
  • actualizar objetos en el juego
  • refrescar la pantalla
  1. while True:
  2.     # comprobar controles
  3.     # evaluar eventos
  4.     for eventos in pygame.event.get():
  5.         if eventos.type == QUIT:
  6.             sys.exit(0)
  7.     # actualizar los objetos (sprites)
  8.     # dibujar / refrescar la pantalla
set_mode
http://www.losersjuegos.com.ar/traducciones/pygame/display#set_mode

Color de fondo en mi ventana

Cuando creamos la ventana principal, set_mode devuelve un objeto (surface) que podemos usar para colorear el fondo:

  1. BG_COLOR = 150, 150, 80
  2.  
  3. pantalla = pygame.display.set_mode((ANCHO, ALTO))
  4. pygame.display.set_caption("Mi primer juego con pygame")
  5.  
  6. while True:
  7.     for eventos in pygame.event.get():
  8.         if eventos.type == QUIT:
  9.             sys.exit(0)
  10.     pantalla.fill(BG_COLOR)
  11.  
  12.     pygame.display.flip()  # Ver referencia de flip más adelante
flip
http://www.losersjuegos.com.ar/traducciones/pygame/display#flip

flip actualiza la pantalla. Pygame maneja la pantalla con Double Buffer. Primero dibuja la pantalla en segundo plano y después la hace visible.

Imágenes

Cargar imágenes

Podemos cargar un fondo así:

fondo = pygame.image.load('imagenes/escenario.jpg')

Transparencias

En Pygame se usan dos tipos de transparencias, la transparencia alpha y la de colorkey:

Transparencia alfa (alpha) 
Se aplica a toda la imagen, es un valor que va desde 0 a 255 donde 0 es opaco y 255 es transparente, se puede hacer una imagen borrosa dandole valores intermedios
Tranparencia colorkey 
Se aplica solo a un color de la imagen y hace ese color invisible

Una función interesante para cargar imágenes con transparencia alfa:

  1. def cargar_imagen(nombre, optimizar=False):
  2.     ruta = os.path.join('imagenes', nombre)
  3.     imagen = pygame.image.load(ruta)
  4.  
  5.     if optimizar:
  6.         return imagen.convert()
  7.     else:
  8.         return imagen.convert_alpha()

Sistemas de coordenadas

Pygame no usa el sistema de coordenadas cartesianas, con el (0,0) en el centro de la pantalla.

Pygame-coordinates.png

En pygame la esquina superior izquierda tiene la coordenada 0,0. La esquina inferior derecha tiene max_ancho-1, max_alto-1 .

Colocar la imagen en la pantalla

 screen.blit(imagen, (posx, posy))

Si hay una imagen de fondo, se suele colocar:

 screen.blit(fondo, (0, 0))

Sprites

Los distintos elementos de un juego tienen mucha información: imagen, posición, tipo y dirección de movimento, vidas, etc. Crearemos una clase, que hereda de Sprite para representar estos objetos. Un sprite en pygame tiene:

  • self.image
  • self.rect
  • update(self)

Manejar los rectángulos

Atributos para manipular un rectángulo:

top, left, bottom, right
topleft, bottomleft, topright, bottomright
midtop, midleft, midbottom, midright
center, centerx, centery
size, width, height
w,h

A una superficie le podemos pedir su rectángulo:

 imagen.get_rect()

Un sprite de ejemplo

  1. class Banana(Sprite):                             # Heredan de la clase Sprite
  2.     def __init__(self, scr=None):                 # Le pasamos la pantalla donde se dibujará
  3.         Sprite.__init__(self)
  4.         self.image = cargar_imagen('banana.png')  # Usamos la función citada antes
  5.         self.rect = self.image.get_rect()         # Guardamos el rectángulo para manipular la imagen
  6.         self.scr = scr                            # Usaremos esta superficie para dibujar el sprite
  7.         self.velocidad = 1                        # Velocidad a la que se moverá nuestro objeto
  8.     def update(self):
  9.         self.rect.top += self.velocidad           # Movimiento descendente: aumenta el valor de y
  10.     def draw(self):
  11.         if self.scr: self.scr.blit(self.image, self.rect)  # Para dibujar en la pantalla

Movimiento

El bucle principal del juego se ejecuta muchas veces por segundo. Si cambiamos la posición en que se dibuja un objeto (su rectángulo), generamos una sensación de movimento.

El movimiento puede ser automático, generado por un evento (teclado, joystick, webcam, wiimote, ...) o por interacción con otros objetos.

Velocidad del movimiento

Es importante controlar la velocidad a la que se refresca la pantalla:

  1. # creación de reloj
  2. clock = pygame.time.Clock()
  3.  
  4. # dentro del bucle del juego
  5. while True:
  6.     # ...
  7.     tiempo = clock.tick(60)

El juego intentará hacer 60 fps (frames por segundo)

http://www.losersjuegos.com.ar/traducciones/pygame/time/clock

Control de los límites de la pantalla

Normalmente no dejaremos que los sprites se muevan fuera de la pantalla: desaparecen, rebotan, hacemos un scroll ... En cada ciclo del juego tendremos que comprobar que los objetos no se salgan de la pantalla. Recuerda que el límite superior e izquierdo es el 0, el límite derecho es la anchura definida al crear la pantalla y el límite inferior, la altura de la pantalla.


Teclado

¿Qué teclas se han pulsado?

  1. keys = pygame.key.get_pressed()
  2. # comprueba si se ha pulsado la tecla de flecha arriba
  3. if keys[K_UP]:
  4.     self.rect.centery -= self.velocidad

Podemos detectar un evento de pulsar una tecla:

  1. if event.type == pygame.KEYDOWN:
  2.     print event.key

Aquí tienes todo el catálogo de las teclas (keycodes): http://www.pygame.org/docs/ref/key.html

Movimiento con el ratón

  1. if event.type == pygame.MOUSEBUTTONDOWN: # o  MOUSEBUTTONUP o MOUSEMOTION
  2.     (mouseX, mouseY) = pygame.mouse.get_pos()
  3.     # ...

http://www.pygame.org/docs/ref/mouse.html

FPS: Frames por segundo

Un frame es un paso completo el bloque actualizar/mostrar/espera La velocidad de ejecución debería ser la misma en todas las plataformas, pero a veces va demasiado despacio y otras demasiado deprisa. Regla de oro: como mínimo debe de haber 30 actualizaciones por segundo. Pygame cuenta el tiempo en milisegundos.

  1. clock = pygame.time.Clock()
  2. clock.tick(30) # 30 veces por segundo

Clock devuelve el tiempo pasado desde el frame anterior.

  1. milliseconds = clock.tick(FPS) 
  2. playtime += milliseconds / 1000.0


Colisiones

Para comprobar si dos objetos se tocan (sus rectángulos):

 pygame.sprite.collide_rect(objeto1, objeto2)
 pygame.sprite.collide_circle(objeto1, objeto2)

Devuelven verdadero o falso.

Si se utilizan grupos de sprites (balas, naves, enemigos, ...):

 pygame.sprite.spritecollideany(objeto, grupo)
 pygame.sprite.groupcollide(grupo1, grupo2)

http://www.losersjuegos.com.ar/traducciones/pygame/sprite

Rebotes

Cuando un objeto rebota, el ángulo de reflexión es el mismo que el ángulo de incidencia:


Sonidos

Sonidos del juego

  1. sonido = pygame.mixer.Sound(<ruta>) # soporta .wav, .mp3, .ogg
  2. # ...
  3. sonido.play()

Música de fondo

 pygame.mixer.music.load(ruta)
 pygame.mixer.music.play(1)  # el 1 indica repetición

Textos

Podemos usar la fuente por defecto del sistema (None), una que tengamos instalada o un archivo con una fuente. Los pasos son:

  • Creación del objeto fuente: Prepara la definición de la fuente para el tamaño que queremos usar
  • Render del texto, que crea una superficie
  • Colocación de la superficie en la pantalla del juego

El primer paso es más costoso y lo haremos fuera del bucle principal del juego.

  1. font = pygame.font.Font(None, 28) # fuente por defecto 
  2. # ...
  3. texto = font.render("Puntos: 1000", 1, (0, 0, 0)) # Texto, antialiasing, color en RGB
  4. # ...
  5. screen.blit(texto, (10, 10))

Más utilidades para fuentes

pygame.font.get_fonts -> Devuelve todas las fuentes disponibles 
pygame.font.SysFont -> Crea un objeto fuente a partir de las fuentes del sistema.

http://www.losersjuegos.com.ar/traducciones/pygame/font

Animaciones

Las animaciones se simulan. Se va cambiando la imagen. Hay que dejar unos ciclos (milisegundos) cada imagen para que se vea en pantalla.

Posición y velocidad

¿Dónde está un objeto en el instante x?
La velocidad es la proporción entre la distancia recorrida y el tiempo. En el desplazamiento tenemos que tener en cuenta también la dirección del objeto.
Dadas las variables: posición posición original (x, y), velocidad y ángulo:
  1. desplazamiento_x = (velocidad * cos(angulo))
  2. desplazamiento_y = (velocidad * sin(angulo))
  3. posicion_x += desplazamiento_x
  4. posicion_y += desplazamiento_y

Aceleración

Cuando movemos un objeto a una velocidad, se le puede añadir una aceleración continua a la velocidad

  1. velocidad += aceleracion
  2. desplazamiento_x = (velocidad * cos(angulo))
  3. desplazamiento_y = (velocidad * sin(angulo))
  4. posicion_x += desplazamiento_x
  5. posicion_y += desplazamiento_y

Gravedad

Es una aceleración hacia abajo. La gravedad de la tierra es de 9.81 metros por segundo. En un juego, la gravedad constante depende del frame rate. Lo utilizamos cuando un personaje salta, en los proyectiles, etc.