builtins — Objetos incorporados

Pygame Zero proporciona útiles objetos incorporados para ayudarte a crear juegos fácilmente.

Pantalla

El objeto screen representa la pantalla de tu juego.

Es una fina envoltura alrededor de una superficie de Pygame que te permite fácilmente dibujar imágenes en la pantalla («blit»).

class Screen
bounds()

Nuevo en la versión 1.3.

Devuelve un ZRect que representa los límites de la pantalla.

clear()

Restablece la pantalla en negro.

fill((rojo, verde, azul)[, gcolor=(r, g, b)])

Rellena la pantalla con un color sólido.

Nuevo en la versión 1.3: Si se da gcolor entonces rellena con un gradiente, desde color en la parte superior de la pantalla hasta gcolor en la parte inferior.

blit(imagen, (izquierda, arriba))

Dibuja la imagen en la pantalla en la posición dada.

blit() acepta una superficie o una cadena como parámetro image. como parámetro. Si image es una str entonces la imagen nombrada será cargada desde el directorio images/. blit() acepta una superficie o una cadena como parámetro de image. Si image es una cadena (str), la imagen nombrada se cargará desde el directorio images/.

draw.line(start, end, (r, g, b), width=1)

Dibuja una línea desde el inicio hasta el final con un ancho de línea determinado.

draw.circle(pos, radius, (r, g, b), width=1)

Dibuja el contorno de un círculo con un ancho de línea determinado.

draw.filled_circle(pos, radio, (r, g, b))

Dibuja un círculo relleno.

draw.rect(rect, (r, g, b), width=1)

Dibuja el contorno de un rectángulo con un ancho de línea determinado.

Toma un Rect.

draw.filled_rect(rect, (r, g, b))

Dibuja un rectángulo relleno.

draw.text(text, [pos, ]**kwargs)

Dibuja un texto.

Hay una API muy rica para posicionar y formatear el texto; ver Formato de texto para más detalles.

draw.textbox(text, rect, **kwargs)

Dibuja el texto, con el tamaño necesario para llenar el Rect dado.

Hay una API muy rica para formatear el texto; ver Formato de texto para más detalles.

Truco

Todos los colores pueden especificarse como tuplas (r, g, b), o por nombre, utilizando uno de los nombres de colores de Pygame.

Rect

La clase Pygame Rect está disponible como un built in. Se puede utilizar en una variedad de formas, desde detectar clics dentro de una región hasta dibujar una caja en la pantalla:

Por ejemplo, se puede dibujar una caja con:

RED = 200, 0, 0
BOX = Rect((20, 20), (100, 100))

def draw():
    screen.draw.rect(BOX, RED)

Carga de recursos

Los objetos images y sounds pueden utilizarse para cargar imágenes y sonidos de archivos almacenados en los subdirectorios images y sounds respectivamente. Pygame Zero se encargará de cargar estos recursos bajo demanda y los almacenará en caché para evitar la recarga de los mismos.

Por lo general, debes asegurarte de que tus imágenes se nombren con letras minúsculas números y guiones bajos. También tienen que empezar con una letra.

Nombres de archivos como estos funcionarán bien con el cargador de recursos:

alien.png
alien_hurt.png
alien_run_7.png

Estos no funcionarán:

3.png
3grados.png
mi-gato.png
sam's dog.png

El cargador de recursos almacena en caché las imágenes y sonidos cargados. Para borrar la caché (por ejemplo, si tiene problemas de memoria), utilice las funciones unload() y unload_all().

Ejemplo:

cow = Actor('cow')
loader.images.unload('cow') # borra la caché de cow.png
loader.images.unload_all() # borra todos los archivos de imagen en caché

Imágenes

Pygame Zero puede cargar imágenes en formato .png, .gif y .jpg. PNG es recomendado: Permitirá imágenes de alta calidad con transparencia.

Tenemos que asegurarnos de que un directorio de imágenes está configurado. Si su proyecto contiene los siguientes archivos:

space_game.py
images/alien.png

Entonces space_game.py podría dibujar el sprite “alien” en la pantalla con este código:

def draw():
    screen.clear()
    screen.blit('alien', (10, 10))

El nombre que se pasa a blit() es el nombre del archivo de imagen dentro del directorio sin la extensión del archivo.

O utilizando la API Actores,

alien = Actor('alien')

def draw():
    alien.draw()

En ambos casos hay algunas restricciones en los nombres de los archivos: Sólo pueden contener letras latinas minúsculas, números y guiones bajos. Esto es para evitar problemas de compatibilidad cuando su juego se juega en un sistema operativo diferente que tenga diferente sensibilidad a las mayúsculas y minúsculas.

Superficies de imagen

También puedes cargar imágenes desde el directorio images utilizando el objeto images. Esto le permite trabajar con los datos de la imagen en sí, consultar sus dimensiones y demás:

forest = []
for i in range(5):
    forest.append(
        Actor('tree', topleft=(images.tree.get_width() * i, 0))
    )

Cada imagen cargada es una Superficie de Pygame. Normalmente se utiliza screen.blit(...) para dibujarla en la pantalla. También proporciona métodos prácticos para consultar el tamaño de la imagen en píxeles:

class Superficie
get_width()

Devuelve el ancho de la imagen en píxeles.

get_height()

Devuelve la altura de la imagen en píxeles.

get_size()

Devuelve una tupla (anchura, altura) que indica el tamaño en píxeles de la superficie.

get_rect()

Obtiene un Rect que se rellena previamente con los límites de la imagen si esta se encuentra en el origen.

Efectivamente esto es equivalente a:

Rect((0, 0), image.get_size())

Sonidos

Pygame Zero puede cargar sonidos en formatos .wav y .ogg. WAV es ideal para pequeños efectos de sonido, mientras que OGG es un formato comprimido que es más adecuado para música. Puedes encontrar archivos .ogg y .wav gratuitos en línea que puedes utilizar en tu juego.

Tenemos que asegurarnos de que se ha creado un directorio de sonidos. Si su proyecto contiene los siguientes archivos:

drum_kit.py
sonidos/tambor.wav

Entonces drum_kit.py podría reproducir el sonido de la batería cada vez que se pulse el ratón con este código:

def on_mouse_down():
    sounds.drum.play()

Cada sonido cargado es un Sound de Pygame, y tiene varios métodos para reproducir y detener el sonido, así como consultar su duración en segundos:

class Sound
play()

Reproduce el sonido.

play(loops)

Reproduce el sonido, pero con un número de bucles.

Parámetros

loops – El número de veces que se va a hacer el bucle. Si pasas -1 como número de veces, el sonido se reproducirá eternamente (o hasta que llames a Sound.stop())

stop()

Deja de reproducir el sonido.

get_length()

Obtiene la duración del sonido en segundos.

Debes evitar usar el objeto sounds para reproducir piezas musicales más largas. Debido a que el sistema de sonidos cargará completamente la música en la memoria antes de reproducirla, esto puede usar mucha memoria, así como introducir un retraso mientras se carga la música.

Música

Nuevo en la versión 1.1.

Advertencia

La API de música es experimental y puede estar sujeta a problemas de portabilidad.

En particular:

  • El MP3 puede no estar disponible en algunas distribuciones de Linux.

  • Algunos archivos OGG Vorbis parecen colgar Pygame con el 100% de la CPU.

En el caso de este último problema, el problema puede ser arreglado por volver a codificar (posiblemente con un codificador diferente).

Un objeto incorporado llamado music proporciona acceso a la reproducción de música desde un directorio music/ (junto a sus directorios images/ y sounds/, si los tienes). El sistema de música cargará la pista poco a poco mientras se reproduce la música, evitando los problemas de usar sounds para reproducir pistas más largas.

Otra diferencia con el sistema de sonidos es que sólo una pista de música puede estar reproducirse a la vez. Si reproduce una pista diferente, la pista que se estaba reproduciendo anteriormente se detendrá.

music.play(nombre)

Reproduce una pista musical del archivo dado. La pista se reproducirá en bucle indefinidamente.

Esto reemplaza la pista que se está reproduciendo y cancela cualquier pista previamente en cola con queue().

No es necesario incluir la extensión en el nombre de la pista; por ejemplo, para reproducir el archivo handel.mp3 en bucle:

music.play('handel')
music.play_once(nombre)

Similar a play(), pero la música se detendrá después de reproducirse una vez.

music.queue(nombre)

Similar a play_once(), pero en lugar de detener la música actual, la música actual, la pista se pondrá en cola para reproducirse después de que la pista actual termine (o después de cualquier otra pista previamente puesta en cola).

music.stop()

Detiene la música.

music.pause()

Pone en pausa la música temporalmente. Se puede reanudar llamando a unpause().

music.unpause()

Desactiva la música.

music.is_playing()

Devuelve True si la música se está reproduciendo (y no está en pausa), False en caso contrario.

music.fadeout(duration)

Desvanece y eventualmente detiene la reproducción de la música actual.

Parámetros

duration – La duración en segundos durante la cual el sonido se desvanecerá. Por ejemplo, para desvanecerse durante medio segundo, llame a ``music.fadeout(0.5)

music.set_volume(volume)

Establece el volumen del sistema de música.

Toma un número entre 0 (que significa silencio) y 1 (que significa volumen completo).

music.get_volume()

Obtiene el volumen actual del sistema de música.

Si ha iniciado la reproducción de una pista musical utilizando music.play_once(), puede utilizar el hook on_music_end() para hacer algo cuando la música termina - por ejemplo, para elegir otra pista al azar.

Reloj

A menudo, al escribir un juego, querrás programar algún evento del juego para que ocurra en un momento posterior. Por ejemplo, podemos querer que un gran jefe alienígena aparezca después de 60 segundos. O quizás que un power-up aparezca cada 20 segundos.

Más sutiles son las situaciones en las que se quiere retrasar alguna acción durante un periodo más corto. Por ejemplo, puedes tener un arma láser que tarda 1 segundo en cargarse.

Podemos utilizar el objeto clock para programar una función que se produzca en el futuro.

Empecemos definiendo una función fire_laser que queremos que se ejecute en el futuro:

def fire_laser():
    lasers.append(player.pos)

Luego, cuando se pulse el botón de disparo, pediremos clock que lo llame después de exactamente 1 segundo:

def on_mouse_down():
    clock.schedule(fire_laser, 1.0)

Fíjate en que fire_laser es la propia función; sin paréntesis, ¡no se llama aquí! El reloj la llamará por nosotros.

(Es una buena costumbre escribir los tiempos en segundos con un punto decimal, como 1.0. Esto hace que sea más obvio cuando usted está leyendo de nuevo, que te estás refiriendo a un valor de tiempo y no a un recuento de cosas).

clock proporciona los siguientes métodos útiles:

class Reloj
schedule(callback, delay)

Programa la llamada de retorno para que sea llamada después del retardo dado.

Las llamadas repetidas programarán el callback repetidamente.

Parámetros
  • callback – Un callback que no toma argumentos.

  • delay – El retraso, en segundos, antes de que la función deba ser llamada.

schedule_unique(callback, delay)

Programa la llamada de retorno para que sea llamada una vez después del retardo dado.

Si callback ya estaba programado, lo cancela y lo reprograma. Este se aplica también si se ha programado varias veces: Después de llamar a schedule_unique, se programará exactamente una vez.

Parámetros
  • callback – Un callback que no toma argumentos.

  • delay – El retraso, en segundos, antes de que la función sea llamada.

schedule_interval(callback, interval)

Programar la llamada de retorno para que sea llamada repetidamente.

Parámetros
  • callback – Un callback que no toma argumentos.

  • interval – El intervalo en segundos entre las llamadas a callback.

unschedule(callback)

Desprograma la llamada de retorno si ha sido previamente programada (ya sea porque ha sido programada con schedule() y aún no ha sido llamada, o porque se ha programado para que se repita con schedule_interval()).

Ten en cuenta que el reloj Pygame Zero sólo mantiene referencias débiles a cada callback que le des. No disparará los eventos programados si los objetos y métodos no son referenciados en otra parte. Esto puede ayudar a evitar que el reloj mantenga los objetos vivos y continúe disparando inesperadamente después de que estén muertos.

La desventaja de las referencias débiles es que no podrás programar lambdas o cualquier otro objeto que haya sido creado puramente para ser programado. Tendrás que mantener una referencia al objeto.

Actores

Una vez que tienes muchas imágenes moviéndose en un juego puede ser conveniente tener algo que mantenga en un solo lugar la imagen y dónde está en la pantalla. Llamaremos a cada imagen en movimiento en la pantalla un Actor. Puedes crear un actor proporcionando al menos un nombre de imagen (de la carpeta de imágenes de arriba). Para dibujar el alienígena del que hablamos arriba

alien = Actor(“alien”, (50, 50))

def draw():

screen.clear() alien.draw()

Puedes mover el actor estableciendo su atributo pos en un update:

def update():
    if keyboard.left:
        alien.x -= 1
    elif keyboard.right:
        alien.x += 1

Y puede cambiar la imagen utilizada para dibujar el actor estableciendo su atributo de imagen a algún nuevo nombre de imagen:

alien.image = 'alien_hurt'

Los actores tienen todos los mismos atributos y métodos que Rect, incluyendo métodos como .colliderect() que pueden ser utilizados para comprobar si dos actores han colisionado.

Posicionamiento de actores

Si asigna un nuevo valor a uno de los atributos de posición, el actor será movido. Por ejemplo:

alien.right = WIDTH

Posicionará al alienígena de manera que su lado derecho se establezca en WIDTH.

Del mismo modo, también puedes establecer la posición inicial del actor en el constructor pasando uno de estos argumentos como palabra clave: pos, topleft, topright, bottomleft, bottomright, midtop, midleft, midright, midbottom o center:

_images/anchor_points.png

Esto puede hacerse durante la creación o asignando un par de coordenadas x, y. Por ejemplo:

WIDTH = 200
HEIGHT = 200

alien = Actor('alien', center=(100,100))

def draw():
    screen.clear()
    alien.draw()
_images/alien_center.png

Cambiando center=(100, 100) por midbottom=(100, 200) te da:

_images/alien_midbottom.png

Si no se especifica una posición inicial, el actor será inicialmente posicionado en la esquina superior izquierda (equivalente a topleft=(0, 0)).

Punto de anclaje

Los actores tienen una «posición de ancla», que es una forma conveniente de posicionar al actor en la escena. Por defecto, la posición de anclaje es el centro, por lo que el atributo se refiere al centro del actor (al igual que las coordenadas x e y). Es común querer establecer el punto de anclaje en otra parte del sprite (tal vez los pies - para que pueda establecer fácilmente que el Actor esté «parado sobre» algo):

alien = Actor('alien', anchor=('center', 'bottom'))
spaceship = Actor('spaceship', anchor=(10, 50))

El ancla se especifica como una tupla (xanchor, yanchor), donde los valores pueden ser flotantes o las cadenas izquierda, centro/medio`, derecha, superior o bottom según el caso.

Rotación

Nuevo en la versión 1.2.

El atributo .angle de un Actor controla la rotación del sprite, en grados, en sentido contrario a las agujas del reloj.

El centro de rotación es el punto de anclaje del Actor.

Tenga en cuenta que esto cambiará la anchura width y la altura height del Actor.

Por ejemplo, para hacer que un sprite de asteroide gire lentamente en sentido contrario a las agujas del reloj en el espacio:

asteroid = Actor('asteroid', center=(300, 300))

def update():
    asteroid.angle += 1

Para que gire en el sentido de las agujas del reloj, cambiaríamos update() por:

def update():
    asteroid.angle -= 1

Como ejemplo diferente, podríamos hacer que un actor nave estuviera siempre de cara al puntero del ratón. Como angle_to() devuelve 0 para «derecha», el sprite que usamos para el «barco» debería estar orientado hacia la derecha:

ship = Actor('ship')

def on_mouse_move(pos):
    ship.angle = ship.angle_to(pos)
Diagrama que muestra cómo configurar los sprites para la rotación con angle_to()

Recuerda que los ángulos hacen un bucle redondo, así que 0 grados == 360 grados == 720 grados. Del mismo modo, -180 grados == 180 grados.

Distancia y ángulo a

Nuevo en la versión 1.2.

Los actores tienen métodos convenientes para calcular su distancia o ángulo a otros Actores o pares de coordenadas (x, y).

Actor.distance_to(objetivo)

Devuelve la distancia de la posición de este actor al objetivo, en píxeles.

Actor.angle_to(objetivo)

Devuelve el ángulo desde la posición de este actor hasta el objetivo, en grados.

Esto devolverá un número entre -180 y 180 grados. El derecho es 0 grados y los ángulos aumentan en sentido contrario a las agujas del reloj.

Por lo tanto:

  • Izquierda es 180 grados.

  • Arriba es 90 grados.

  • Abajo es -90 grados.

Transparencia

Nuevo en la versión 1.3.

En algunos casos es útil hacer que un objeto Actor sea parcialmente transparente. Este puede usarse para desvanecerlo, o para indicar que está «deshabilitado» (disabled).

El atributo .opacity de un Actor controla lo transparente u opaco que es.

  • Cuando un actor no es en absoluto transparente, decimos que es «opaco» y tiene

  • Cuando un actor no es transparente en absoluto, decimos que es «opaco» y tiene un opacity de 1.0, y no se puede ver a través de él.

  • Cuando un actor es completamente transparente, tiene una opacity de 0.0. Esto lo hará completamente invisible.

Para hacer un actor que sea medio transparente (como un fantasma), puedes escribir:

ghost = Actor('ghost')
ghost.opacity = 0.5

Este diagrama muestra la escala; el damero gris se utiliza para dar la sensación de transparencia:

La escala de opacidad en Pygame Zero.

Truco

El orden en el que se dibujan los objetos transparentes superpuestos sigue siendo importante. Un fantasma visto a través de una ventana se ve ligeramente diferente a una ventana vista a través de un fantasma.

El teclado

Probablemente hayas notado que hemos utilizado el teclado en el código anterior. Si quieres saber qué teclas se pulsan en el teclado, puedes consultar los atributos del teclado. Si, por ejemplo, la flecha izquierda se mantiene pulsada, entonces keyboard.left será True, de lo contrario será False.

Hay atributos para cada tecla; algunos ejemplos:

keyboard.a # La tecla 'A'
keyboard.left # La tecla de la flecha izquierda
keyboard.rshift # La tecla de desplazamiento a la derecha
keyboard.kp0 # La tecla '0' del teclado
keyboard.k_0 # La tecla '0' principal

El conjunto completo de constantes de teclas se encuentra en la documentación `Buttons and Keys`_ pero los atributos están en minúsculas, porque son variables no constantes.

Nuevo en la versión 1.1: Ahora también puedes consultar el estado de las teclas utilizando las constantes del teclado ellos mismos:

keyboard[keys.A] # Verdadero si la tecla 'A' está pulsada
keyboard[keys.SPACE] # Verdadero si la barra espaciadora está pulsada

Animaciones

Puedes animar la mayoría de las cosas en pygame usando la función incorporada animate(). Por ejemplo, para mover un Actor <actor> desde su posición actual en la pantalla hasta la posición ``(100, 100)`:

animate(alien, pos=(100, 100))
animate(object, tween='linear', duration=1, on_finished=None, **targets)

Animar los atributos del objeto desde su valor actual hasta el especificado en los valores de los objetivos.

Parámetros
  • tween – El tipo de entrelazado a utilizar.

  • duration – La duración de la animación, en segundos.

  • on_finished – Función llamada cuando la animación termina.

  • targets – Los valores objetivo de los atributos a animar.

El argumento tween puede ser uno de los siguientes:

“linear”

Animar a una velocidad constante de principio a fin

_images/linear.png

“accelerate”

Empezar más despacio y acelerar hasta el final

_images/accelerate.png

“decelerate”

Empezar rápido y desacelerar para terminar

_images/decelerate.png

“accel_decel”

Acelerar hasta el punto medio y desacelerar hasta el final

_images/accel_decel.png

“in_elastic”

Dar un pequeño bamboleo al final

_images/in_elastic.png

“out_elastic”

Dar un pequeño bamboleo al principio

_images/out_elastic.png

“in_out_elastic”

Tener un bamboleo en ambos extremos

_images/in_out_elastic.png

“bounce_end”

Acelerar hasta la meta y rebotar allí

_images/bounce_end.png

“bounce_start”

Rebote en la salida

_images/bounce_start.png

“bounce_start_end”

Rebote en los dos extremos

_images/bounce_start_end.png

La función animate() devuelve una instancia de Animation:

class Animation
stop(complete=False)

Detiene la animación, completando opcionalmente la transición a los valores finales de las propiedades.

Parámetros

complete – Establece el atributo animado al valor final.

running

Será True si la animación se está ejecutando. Será False cuando la duración se haya ejecutado o se haya llamado antes al método stop().

on_finished

Puede establecer este atributo a una función que será llamada cuando la duración de la animación se agote. El argumento on_finished de animate() también establece este atributo. No se llama cuando se llama a stop(). Esta función no toma argumentos.

Generador de tonos

Nuevo en la versión 1.2.

Pygame Zero puede reproducir tonos utilizando un sintetizador incorporado.

tone.play(pitch, duration)

Toca una nota en el tono dado durante la duración dada.

La duración está en segundos.

El «pitch» puede ser especificado como un número, en cuyo caso es la frecuencia de la nota en hercios.

También se puede especificar el tono como una cadena que represente un nombre de nota y una octava. Por ejemplo:

  • 'E4' sería E en la octava 4.

  • 'A#5' sería La sostenido en la octava 5.

  • 'Bb3' sería Si bemol en la octava 3.

La creación de notas, especialmente las largas, lleva tiempo, hasta varios milisegundos. Puedes crear tus notas con antelación para que esto no ralentice su juego mientras se está ejecutando:

tone.create(pitch, duration)

Crea y devuelve un objeto Sonido.

Los argumentos son los mismos que para play(), arriba.

Esto podría usarse en un programa Pygame Zero como este:

beep = tone.create('A3', 0.5)

def on_mouse_down():
    beep.play()

Almacenamiento de datos

El objeto storage se comporta como un diccionario de Python pero su contenido se conserva a través de las sesiones de juego. Los valores que asignes al almacenamiento serán guardados como JSON, lo que significa que sólo puedes almacenar ciertos tipos de objetos en él: list/tuple`, dict, str, float/int`, bool, y None.

El storage de un juego está inicialmente vacío. Tu código tendrá que manejar el caso de que se carguen valores así como el caso de que no se encuentren valores.

Un consejo es utilizar setdefault(), que inserta un valor por defecto si no hay valor para la clave, pero no hace nada si lo hay.

Por ejemplo, podríamos escribir:

storage.setdefault('highscore', 0)

Después de ejecutar esta línea, storage['highscore'] contendrá un valor - 0 si no hay ningún valor cargado, o el valor cargado en caso contrario. Podrías añadir todas tus líneas setdefault hacia la parte superior de tu juego, antes de que cualquier otra cosa mire a storage:

storage.setdefault('level', 1)
storage.setdefault('nombre_del_jugador', 'Anonimo')
storage.setdefault('inventario', [])

Ahora, durante el juego podemos actualizar algunos valores:

si player.colliderect(mushroom):
    puntuación += 5
    si puntuación > storage['highscore']:
        storage['highscore'] = puntuación

Puedes volver a leerlos en cualquier momento:

def draw():
    ...
    screen.draw.text('Puntuación alta: ' + storage['highscore'], ...)

…y por supuesto, se conservarán cuando el juego se vuelva a lanzar.

Estos son algunos de los métodos más útiles de storage:

class storage(dict)
almacenamiento[clave] = valor

Establece un valor en el almacenamiento.

storage[key]

Obtener un valor del almacén. Lanza KeyError si no hay tal clave en el storage.

setdefault(key, default)

Inserta un valor por defecto en el storage, sólo si no existe un valor existe para esta clave.

get(key, default=None)

Obtiene un valor del storage. Si no existe dicha clave, devuelve default, o None si no se ha dado ningún valor por defecto.

clear()

Elimina todos los valores almacenados. Utiliza esto si se produce un mal estado.

save()

Guarda los datos en el disco ahora. Normalmente no necesitas llamar a esto, a menos que estés planeando usar load() para recargar un punto de control, por ejemplo.

load()

Recarga el contenido del almacén con los datos del archivo guardado. Este reemplazará cualquier dato existente en el almacenamiento.

Advertencia

A medida que vayas haciendo cambios en tu juego, storage podría contener valores que no funcionan con tu código actual. Puedes comprobarlo o llamar a .clear() para eliminar todos los valores antiguos, o borrar el archivo de la partida guardada.

Truco

Acuérdate de comprobar que tu juego sigue funcionando si el almacén está vacío.