SlideShare una empresa de Scribd logo
1 de 28
Descargar para leer sin conexión
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
Programación de Juegos 
con PyGame 
Capitulo 6: Sonidos, Sprites 
y Animaciones 
1
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
pygame.mixer 
Bueno ya teniamos casi todos los Modulos y herramientas para programar juegos, la 
unica cosa que nos hacia falta era poder reproducir sonidos y bueno aqui es donde toma 
importancia este modulo, ya que su utilidad es exactamente esa, brindarnos clases y 
funciones para poder reproducir audio. 
Este módulo contiene clases para crear objetos Sound y controlar la reproducción de 
audio. El módulo mixer es opcional y depende de SDL_MIXER Antes de usar este módulo su 
programa debería verificar si el módulo pygame.mixer está disponible. 
El módulo mixer tiene un número limitado de canales para reproducir sonidos. 
Generalmente los programas le piden a pygame que comience a reproducir un sonido y 
pygame selecciona un canal de audio disponible de forma automática. Por defecto hay 8 
canales simultáneos, aunque los programas complejos pueden obtener un control mas 
preciso de la cantidad de canales y utilizarlos. 
Toda la reproducción de sonido se realiza en segundo plano (en hilos diferentes). 
Cuando comienza a reproducir un objeto Sound, esta llamada retornará inmediatamente 
mientras el sonido continúa sonando. Un objeto Sound también se puede reproducir varias 
veces. 
También tiene un canal de streaming que se utiliza para reproducir música y se 
accede a él a través del módulo pygame.mixer.music. 
El módulo mixer se debe inicializar como los otros módulos de pygame, aunque tiene 
algunas condiciones adicionales. La función pygame.mixer.init() toma varios argumentos 
opcionales para controlar la frecuencia de reproducción. pygame colocará por defecto valores 
razonables, aunque no realizará conversión de frecuencias, por lo tanto mixer debería 
iniciarse para coincidir con la frecuencia y calidad de los recursos de audio. 
init 
Inicializar el módulo mixer para cargar y reproducir sonido. Los valores por defecto de 
los argumentos se pueden reemplazar utilizando atributos de audio específicos. El argumento 
size representa cuantos bits se usarán para cada muestra de audio. Se usarán valores de 
muestra con signo si se especifica un valor negativo, en otro caso se usarán muestras de 
audio sin signo. 
El argumento channels se usa para especificar cuando usar el modo estéreo y cuando 
el modo mono. 1 indica mono y 2 estéreo. No se permiten otros valores. 
El argumento buffer controla el número de muestras internas que se usarán en el 
mezclador de sonido. El valor por defecto debería funcionar en la mayoría de los casos. Este 
valor se puede reducir para disminuir la latencia, aunque podría ocurrir una pérdida de 
calidad en el sonido. También se puede aumentar para asegurarse que la reproducción nunca 
se detenga, aunque esto impone latencia. El valor de buffer debe ser potencia de dos. 
Algunos equipos necesitan que el módulo pygame.mixer se inicialice después de los 
módulos de video. El módulo de orden superior tiene precaución de esto automáticamente, 
pero no envía ningún argumento especial la iniciar mixer. Para resolver esto, el módulo mixer 
tiene una función llamada pygame.mixer.pre_init() para definir los valores por defecto antes 
2
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
de llamar a pygame.init 
sintaxis 
pygame.mixer.init(frequency=22050, size=-16, channels=2, buffer=3072): 
return None 
pre_init 
Define con anterioridad los argumentos de mixer.init. 
sintaxis: 
pygame.mixer.pre_init(frequency=0, size=0, channels=0, buffersize=0): 
return None 
quit 
Deshabilita el módulo pygame.mixer. Se detendrá toda la reproducción de audio y los 
objetos Sound cargados podrían ser incompatibles con el mezclador si éste se modifica 
luego. 
sintaxis: 
pygame.mixer.quit(): return None 
get_init 
Consulta si se ha inicializado el módulo mixer. adicionalmete retornara los argumentos con 
los que fue o sera inicializado, el modulo. 
sintaxis: 
pygame.mixer.get_init(): return (frequency, format, channels) 
stop 
Detiene la reproducción de todos los canales de sonido. 
sintaxis: 
pygame.mixer.stop(): return None 
pause 
Detendrá de forma temporal todas las reproducciones en los canales del mezclador 
activos. La reproducción de sonido se puede reanudar mas tarde llamando a la función 
pygame.mixer.unpause(). 
sintaxis: 
pygame.mixer.pause(): return None 
3
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
unpause 
Reanuda la reproducción de audio que se encuentre en pausa. 
sintaxis: 
pygame.mixer.unpause(): return None 
fadeout 
Deducirá el volumen de todos los canales de sonidos en el tiempo indicado por por el 
argumento milliseconds. El sonido se detendrá una vez que el volumen llegue a su menor 
valor. 
sintaxis: 
pygame.mixer.fadeout(time): return None 
set_num_channels 
Define el número de canales disponibles para el mezclador. El valor por defecto es 8 y 
depende de la cantidad de canales que soporte su placa de sonido. Puede aumentar o 
disminuir este valor. Se reduce este valor todos los sonidos que estén sonando en los canales 
a eliminar se detendrán. 
sintaxis: 
pygame.mixer.set_num_channels(count): return None 
get_num_channels 
Obtiene el número total de canales de reproducion activos. 
sintaxis: 
pygame.mixer.get_num_channels(): return count 
set_reserved 
El módulo mixer puede preservar cualquier número de canales para que no se 
seleccionen automáticamente al reproducir Sonidos. No se detendrán los sonidos que 
actualmente estén sonando en los canales reservados. 
Esto permite a la aplicación reservar un número específico de canales para sonidos 
importantes que no deberían interrumpirse y tener garantizado un canal para reproducirse. 
sintaxis: 
pygame.mixer.set_reserved(count): return None 
4
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
find_channel 
Encuentra y retorna un objeto Channel inactivo. Si no hay canales inactivos retornará 
None. Si no hay canales inactivos y el argumento foce vale True entonces encontrará el canal 
que tiene el sonido que mas tiempo se a reproducido y lo retornará. 
Si el módulo tiene canales reservados de la función pygame.mixer.set_reserved() 
entonces esos canales no se retornarán aquí. 
sintaxis: 
pygame.mixer.find_channel(force=False): return Channel 
get_busy 
Retorna True si el módulo está reproduciendo en alguno de los canales. Retornará 
False si el mezclador está libre. 
sintaxis: 
pygame.mixer.get_busy(): return bool 
Music 
El módulo music está muy relacionado con el módulo pygame.mixer. Use el módulo 
music para controlar la reproducción de música en el módulo mixer. 
La diferencia entre la reproducción de música y la reproducción de un sonido es que la 
música se reproduce mientras se carga, y nunca se carga completamente de una vez. El 
módulo mixer soporta solamente la reproducción de una música a la vez. 
load 
Cargará el archivo de música y lo preparará para reproducir. Se detendrá cualquier 
música si se estaba reproduciendo. Esta función no comenzará a reproducir la música. 
Tenga en cuenta que la música solo se puede cargar a partir del nombre de un 
archivo, no se puede cargar desde objetos file como las otras funciones para cargar recursos 
de pygame. 
sintaxis: 
pygame.mixer.music.load(filename): return None 
play 
Reproducirá la música que se ha cargado. Si la música ya estaba sonando entonces se 
reiniciará. El argumento loops controla el número de veces que se debe reproducir la 
canción. Por ejemplo, play(5) causará que la canción suene una vez y luego se repita 5 
5
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
veces; es decir, unas 6 veces. Si el argumento loop vale -1 se repetirá la reproducción 
indefinidamente. 
El argumento de posición start controla a partir de donde comenzará a reproducirse. 
La posición de inicio depende del formato de música utilizado. Los formatos MP3 y OGG 
utilizan la posición como tiempo medido en segundos. La música en formato MOD usará start 
como el número de patrón. Si no se puede definir la posición de inicio se lanzará la excepción 
NotImplementedError. 
sintaxis: 
pygame.mixer.music.play(loops=0, start=0.0): return None 
rewind 
Reinicia la reproducción de la música actual para iniciar desde el principio. 
sintaxis: 
pygame.mixer.music.rewind(): return None 
stop 
Detiene la reproducción de música si se está reproduciendo. 
sintaxis: 
pygame.mixer.music.stop(): return None 
pause 
Detiene de forma temporal la reproducción de música. Con la función 
pygame.mixer.music.unpause() puede continuar la reproducción. 
sintaxis: 
pygame.mixer.music.pause(): return None 
unpause 
Continúa la reproducción de una canción luego de que esta se ha pausado. 
sintaxis: 
pygame.mixer.music.unpause(): return None 
fadeout 
Detendrá la reproducción de música luego de haber reducido el volumen en el tiempo 
especificado (en milisegundos). 
6
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
sintaxis: 
pygame.mixer.music.fadeout(time): return None 
Nota: esta función puede bloquear el programa mientras altera el volumen. 
set_volume 
Define el volumen de la reproducción de música. El argumento value es un número 
entre 0.0 y 1.0. Se redefine el nivel de volumen cuando se carga una nueva música. 
sintaxis: 
pygame.mixer.music.set_volume(value): return None 
get_volume 
Obtiene el volumen de la música. Retorna el volumen actual para el mezclador. El 
valor debe estar entre 0.0 y 1.0. 
sintaxis: 
pygame.mixer.music.get_volume(): return value 
get_busy 
Consulta si se está reproduciendo música. 
sintaxis: 
pygame.mixer.music.get_busy(): return bool 
get_pos 
Obtiene el número de milisegundos desde que el módulo ha comenzado a reproducir 
música. El tiempo que se retorna solo representa cuanto tiempo a estado reproduciendo 
música, este valor no tiene en cuenta cualquier desplazamiento de posición inicial. 
sintaixs: 
pygame.mixer.music.get_pos(): return time 
queue 
Esta función carga un archivo de música y lo pone en una cola. Un archivo que se 
encuentra en la cola comenzará a sonar cuando la música actual termine normalmente. La 
cola de canciones se perderá si la música actual se interrumpe o intercambia. 
sintaxis 
pygame.mixer.music.queue(filename): return None 
7
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
set_endevent 
Esta función hace que pygame emita una señal (con ayuda de la cola de eventos) 
cuando el módulo termine de reproducir. El argumento determina que tipo de evento se 
quiere emite. El evento se emitirá cada vez que una canción termine, no solo la primera vez. 
Para anular la emisión de eventos llame a esta función sin argumentos. 
sintaxis: 
pygame.mixer.music.set_endevent(): return None 
pygame.mixer.music.set_endevent(type): return None 
get_endevent 
Obtiene el evento que un canal emite cuando termina de reproducir. 
sintaxis: 
pygame.mixer.music.get_endevent(): return type 
Sound 
Carga un nuevo sonido a partir de un nombre de archivo, un archivo de python o un 
objeto de almacenamiento que se pueda leer. Se realizará un ajuste limitado de frecuencia 
para que coincida con los argumentos de inicialización del módulo mixer. 
El objeto Sound representa los datos de sonido actual. Los métodos que cambian el 
estado del objeto de sonido lo harán en todas las instancias de ese objeto. El sonido puede 
cargarse desde un archivo de audio OGG o desde un archivo WAV sin compresión. 
sintaixs: 
pygame.mixer.Sound(filename): return Sound 
pygame.mixer.Sound(buffer): return Sound 
pygame.mixer.Sound(object): return Sound 
Nota: La memoria asignada para los datos se copiará internamente, dada de información 
será compartida entre el archivo y el objeto de sonido. 
play 
Comienza a reproducir el sonido en un canal disponible (por ejemplo, en los parlantes 
de la computadora). Se elegirá de forma forzada el canal, por lo tanto la reproducción se 
podría detener el sonido en curso si es necesario. 
El argumento loops controla cuantas veces de deberá repetir el sonido luego de haber 
sonado por primera vez. Un valor como 5 significa que el sonido será reproducido una vez, y 
luego se repetirá cinco veces mas, por lo tanto sonará seis veces en total. El valor por 
defecto (cero) significa que el sonido no se repetirá, y solo sonará una vez. Si loops se define 
a -1 el sonido se repetirá constantemente (aunque podrá llamar a stop() para detenerlo). 
8
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
El argumento maxtime se puede usar para detener la reproducción luego del numero 
de milisegundos indicado. 
El argumento fade_ms hará que el sonido comience a reproducirse desde el valor de 
volumen 0 y aumente de volumen hasta el máximo valor en el tiempo indicado. Note que el 
sonido podría termina antes de que el aumento de volumen se complete. Este método 
retornará un objeto Channel con el canal que ha sido seleccionado. 
sintaxis: 
Sound.play(loops=0, maxtime=0, fade_ms=0): return Channel 
get_num_channels 
Retorna el numero de canales activos donde se está reproduciendo este sonido. 
sintaxis: 
Sound.get_num_channels(): return count 
get_length 
Obtiene la longitud del sonido. Retorna la longitud del sonido en segundos. 
sintaxis: 
Sound.get_length(): return seconds 
get_buffer 
Obtiene un objeto de almacenamiento para modificar el sonido. Retorna un objeto de 
almacenamiento para modificar el sonido. Este objeto se puede usar para acceso directo y 
manipulación. 
sintaxis: 
Sound.get_buffer(): return BufferProxy 
stop, fadeout, set_volume, get_volume, set_volume 
Para no aburrirlos este metodos hacen exactamente lo mismos que los metodos de las 
otras clases, por lo que evitare comentarlos. 
Channel 
Retorna un objeto Channel para uno de los canales actuales. El argumento id debe ser 
un valor entre 0 y el valor que devuelve pygame.mixer.get_num_channels(). 
El objeto Channel se puede usar para obtener un control preciso sobre la reproducción 
9
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
de sonidos. Un canal solo puede reproducir un objeto Sound a la vez. Como pygame por 
defecto maneja por su cuenta estos objetos, utilizarlos es completamente opcional. 
sintaxis: 
pygame.mixer.Channel(id): return Channel 
play 
Comenzará a reproducir un sonido en un canal específico. Se interrumpirá cualquier 
sonido que esté sonando en este canal. 
El argumento loops tiene el mismo significado que en Sound.play(): es el número de 
veces que se repetirá el sonido luego de sonar la primera vez. Si vale 3, entonces el sonido 
se reproducirá 4 veces (la primera y luego 3 veces mas). Si loops vale -1, entonces el sonido 
se repetirá indefinidamente. 
Como en Sound.play(), el argumento maxtime se puede usar para detener la 
reproducción de sonido luego de un tiempo determinado (indicado en milisegundos). 
sintaxis: 
Channel.play(Sound, loops=0, maxtime=0, fade_ms=0): return None 
Nota: Al igual que Sound.play(), el argumento fade_ms se puede usar para alterar 
progresivamente el volumen de un sonido. 
Stop 
Detiene la reproducción de sonido en el canal. Luego de interrumpir la reproducción el 
canal quedará disponible para que nuevos sonidos puedan sonar en él. 
sintaxis: 
Channel.stop(): return None 
pause 
Detiene de forma temporal la reproducción de sonido en un canal. Este sonido se 
puede reanudar nuevamente mediante la función 
Channel.unpause(). 
sintaxis: 
Channel.pause(): return None 
unpause 
Continúa la reproducción en un canal que está en pausa. 
sintaxis: 
Channel.unpause(): return None 
10
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
fadeout 
Detiene la reproducción de un canal luego de reducir progresivamente el volumen de 
un sonido en el tiempo indicado por el argumento time (en milisegundos). 
sintaixs: 
Channel.fadeout(time): return None 
set_volume 
Define el volumen, o latencia, de un sonido. El nivel de volumen se reinicia cuando un 
canal comienza a reproducir nuevamente. Esta función solo afecta al sonido actual. El 
argument value debe ser un número entre 0.0 y 1.0 
Si se pasa un solo argumento, este se interpretará como el volumen de ambos 
parlantes. Si se pasan dos argumento y el módulo mixer usa el modo estéreo, entonces el 
primer argumento será el volumen del parlante izquierdo y el segundo argumento será el 
volumen del parlante derecho. (Si el segundo argumento es None, entonces el primer 
argumento se interpretará como el volumen de ambos parlantes.) 
sintaxis: 
Channel.set_volume(value): return None 
Channel.set_volume(left, right): return None 
get_volume 
Retorna el volumen del canal para el sonido que es está reproduciendo. Esta función 
no tiene en cuenta la separación estéreo que se ha utilizado en Channel.set_volume. El 
objeto Sound también tiene su propio volumen que se mezcla con el del canal. 
sintaxis: 
Channel.get_volume(): return value 
get_busy 
Consulta si el canal está activo. 
sintaxis: 
Channel.get_busy(): return bool 
get_sound 
Obtiene el sonido que se está reproduciendo actualmente. Retorna el objeto Sound 
que se está reproduciendo en este canal. Retornará None si el canal está inactivo. 
sintaxis: 
11
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
Channel.get_sound(): return Sound 
queue 
Un objeto Sound comienza a reproducirse inmediatamente después de otro si se 
coloca en la cola de reproducción del canal. Cada canal solo puede tener un sonido en cola al 
mismo tiempo. El sonido en cola solo se reproducirá si el sonido actual finaliza normalmente. 
En otro caso, si se llama a Channel.stop() o Channel.play(), el sonido en cola se cancelará. El 
sonido comenzará a reproducirse inmediatamente si no hay otro sonido en curso. 
sintaxis: 
Channel.queue(Sound): return None 
get_queue 
Se retornará el sonido que esté en cola para este canal. Una vez que el sonido 
comienza a reproducirse ya no estará en la cola de reproducción. 
sintaxis: 
Channel.get_queue(): return Sound 
set_endevent 
Hace que el canal envíe un evento cuando la reproducción finalice. Cuando se define 
un evento de terminación para el canal, se enviará un evento a la cola de eventos cada vez 
que un sonido termine de reproducirse en este canal (no solo la primera vez). Use la función 
pygame.event.get() para recibir el evento de terminación una vez que halla sido enviado. 
Note que si ha llamado a Sound.play(n) o Channel.play(sound, n), el evento de 
terminación se enviará una sola vez, luego de reproducirse “n+1” veces (vea la 
documentación de Sound.play). 
Se enviará el evento de terminación inmediatamente si se llama a Channel.stop() o 
Channel.play() mientras el sonido está en reproducción. 
El argumento type indica el identificador de evento para enviar a la cola de eventos. 
Puede ser válido usar cualquier tipo de evento, aunque una buena elección debería ser optar 
por un valor entre pygame.locals.USEREVENT y pygame.locals.NUMEVENTS. 
sintaxis: 
Channel.set_endevent(): return None 
Channel.set_endevent(type): return None 
El canal dejará de enviar eventos si se llama a esta función sin argumentos. 
get_endevent 
12
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
Obtiene el evento que un canal emite cuando finaliza la reproducción. Retorna el tipo 
de evento que se enviará cada vez que el canal termina de reproducir un objeto Sound. Esta 
función retornará pygame.NOEVENT si el canal no tiene asignado un evento para emitir. 
sintaxis: 
Channel.get_endevent(): return type 
La verdad de la Milanesa :P 
Traducido significa lo que en verdad nos tiene que interesar si son como yo y no 
tienen conocimientos avanzados sobre audio pero aun asi les interesa agregar sonidos a sus 
juegos. 
En resumen, pygame.mixer nos brinda los controles generales sobre el resto de los 
modulos de niveles inferiores en el manejo de audio, Ademas nos da 2 posibilidadeso formas 
para reproducir sonidos, la primera es directa y mas sencilla utiliza el modulo 
pygame.mixer.music pero tiene la dificultad de que solo puede reproducir un sonido o 
tema a la ves, a lo sumo los diferentes sonidos se podrian ir agregando a la cola de 
reproducion, el unico problema es que es necesario cargar desde archivo cada ves que se 
quiere reproducir. 
Bien ahora un poco de codigo de ejemplo sobre pygame.mixer.music, pero este sera 
un poco interactivo para no tener que escribir demasiado. 
>>> import pygame 
>>> pygame.init() #inicializamos la mayoria de los modulos entre ellos mixer 
(6, 0) 
>>> pygame.mixer.music.load('after_in_the_dark.ogg') #al archivo lo tengo en 
el path de python por eso no pongo la ruta 
>>> pygame.mixer.music.play(2) #el tema se reproducira 3 veses 
>>> pygame.mixer.music.queue('nirvana_seigyo_fortnoug.ogg') #agregamos el 
archivo a la cola de reproducion 
En fin lo que hicimos fue, primero como siempre importar e inicializar pygame, con 
ello tanbien automaticamente logramos inicializar pygame.mixer con los parametros por 
defecto. 
Lo siguiente fue cargar un tema en OGG (por algun motivo con este metodo cuando 
intento cargar otra cosa que no sea un OGG como un WAV me da error, me dice que no lo 
puede cargar). 
Luego le decimos que reprodusca el tema actual, si queremos que se reprodusca 1 
vez pasamos 0, si queremos que se reprodusca 2 veses pasaremos un 1 y haci 
sucesivamente, si quisieramos que se reprodujera el tema indefinidamente tendriamos que 
pasar -1 como parametro. 
por ultimo agregamos otro archivo a la cola de reproducion, este comenzara a 
reproducirse automaticamente despues de que el ultimo archivo termine de reproducirse. 
La segunda forma, diria la recomendada (Usar los Objectos Chanels Solo si saben 
como hacerlo, sino estaran apostando a su suerte :P) es reproducir los sonidos que emita 
nuestro juego mediante el uso de objectos Sound y dejar que pygame se encargue del 
manejo de de los canales osea los objectos Chanels, su manejo basico es sencillo y se crean 
de la siguiente manera: 
13
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
back = pygame.mixer.Sound('background.ogg') #suponer que este es el sonido de 
fondo 
sound1 = pygame.mixer.Sound('sound.wav') #sonidos para los efectos 
#.... otros sonido que quieran agregar 
Sonido de Fondo (Background) 
Es el sonido que se reproducira todo el tiempo para anbientizarnos con el ecenario, es 
el mas sencillo de implementar, al comienzo del bucle principal (antes de entrar en el) del 
juego solo tendrian que comenzar a reproducir indefinidamente el sonido de fondo, seria 
razonable que la duracion del sonido que usaremos como fondo sea dentro de todo larga. 
back.play(-1) #reproducir indefinidamente 
loop = True 
while lopp: 
screen.fill(BLANCO) 
.... 
por ende al salir de dicho bucle llamar al metodo stop() para detener su reproducion 
back.stop() 
Efectos de Sonidos 
Los efectos de sonido normalmente son lanzados por ejemplos cuando una pelota 
coliciona con la parede, aceleramos un auto, un diparo coliciona contra un tanque y por 
ejemplo tenemos que lanzar la animacion de una explosion junto con el sonido, en fin 
podemos hacer varias cosas, definer los efectos de sonido por cada objecto, cosa que no es 
muy logico ya que eston objectos no son unicos en el juego y tenderan a repetirse, la otra 
solucion es tener un mini modulo donde precargariamos todos nuestros efectos de sonidos 
por ejemplo en un dicionario, creariamos una sencilla funcion que reproduciria un sonido 
determinado por una cadena de caracteres que por ejemplo coincidiria con la clave (en el 
dicionario) del objecto sonido que queremos reproducir en fin algo como: 
SONIDOS = { 
'shoot' : pygame.mixer.Sound('sonidos/shoot.wav'), 
'explode' : pygame.mixer.Sound('sonidos/explocion.wav'), 
'clic' : pygame.mixer.Sound('sonidos/clic.wav'), 
# etc... 
} 
def reproducir(tema): 
SONIDOS[key].play() 
Despues solo importariamos el mini modulo dentro del archivo donde por ejemplo 
definiriamos la clase que maneje a nuestro personaje, y cuando querramos reproducir un 
sonido determinado por ejemplo siguiendo con la explocion: 
#extracto de codigo de lo que podria ser una clase que maneje los objectos disparo, esto es 
solo para ejemplificar 
14
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
def colicion(self, target): 
if self.colliderect(target.rect): 
self.explode() #lanza la animacion de explocion 
self.enable = False 
#reproducimos el sonido 
reproducir("explode") 
Otra opcion mas elegante seria que cuando ocurra algo como esto, lancemos un 
evento (para algo esta pygame.event y no es un simple modulo que comente por comentar) 
de la siguiente forma: 
#creamos un evento personalizado 
evt = pygame.event.Event(pygame.USEREVENT, {'play':'explode'}) 
pygame.event.post(evt) #lo colocamos dentro de la cola 
Nota: En los eventos creados por el usauario podemos aceder al dicionario de parametros 
mediante el atributo 'dict' 
Luego en la secion donde normalmente leemos todos los eventos en busca de algun 
evento pygame.QUIT podriamos agregar unas cuantas lineas para que esta secion se 
encargue de reproducir todos los sonidos, osea capturar lo eventos del tipo 
pygame.USEREVENT y reproducir el tema definido por play: 
for evento in pygame.event.get(): 
#capturamos los eventos creados 
if evento.type == pygame.USEREVENT: 
reproducir(evento.dict['play']) 
elif evento.type == pygame.QUIT: 
loop =False 
pygame.sprite 
Bueno el ultimo modulo de pygame que veremos en este capitulo se llama 
pygame.sprite el cual a rasgo generales nos permite manejar grupos de objecto, y que son 
esos objectos que mencionamos, bueno este termino no se refiere explicitamente a la POO 
sino al manejo de Objectos Sprites osea todos los elementos que interactuan en nuestro 
juego. 
El uso de este modulo es opcional, particularmente no lo uso por que prefiero escribir 
mis propias clases para manejo de Sprites, esto no es reinventar la rueda, solo es hacer 
soluciones a medida. 
Se espera que la clase Sprite se utilice como clase base para los 
diferentes tipos de objetos en el juego. También hay una clase Group básica que 
simplemente almacena sprites. Un juego podría crear nuevos tipos de clases Group que 
operen sobre instancias de objetos Sprite personalizadas. 
La clase Sprite básica puede dibujar los sprites que contiene sobre una superficie. El 
método Group.draw() requiere que cada que cada Sprite tenga los atributos image y 
15
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
rect. El método Group.clear() requiere estos mismos atributos para poder borrar 
todos los sprites con fondo de pantalla. También hay grupos mas avanzados, por ejemplo 
pygame.sprite.RenderUpdates() y pygame.sprite.OrderedUpdates(). 
Los sprites y los grupos manejan sus relaciones con los métodos add() y remove()'. 
Estos métodos pueden aceptar una o varias instancias de objetos. Los inicializadores para 
estas clases también aceptan uno o varios objetos para insertar. Es seguro agregar y 
eliminar el mismo Sprite de un grupo. 
Mientras es posible diseñar clases de sprite y grupos que no deriven desde las clases 
Sprite y AbstractGroup de mas arriba, es extremadamente que herede de ellas cuando 
agregue una clase de grupo o sprite. Los sprites no son seguros para operar desde diferentes 
hilos, por lo tanto debe bloquearlos usted mismo si está usando hilos. 
spritecollide 
Encuentra sprites en el grupo que están en contacto con otro sprite. Retorna una lista 
que contiene todos los sprites en un grupo que están colisionando con otro sprite. La 
intersección se determina comparando el atributo Sprite.rect de cada sprite. 
El argumento dokill es un valor booleando. Si vale True todos los sprites que 
colisionan se eliminarán del grupo. 
El argumento collided es una función que se utiliza para calcular si dos sprites están 
en contacto, esta función debería tomar dos sprites como agumentos y retornar un valor 
True o False indicado si están colisionando. Si no se especifica el valor para el argumento, 
todos los sprites deberán tener un valor rect, que es el rectángulo del área de sprite, que se 
usará para calcular la colisión. 
Funciones de colisión: 
• collide_rect 
• collide_rect_ratio 
• collide_circle 
• collide_circle_ratio 
• collide_mask 
sintaxis: 
pygame.sprite.spritecollide(sprite, group, dokill, collided = None): 
return Sprite_list 
collide_rect 
Consulta la colisión entre dos sprites. Usa la función colliderect del módulo rect para 
calcular la colisión. Está diseñada para ser enviada como una función de colisión a las 
funciones generales de colisión. Los sprites deben tener atributos rect. 
sintaxis 
pygame.sprite.collide_rect(left, right): return bool 
collide_rect_ratio 
16
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
Verifica colisiones entre dos sprites usando usa versión reducida de los rectángulos de 
sprite. Se generan con un radio, y la instancia retornada está diseñada para ser enviada 
como una función de colisión a las funciones generales de colisión. El argumento ratio es un 
número real, 1.0 indica que será del mismo tamaño, 2.0 es el doble de grande y 0.5 es de la 
mitad de tamaño. 
sintaixis: 
pygame.sprite.collide_rect_ratio(ratio): return collided_callable 
collide_circle 
Verifica la colisión entre dos sprites, verificando si dos círculos centrados en los sprites 
están en contacto. Si el sprite tiene un atributo radius este se usará para crear en círculo, en 
caso de que no exista se creará un círculo lo suficientemente grande para contener todo el 
rectángulo del sprite indicado por el atributo rect. Esta función está diseñada para ser 
enviada como función de colisión a las funciones generales de colisión. Los sprites deben 
tener los atributos rect y radius 
sintaixis: 
pygame.sprite.collide_circle(left, right): return bool 
collide_circle_ratio 
Verifica colisiones entre dos sprites usando usa versión reducida de los círculos de 
sprite. Se generan con un radio, y la instancia retornada está diseñada para ser enviada 
como una función de colisión a las funciones generales de colisión. El argumento ratio es un 
número real, 1.0 indica que será del mismo tamaño, 2.0 es el doble de grande y 0.5 es de la 
mitad de tamaño. 
El objeto creado verifica la existencia de colisión entre dos sprites, comprobando si los 
dos círculos con centro en los sprites están en contacto luego de haberlos alterado de 
tamaño. Lo los sprites tienen un atributo radius este se usará para crear el círculo, en otro 
caso se creará un círculo lo suficientemente grande grande para contener por completo el 
rectángulo de sprite según su atributo rect. Está diseñada para ser enviada como función de 
colisión a las funciones generales de colisión. Los sprites deben tener los atributos rect y 
radius (este último es opcional). 
sintaixis: 
pygame.sprite.collide_circle_ratio(ratio): return collided_callable 
collide_mask 
Verifica la colisión entre dos sprites, probando si sus máscaras de bits se superponen. 
Si el sprite tiene un atributo mask, este atributo se usará como máscara, en otro caso se 
creará la máscara a partir de la imagen del sprite. Esta función está diseñada para ser 
enviada como función de colisión a las funciones generales de colisión. Los sprites deben 
tener un atributo rect y un atributo opcional de nombre mask. 
17
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
sintaixis: 
pygame.sprite.collide_mask(SpriteLeft, SpriteRight): return bool 
groupcollide 
Esta función encontrará intersecciones entre todos los sprites de dos grupos. Las 
intersecciones se determinan comparando los atributos Sprite.rect de cada Sprite. Cada 
sprite dentro del grupo group1 se agrega al diccionario de retorno como clave. El valor de 
cada elemento será una lista de los sprites del grupo group2 que colisionan con el primero. 
sintaixis: 
pygame.sprite.groupcollide(group1, group2, dokill1, dokill2): return 
Sprite_dict 
spritecollideany 
Consulta si el sprite dado colisiona con algún sprite en el grupo. La intersección se 
determina comparando el atributo Sprite.rect de cada sprite. Esta prueba de colisión puede 
ser mas rápida que pygame.sprite.spritecollideany() dado que tiene menos trabajo para 
hacer. Retornará al encontrar la primer colisión. 
sintaixis: 
pygame.sprite.spritecollideany(sprite, group): return bool 
Sprite 
Como comente arriba, pygame.sprite.Sprite es la clase base de cualquier objecto en 
un juego, por defecto esta clase posee 2 atributos image y rect. sobre-escribirán el método 
Sprite.update() y asignarán un valor a los atributos Sprite.image y Sprite.rect. El constructor 
puede aceptar cualquier número de objetos Group a donde se insertará el objeto. 
sintaxis: 
pygame.sprite.Sprite(*groups): return Sprite 
update 
La implementación por defecto de este método no hace nada; es solo un hueco 
conveniente que puede sobreescribir. Este método se llama desde Group.update() con 
cualquier argumento que se le envíe. 
sintaxis: 
Sprite.update(*args): #tiene que redefinirse este metodo 
18
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
add 
Inserta el sprite a los grupos. 
sintaixis: 
Sprite.add(*groups): return None 
remove 
Elimina un sprite de los grupos. 
sintaixis: 
Sprite.remove(*groups): return None 
kill 
Elimina el Sprite de todos los grupos. El Sprite será eliminado de todos los grupos a 
los que pertenezca. No se cambiará nada acerca del estado del Sprite. Es posible continuar 
usando el Sprite luego de haber llamado a este método, incluyendo agregarlo a otros grupos. 
sintaixis: 
Sprite.kill() return None 
alive 
Consulta si el sprite pertenece a algún grupo. 
sintaxis: 
Sprite.alive(): return bool 
groups 
Lista los grupos que contienen este sprite. 
sintaixis: 
Sprite.groups(): return group_list 
Group 
Un contenedor simple para objetos Sprite, es el mas basico de todos los grupos 
contenedores que posee pygame.sptrite. Se puede heredar de esta clase para crear 
contenedores que tengan comportamiento mas específico. El constructor toma cualquier 
número de sprites para agregar en el grupo. El grupo soporta las siguientes operaciones 
estándar de python: in, len, bool iter 
19
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
sintaixis: 
pygame.sprite.Group(*sprites): return Group 
sprites 
Retorna una lista con todos los sprites contenidos en el grupo. También puede obtener 
un iterador para el grupo, aunque no podrá iterar en el grupo mientras lo modifica. 
sintaixis: 
Group.sprites(): return sprite_list 
copy 
Duplica el grupo. crea una copia en ves de una referencia del grupo. 
sintaixis: 
Group.copy(): return Group 
add 
Agrega cualquier número de sprites a este grupo. Esta función solo agregará sprites 
que aún no sean miembros del grupo. 
sintaixis: 
Group.add(*sprites): return None 
remove 
Elimina cualquier número de sprites del grupo. Esta función solo elimina sprites que 
son miembros actuales del grupo. 
sintaxis: 
Group.remove(*sprites): return None 
has 
Consulta si un grupo contiene sprites. 
sintaixis: 
Group.has(*sprites): return None 
update 
Llama al método update()) en todos los sprites incluidos en el grupo. La clase base 
Sprite tiene un método update que toma cualquier número de argumentos y no hace nada. 
20
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
Los argumento que se pasan a Group.update() se pasarán a cada Sprite. 
sintaixis: 
Group.update(*args): return None 
draw 
Dibuja los sprites contenidos sobre el argumento Surface. Para ello utiliza el atributo 
Sprite.image para la superficie fuente y Sprite.rect para la posición. El grupo no almacena los 
sprites en orden, por lo tanto el orden al momento de dibujar es arbitrario. 
sintaixis: 
Group.draw(Surface): return None 
clear 
Borra los sprites usados en la última llamada a Group.draw(). La superficie destino se 
limpia pintando con el fondo de pantalla sobre las posición anterior del sprite. 
El fondo de pantalla es generalmente una Superficie que tiene las mismas 
dimensiones que la superficie destino. De todas formas, también puede ser un nombre de 
función que tome dos argumentos, la superficie destino y un area a limpia. La función 
background se llamará varias veces para limpiar la pantalla. 
sintaixis: 
Group.clear(Surface_dest, background): return None 
empty 
Elimina todos los sprites de este grupo. 
sintaixis: 
Group.empty(): return None 
Grupos Avanzados de Sprites 
Ademas de la clase basica Group, pygame provee un grupo de clases especificas para 
manejar distintos tipos de sprites, todos ellos heredan los atributos y metodos basicos que 
heredan de Group, estos son: 
GroupSingle 
Grupo contenedor que almacena un solo Sprite, para que sirve, es simple este es el 
grupo que almacenara al Heroe. Existe una propiedad especial, GroupSingle.sprite, que 
accede al sprite que un grupo contiene. Puede ser None cuando el grupo está vacío. Incluso 
21
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
la propiedad se puede utilizar para asignarle un sprite y que éste se almacene dentro del 
contenedor GroupSingle. 
LayeredDirty 
El grupo LayeredDirty está diseñado para objetos DirtySprite que es una subclase con 
algunas cosas mas que Sprite, osea trabaja con sprites que utilizan la tecnica de rectangulo 
Sucio, y es subclase de LayeredUpdates. Este grupo utiliza una técnica de marcas dirty, por 
lo tanto es mas rápido que los grupos pygame.sprite.RenderUpdates si usted tiene varios 
sprites estáticos. Además cambia automáticamente entre dos modalidades de actualización: 
pantalla completa o actualización dirty rectangles, por lo tanto no tendrá que preocuparse de 
que tendría que ser mas rápido. 
LayeredUpdates 
Grupo que pemite dibujar los Sprites mediante capas, osea se define el orden de 
dibujo de cada sprite usando el argumento para indicar a que capa pertenece. 
Si el sprite que se agrega al grupo tiene un atributo de nombre layer, entonces se 
utilizará ese atributo para determinar en que capa se va a agregar el sprite. Si el argumento 
kwarg contiene el parámetro layer entonces los sprites se agregarán a esa capa (ignorando 
el atributo sprite.layer). Se utilizará la capa por defecto para insertar los sprites si no se 
utiliza ninguna de las formas descritas mas arriba. 
RenderUpdates 
Clase de grupo que utiliza el procedimiento 'dirty rectangles'. Dibuja las imágenes de 
objetos Sprite y guarda información de las áreas modificadas. 
Dibuja todos los objetos Sprite en la superficie, al igual que Group.draw(). Aunque 
este método retorna una lista de áreas rectangulares de la pantalla que han sido 
modificadas. Los cambios devueltos incluyen áreas de la pantalla que han sido afectadas por 
llamadas previas a Group.clear 
La lista de objetos Rect devuelta se podría utilizar para llamar a 
pygame.display.update. Esto ayudará a mejorar el rendimiento del programa en modos de 
video gestionados por software. Este tipo de actualización solamente es útil en pantallas sin 
fondos animados. 
OrderedUpdates 
Esta clase deriva de pygame.sprite.RenderUpdates(). Mantiene el orden en que se 
agregaron los objetos Sprite al grupo para imprimirlos. Esto produce que agregar y eliminar 
objetos del grupo sea un poco mas lento que en los Grupos normales. 
Bueno los ejemplos de trabajo con Sprites y Grupos son sencillos, yo los dejo para 
que los vean mas abajo, cuando muestre el codigo de como crear animacion sencilla. 
22
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
Animacion de Sprites 
Esto es bastante simple, aquí aparece el concepto de frame o cuadro, que 
corresponde a una de las imágenes que forman la animación completa de un sprite. Podemos 
pensar en una secuencia de imágenes que son dibujadas rápidamente, que engañan al ojo 
humano dando el efecto de un movimiento fluido. Es el mismo método que se utiliza para los 
dibujos animados. Si alguna ves trabajaron con Flash o hicieron un gif animado creo que 
sabran de que estamos ablando. 
El número de frames dibujados en un periodo de tiempo se conoce como frame rate 
(tasa de frames), siendo un aspecto muy importante en la animación, ya que de esto 
depende la calidad de animación que obtendremos. Si cada uno de los frames se muestra 
muy rápido o muy lento, la ilusión del movimiento se perderá y el usuario verá cada uno de 
los frames como una imagen separada. Una animación muy común puede ser la de un 
personaje caminando, saltando, o realizando cualquier otra acción. 
Esto también debe ser representado de alguna forma inteligente en nuestro 
videojuego, utilizando algún tipo de estructura de datos adecuada, como un vector o lista. 
Normalmente el sprite tendrá como atributo una lista de animaciones (las acciones del 
personaje, enemigo, etc.), 
donde cada animación corresponderá a otra lista con cada uno de los frames. La totalidad de 
los frames que forman un personaje, suele lmacenarse en un solo archivo de imagen, a esto 
se le llama sprite sheet, es decir, una imagen donde tenemos secuencias de frames para las 
diferentes acciones que puede realizar un personaje en un videojuego. La siguiente imagen 
lo ilustra claramente. 
23
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
¿Que es un Frame (Cuadro)? 
Durante todo este tiempo estubimos ablando de Frame Rate o Cuadros por Segundo, 
un Frame vendria a ser el estado de una animacion (en este caso nuestro juego) en un 
momento de tiempo determinado, para mayor sencilles un frame es un estado de la ecena 
(en este caso nuestro personaje) que es remplazada tan rapidamente que no hace parecer 
que tenemos un efecto de fluides en el movimento del personaje. A modo de ejemplo los 
frames vendrian a ser las capturas de los diferentes estados de una imagen como la de mas 
abajo, si los vemos por separados no tiene sentiedo, pero si los juntamos y hacemos que 
cambie cada determinado intervalo de tiempo lograremos un efecto de animacion en la 
pelota. 
Animacion Completa vs Animacion Limitada 
En el cine existe un estándar de 24 imágenes por segundo. Esa es la tasa a la que 
graban las cámaras y proyectan los proyectores. Se toma una fotografía de la imagen cada 
veinticuatroavo de segundo. 
En la animación, sin embargo, las imágenes no se toman sino que se producen 
individualmente, y por ello no tienen que cumplir necesariamente con el estándar del cine. 
Una película de animación tiene siempre 24 fotogramas por segundo, pero no 
necesariamente todos esos fotogramas muestran imágenes diferentes: en la animación, las 
imágenes suelen repetirse en varios fotogramas. 
Así pues, tenemos varias tasas de animación: 
• En unos: cada imagen es diferente, sin repetición. 24 imágenes por segundo, 1 
imagen cada fotograma. 
• En doses: cada imagen se repite dos veces. 12 imágenes por segundo, 1 imagen cada 
2 fotogramas. 
• En treses: cada imagen se repite tres veces. 8 imágenes por segundo, 1 imagen cada 
3 fotogramas. 
Se ha calculado que el umbral visual por debajo del que ya no se capta un 
movimiento sino imágenes individuales es de 7 imágenes por segundo. 
Animación completa es cuando se anima en unos o en doses. Es el estándar de la 
animación estadounidense para salas de cine, principalmente las películas de Walt Disney, y 
24
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
también los largometrajes europeos. Generalmente, se animan las escenas con muchos 
movimientos rápidos en unos, y el resto en doses (la pérdida de calidad es imperceptible). 
Animación limitada es cuando se anima en una tasa inferior. El estándar del animé 
japonés es animación en treses. La pérdida de calidad ya es perceptible si se es observador. 
El concepto de animación limitada también afecta a otros aspectos diferentes de la tasa. Por 
ejemplo, es animación limitada cuando se repiten ciclos: pensemos en Pedro Picapiedra 
corriendo mientras al fondo aparecen una y otra vez las mismas casas en el mismo orden. 
Hay que tener en cuenta que diferentes elementos de la imagen (un personaje, otro 
personaje, un objeto móvil, un plano del fondo, otro plano del fondo) se animan por 
separado, y que por tanto dentro de la misma escena puede haber elementos con diferentes 
tasas de animación. 
Un Ejemplo Sencillo 
Veremos como almacenar varios cuadros de animación en un solo archivo para 
realizar una animación muy simple (como mencionamos arriba). Esto nos resultará de 
utilidad para manejar animaciones y comprender los próximos artículos. Creando los gráficos 
del personaje 
Para mostrar una animación tendremos que imprimir uno a uno varios cuadros de 
animación. Nos resultará de mucha utilidad almacenar cada uno de estos cuadros en un 
único fichero gráfico. 
Cuando nos queramos referir a la imagen que contiene todos los cuadros le 
llamaremos grilla, porque contiene varios rectángulos de igual tamaño con los cuadros de 
animación de nuestro personaje. 
Aunque no todos los cuadros y o capturas de nuestro personaje obligatoriamete 
tienen que tener el mismo grosor, pero al hacerlo nos evitaremos complicaciones en el 
codigo, bien las imagen con todos los cuadros que usaremos para este ejemplo es un poco 
reducida (solo unos poco cuadros). 
Como vemos nuestro ejemplo contendra 5 cuadros, para claridad los enumeraremos 
de 0 a 4 (por que de 0 a 4 y no de 1 a 5, es simple cuando animemos y hagamos 
desplazamiento nos sera mas sencillo). 
Para dibujar algunos de los cuadros necesitamos al menos conocer la siguiente 
información: 
• Cantidad total de Filas y Columnas, en nuestro caso 1, fila y 5 columnas 
• El ancho y alto Completo de la imagen, en este ejemplo 240x35 pixels 
Con estos datos ya podemos calcular el ancho y alto de cada cuadro: 
frame_ancho = imagen_ancho // num_filas 
frame_alto = imagen_alto // num_columnas 
25
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
en nuestro caso: 
frame_ancho = 240 // 5 # 48 
frame_alto = 35 / 1 # 35 
Ahora bien supongamos que queremos calcular el area a dibujar de un frame o cuadro 
en particular por ejemplo el frame 3 (vendria a ser el cuarto cuadro), conocemos el ancho y 
alto del frame solo nos falta conocer el desplazamiento vertical (en realidad en este ejemplo 
no hay osea es 0 ya que tenemos una sola fila) y horizontal, como todos los cuadros o 
frames son del mismo tamaño este calculo del desplazamiento es simple y solo tenemos que 
multiplicar el nro de frame actual por el ancho o alto dependiendo la situacion. 
frame_num = 3 #para el ejemplo 
dy = 0 #como dijimos en este ejemplo no tenemos desplazamiento vertical 
dx = frame_num * frame_ancho # 3 * 48 = 144 
Con eso ya tenemos el area de recorte para mostrar en pantalla y usando el metodo 
surface.blit seria: 
area_recorte = pygame.Rect(dx, dy, frame_ancho, frame_alto) 
surface.blit(imagen, (x, y), area_recorte) 
Por ultimo hay que definir un ciclo de animacion, en nuestro ejemplo el ciclo de 
animacion sera el siguiente: 
0,1,2,3,4,5,0,1,2,3,4,5,1,2,3.... 
Bien ahora veamos el codigo completo de como se veria una clase Sprite basica que 
represente una animacion: 
class SpriteAnimado(pygame.sprite.Sprite): 
def __init__(self, imagen, filas=1, columnas=1): 
pygame.sprite.Sprite.__init__(self) 
#grilla que contendra todos los cuadros o frames 
self.image = pygame.image.load(imagen) 
self.image.set_colorkey(MAGENTA) 
#como tengo pocos cuadros tengo que agregar un contador 
#adicional para que los cuadros no pasen tan rapido 
self.cont = 0 
self.filas = filas 
self.columnas = columnas 
self.frame_num = 0 
self.frame_ancho = self.image.get_width() / self.columnas 
self.frame_alto = self.image.get_height() / self.filas 
self.rect = pygame.Rect(0, 0, self.frame_ancho, self.frame_alto) 
26
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
def update(self, *argv): 
self.cont += 1 
if self.cont > 10: 
self.frame_num += 1 
self.cont = 0 
if self.frame_num >= 5: 
self.frame_num = 0 
def draw(self, surface): 
dx = self.frame_num * self.frame_ancho 
dy = 0 
area_recorte = pygame.Rect(dx, dy, self.frame_ancho, self.frame_alto) 
surface.blit(self.image, self.rect, area_recorte) 
A estas alturas no creo que sea necesario explicar el resto del codigo, y como veran 
este ejemplo ademas nos sirvio como ejemplo de como crear una clase derivada del modulo 
sprite.Sprite, como veran modifique ademas el metodo draw (habran notado que a lo largo 
de este curso use drawn en ves de draw para el metodo que dibuja el sprite sobre la 
superficie, se que esta mal expresado como lo escribo, pero diria que es solo una cuestion de 
gustos.) en fin aca tienen una captura del ejemplo corriendo: 
(vease ejemplo_animacion.py) 
Bueno con esto doy por finalizado este Modulo de Introducion a la Programacion de 
Juego, mas explicitamente al sub Curso Aprender a usar PyGame, Ahora bien el curso 
completo no termina aquí, le sigue el segundo modulo donde ya nos dedicaremos 
explicitamente al tema programacion de juegos, aunque seguiremos usando pygame, el uso 
o no de esta librería no tendra tanta relevancia, en fin algunos de los temas que vienen en la 
segunda parte de este curso, aunque no os digo que los publique en ese orden: 
• IA (Inteligencia Artificial) Introducion a la Inteligencia Artificial aplicada a la 
programacion de Juegos 
• Scroling (Mapas compuestos por tiles) 
• Juegos en Red (como utilizar Sockets en nuestros juegos) 
27
Curso de: Programación de Juegos con PyGame 
Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com 
• mas... 
Saludos, y nos vemos en la segunda parte del curso... 
28

Más contenido relacionado

Destacado (9)

Intro PyGame Capitulo 1
Intro PyGame Capitulo 1Intro PyGame Capitulo 1
Intro PyGame Capitulo 1
 
Taller de Pilas Engine, un motor de juegos en Python - PyConES 2014
Taller de Pilas Engine, un motor de juegos en Python - PyConES 2014Taller de Pilas Engine, un motor de juegos en Python - PyConES 2014
Taller de Pilas Engine, un motor de juegos en Python - PyConES 2014
 
(Sin anotaciones) - En busca de la Física
(Sin anotaciones) - En busca de la Física(Sin anotaciones) - En busca de la Física
(Sin anotaciones) - En busca de la Física
 
Programación de Videojuegos con Python y Pilas (III)
Programación de Videojuegos con Python y Pilas (III)Programación de Videojuegos con Python y Pilas (III)
Programación de Videojuegos con Python y Pilas (III)
 
Curso Programacion de Juego Introducion IA
Curso Programacion de Juego Introducion IACurso Programacion de Juego Introducion IA
Curso Programacion de Juego Introducion IA
 
Programación de Videojuegos con Python y Pilas (I)
Programación de Videojuegos con Python y Pilas (I)Programación de Videojuegos con Python y Pilas (I)
Programación de Videojuegos con Python y Pilas (I)
 
Intro PyGame Capitulo 5
Intro PyGame Capitulo 5Intro PyGame Capitulo 5
Intro PyGame Capitulo 5
 
Programación de Videojuegos con Python y Pilas (II)
Programación de Videojuegos con Python y Pilas (II)Programación de Videojuegos con Python y Pilas (II)
Programación de Videojuegos con Python y Pilas (II)
 
Programación con Pygame I
Programación con Pygame IProgramación con Pygame I
Programación con Pygame I
 

Similar a Intro Pygame Capitulo 6

Como hacer un reproductor de mp3
Como hacer un reproductor de mp3Como hacer un reproductor de mp3
Como hacer un reproductor de mp3
Maxon Dixom
 
Tutorial Essential & Pro Tools, EspañOl
Tutorial   Essential & Pro Tools, EspañOlTutorial   Essential & Pro Tools, EspañOl
Tutorial Essential & Pro Tools, EspañOl
BartGonzalez
 
PráCticas Con Sonido
PráCticas Con SonidoPráCticas Con Sonido
PráCticas Con Sonido
Aida Martín
 
La edicion musical_para_las_clases_de_educacion_fsica[1]
La edicion musical_para_las_clases_de_educacion_fsica[1]La edicion musical_para_las_clases_de_educacion_fsica[1]
La edicion musical_para_las_clases_de_educacion_fsica[1]
aalandesalfonso
 
Unmp3
Unmp3Unmp3
Unmp3
Diego
 
Audition reference
Audition referenceAudition reference
Audition reference
Yimi Rueda
 
Programas para edicion de audio e imagen
Programas para edicion de audio e imagenProgramas para edicion de audio e imagen
Programas para edicion de audio e imagen
wilberavalosp
 
Programas para edicion de audio e imagen
Programas para edicion de audio e imagenProgramas para edicion de audio e imagen
Programas para edicion de audio e imagen
Chepe1234
 

Similar a Intro Pygame Capitulo 6 (20)

Actividades 1 a 7
Actividades 1 a 7Actividades 1 a 7
Actividades 1 a 7
 
Traktor
TraktorTraktor
Traktor
 
Como hacer un reproductor de mp3
Como hacer un reproductor de mp3Como hacer un reproductor de mp3
Como hacer un reproductor de mp3
 
Tutorial Essential & Pro Tools, EspañOl
Tutorial   Essential & Pro Tools, EspañOlTutorial   Essential & Pro Tools, EspañOl
Tutorial Essential & Pro Tools, EspañOl
 
Audacity Maria Valdes Solis
Audacity Maria Valdes SolisAudacity Maria Valdes Solis
Audacity Maria Valdes Solis
 
PráCticas Con Sonido
PráCticas Con SonidoPráCticas Con Sonido
PráCticas Con Sonido
 
PráCticas Con Sonido
PráCticas Con SonidoPráCticas Con Sonido
PráCticas Con Sonido
 
La edicion musical_para_las_clases_de_educacion_fsica[1]
La edicion musical_para_las_clases_de_educacion_fsica[1]La edicion musical_para_las_clases_de_educacion_fsica[1]
La edicion musical_para_las_clases_de_educacion_fsica[1]
 
Unmp3
Unmp3Unmp3
Unmp3
 
Manual de hydrogen
Manual de hydrogenManual de hydrogen
Manual de hydrogen
 
Prcticasconsonido
PrcticasconsonidoPrcticasconsonido
Prcticasconsonido
 
Audition reference
Audition referenceAudition reference
Audition reference
 
Música y efectos de sonido en unity con audio listener y audio source
Música y efectos de sonido en unity con audio listener y audio sourceMúsica y efectos de sonido en unity con audio listener y audio source
Música y efectos de sonido en unity con audio listener y audio source
 
Soundation tutorial.
Soundation tutorial. Soundation tutorial.
Soundation tutorial.
 
Etiquetas de audio html
Etiquetas de audio htmlEtiquetas de audio html
Etiquetas de audio html
 
Guía para aprender a editar en openitg
Guía para aprender a editar en openitgGuía para aprender a editar en openitg
Guía para aprender a editar en openitg
 
Programas para edicion de audio e imagen
Programas para edicion de audio e imagenProgramas para edicion de audio e imagen
Programas para edicion de audio e imagen
 
Programas para edicion de audio e imagen
Programas para edicion de audio e imagenProgramas para edicion de audio e imagen
Programas para edicion de audio e imagen
 
Tutorial extenso para crear Singstars
Tutorial extenso para crear SingstarsTutorial extenso para crear Singstars
Tutorial extenso para crear Singstars
 
Audacity
AudacityAudacity
Audacity
 

Intro Pygame Capitulo 6

  • 1. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com Programación de Juegos con PyGame Capitulo 6: Sonidos, Sprites y Animaciones 1
  • 2. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com pygame.mixer Bueno ya teniamos casi todos los Modulos y herramientas para programar juegos, la unica cosa que nos hacia falta era poder reproducir sonidos y bueno aqui es donde toma importancia este modulo, ya que su utilidad es exactamente esa, brindarnos clases y funciones para poder reproducir audio. Este módulo contiene clases para crear objetos Sound y controlar la reproducción de audio. El módulo mixer es opcional y depende de SDL_MIXER Antes de usar este módulo su programa debería verificar si el módulo pygame.mixer está disponible. El módulo mixer tiene un número limitado de canales para reproducir sonidos. Generalmente los programas le piden a pygame que comience a reproducir un sonido y pygame selecciona un canal de audio disponible de forma automática. Por defecto hay 8 canales simultáneos, aunque los programas complejos pueden obtener un control mas preciso de la cantidad de canales y utilizarlos. Toda la reproducción de sonido se realiza en segundo plano (en hilos diferentes). Cuando comienza a reproducir un objeto Sound, esta llamada retornará inmediatamente mientras el sonido continúa sonando. Un objeto Sound también se puede reproducir varias veces. También tiene un canal de streaming que se utiliza para reproducir música y se accede a él a través del módulo pygame.mixer.music. El módulo mixer se debe inicializar como los otros módulos de pygame, aunque tiene algunas condiciones adicionales. La función pygame.mixer.init() toma varios argumentos opcionales para controlar la frecuencia de reproducción. pygame colocará por defecto valores razonables, aunque no realizará conversión de frecuencias, por lo tanto mixer debería iniciarse para coincidir con la frecuencia y calidad de los recursos de audio. init Inicializar el módulo mixer para cargar y reproducir sonido. Los valores por defecto de los argumentos se pueden reemplazar utilizando atributos de audio específicos. El argumento size representa cuantos bits se usarán para cada muestra de audio. Se usarán valores de muestra con signo si se especifica un valor negativo, en otro caso se usarán muestras de audio sin signo. El argumento channels se usa para especificar cuando usar el modo estéreo y cuando el modo mono. 1 indica mono y 2 estéreo. No se permiten otros valores. El argumento buffer controla el número de muestras internas que se usarán en el mezclador de sonido. El valor por defecto debería funcionar en la mayoría de los casos. Este valor se puede reducir para disminuir la latencia, aunque podría ocurrir una pérdida de calidad en el sonido. También se puede aumentar para asegurarse que la reproducción nunca se detenga, aunque esto impone latencia. El valor de buffer debe ser potencia de dos. Algunos equipos necesitan que el módulo pygame.mixer se inicialice después de los módulos de video. El módulo de orden superior tiene precaución de esto automáticamente, pero no envía ningún argumento especial la iniciar mixer. Para resolver esto, el módulo mixer tiene una función llamada pygame.mixer.pre_init() para definir los valores por defecto antes 2
  • 3. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com de llamar a pygame.init sintaxis pygame.mixer.init(frequency=22050, size=-16, channels=2, buffer=3072): return None pre_init Define con anterioridad los argumentos de mixer.init. sintaxis: pygame.mixer.pre_init(frequency=0, size=0, channels=0, buffersize=0): return None quit Deshabilita el módulo pygame.mixer. Se detendrá toda la reproducción de audio y los objetos Sound cargados podrían ser incompatibles con el mezclador si éste se modifica luego. sintaxis: pygame.mixer.quit(): return None get_init Consulta si se ha inicializado el módulo mixer. adicionalmete retornara los argumentos con los que fue o sera inicializado, el modulo. sintaxis: pygame.mixer.get_init(): return (frequency, format, channels) stop Detiene la reproducción de todos los canales de sonido. sintaxis: pygame.mixer.stop(): return None pause Detendrá de forma temporal todas las reproducciones en los canales del mezclador activos. La reproducción de sonido se puede reanudar mas tarde llamando a la función pygame.mixer.unpause(). sintaxis: pygame.mixer.pause(): return None 3
  • 4. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com unpause Reanuda la reproducción de audio que se encuentre en pausa. sintaxis: pygame.mixer.unpause(): return None fadeout Deducirá el volumen de todos los canales de sonidos en el tiempo indicado por por el argumento milliseconds. El sonido se detendrá una vez que el volumen llegue a su menor valor. sintaxis: pygame.mixer.fadeout(time): return None set_num_channels Define el número de canales disponibles para el mezclador. El valor por defecto es 8 y depende de la cantidad de canales que soporte su placa de sonido. Puede aumentar o disminuir este valor. Se reduce este valor todos los sonidos que estén sonando en los canales a eliminar se detendrán. sintaxis: pygame.mixer.set_num_channels(count): return None get_num_channels Obtiene el número total de canales de reproducion activos. sintaxis: pygame.mixer.get_num_channels(): return count set_reserved El módulo mixer puede preservar cualquier número de canales para que no se seleccionen automáticamente al reproducir Sonidos. No se detendrán los sonidos que actualmente estén sonando en los canales reservados. Esto permite a la aplicación reservar un número específico de canales para sonidos importantes que no deberían interrumpirse y tener garantizado un canal para reproducirse. sintaxis: pygame.mixer.set_reserved(count): return None 4
  • 5. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com find_channel Encuentra y retorna un objeto Channel inactivo. Si no hay canales inactivos retornará None. Si no hay canales inactivos y el argumento foce vale True entonces encontrará el canal que tiene el sonido que mas tiempo se a reproducido y lo retornará. Si el módulo tiene canales reservados de la función pygame.mixer.set_reserved() entonces esos canales no se retornarán aquí. sintaxis: pygame.mixer.find_channel(force=False): return Channel get_busy Retorna True si el módulo está reproduciendo en alguno de los canales. Retornará False si el mezclador está libre. sintaxis: pygame.mixer.get_busy(): return bool Music El módulo music está muy relacionado con el módulo pygame.mixer. Use el módulo music para controlar la reproducción de música en el módulo mixer. La diferencia entre la reproducción de música y la reproducción de un sonido es que la música se reproduce mientras se carga, y nunca se carga completamente de una vez. El módulo mixer soporta solamente la reproducción de una música a la vez. load Cargará el archivo de música y lo preparará para reproducir. Se detendrá cualquier música si se estaba reproduciendo. Esta función no comenzará a reproducir la música. Tenga en cuenta que la música solo se puede cargar a partir del nombre de un archivo, no se puede cargar desde objetos file como las otras funciones para cargar recursos de pygame. sintaxis: pygame.mixer.music.load(filename): return None play Reproducirá la música que se ha cargado. Si la música ya estaba sonando entonces se reiniciará. El argumento loops controla el número de veces que se debe reproducir la canción. Por ejemplo, play(5) causará que la canción suene una vez y luego se repita 5 5
  • 6. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com veces; es decir, unas 6 veces. Si el argumento loop vale -1 se repetirá la reproducción indefinidamente. El argumento de posición start controla a partir de donde comenzará a reproducirse. La posición de inicio depende del formato de música utilizado. Los formatos MP3 y OGG utilizan la posición como tiempo medido en segundos. La música en formato MOD usará start como el número de patrón. Si no se puede definir la posición de inicio se lanzará la excepción NotImplementedError. sintaxis: pygame.mixer.music.play(loops=0, start=0.0): return None rewind Reinicia la reproducción de la música actual para iniciar desde el principio. sintaxis: pygame.mixer.music.rewind(): return None stop Detiene la reproducción de música si se está reproduciendo. sintaxis: pygame.mixer.music.stop(): return None pause Detiene de forma temporal la reproducción de música. Con la función pygame.mixer.music.unpause() puede continuar la reproducción. sintaxis: pygame.mixer.music.pause(): return None unpause Continúa la reproducción de una canción luego de que esta se ha pausado. sintaxis: pygame.mixer.music.unpause(): return None fadeout Detendrá la reproducción de música luego de haber reducido el volumen en el tiempo especificado (en milisegundos). 6
  • 7. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com sintaxis: pygame.mixer.music.fadeout(time): return None Nota: esta función puede bloquear el programa mientras altera el volumen. set_volume Define el volumen de la reproducción de música. El argumento value es un número entre 0.0 y 1.0. Se redefine el nivel de volumen cuando se carga una nueva música. sintaxis: pygame.mixer.music.set_volume(value): return None get_volume Obtiene el volumen de la música. Retorna el volumen actual para el mezclador. El valor debe estar entre 0.0 y 1.0. sintaxis: pygame.mixer.music.get_volume(): return value get_busy Consulta si se está reproduciendo música. sintaxis: pygame.mixer.music.get_busy(): return bool get_pos Obtiene el número de milisegundos desde que el módulo ha comenzado a reproducir música. El tiempo que se retorna solo representa cuanto tiempo a estado reproduciendo música, este valor no tiene en cuenta cualquier desplazamiento de posición inicial. sintaixs: pygame.mixer.music.get_pos(): return time queue Esta función carga un archivo de música y lo pone en una cola. Un archivo que se encuentra en la cola comenzará a sonar cuando la música actual termine normalmente. La cola de canciones se perderá si la música actual se interrumpe o intercambia. sintaxis pygame.mixer.music.queue(filename): return None 7
  • 8. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com set_endevent Esta función hace que pygame emita una señal (con ayuda de la cola de eventos) cuando el módulo termine de reproducir. El argumento determina que tipo de evento se quiere emite. El evento se emitirá cada vez que una canción termine, no solo la primera vez. Para anular la emisión de eventos llame a esta función sin argumentos. sintaxis: pygame.mixer.music.set_endevent(): return None pygame.mixer.music.set_endevent(type): return None get_endevent Obtiene el evento que un canal emite cuando termina de reproducir. sintaxis: pygame.mixer.music.get_endevent(): return type Sound Carga un nuevo sonido a partir de un nombre de archivo, un archivo de python o un objeto de almacenamiento que se pueda leer. Se realizará un ajuste limitado de frecuencia para que coincida con los argumentos de inicialización del módulo mixer. El objeto Sound representa los datos de sonido actual. Los métodos que cambian el estado del objeto de sonido lo harán en todas las instancias de ese objeto. El sonido puede cargarse desde un archivo de audio OGG o desde un archivo WAV sin compresión. sintaixs: pygame.mixer.Sound(filename): return Sound pygame.mixer.Sound(buffer): return Sound pygame.mixer.Sound(object): return Sound Nota: La memoria asignada para los datos se copiará internamente, dada de información será compartida entre el archivo y el objeto de sonido. play Comienza a reproducir el sonido en un canal disponible (por ejemplo, en los parlantes de la computadora). Se elegirá de forma forzada el canal, por lo tanto la reproducción se podría detener el sonido en curso si es necesario. El argumento loops controla cuantas veces de deberá repetir el sonido luego de haber sonado por primera vez. Un valor como 5 significa que el sonido será reproducido una vez, y luego se repetirá cinco veces mas, por lo tanto sonará seis veces en total. El valor por defecto (cero) significa que el sonido no se repetirá, y solo sonará una vez. Si loops se define a -1 el sonido se repetirá constantemente (aunque podrá llamar a stop() para detenerlo). 8
  • 9. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com El argumento maxtime se puede usar para detener la reproducción luego del numero de milisegundos indicado. El argumento fade_ms hará que el sonido comience a reproducirse desde el valor de volumen 0 y aumente de volumen hasta el máximo valor en el tiempo indicado. Note que el sonido podría termina antes de que el aumento de volumen se complete. Este método retornará un objeto Channel con el canal que ha sido seleccionado. sintaxis: Sound.play(loops=0, maxtime=0, fade_ms=0): return Channel get_num_channels Retorna el numero de canales activos donde se está reproduciendo este sonido. sintaxis: Sound.get_num_channels(): return count get_length Obtiene la longitud del sonido. Retorna la longitud del sonido en segundos. sintaxis: Sound.get_length(): return seconds get_buffer Obtiene un objeto de almacenamiento para modificar el sonido. Retorna un objeto de almacenamiento para modificar el sonido. Este objeto se puede usar para acceso directo y manipulación. sintaxis: Sound.get_buffer(): return BufferProxy stop, fadeout, set_volume, get_volume, set_volume Para no aburrirlos este metodos hacen exactamente lo mismos que los metodos de las otras clases, por lo que evitare comentarlos. Channel Retorna un objeto Channel para uno de los canales actuales. El argumento id debe ser un valor entre 0 y el valor que devuelve pygame.mixer.get_num_channels(). El objeto Channel se puede usar para obtener un control preciso sobre la reproducción 9
  • 10. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com de sonidos. Un canal solo puede reproducir un objeto Sound a la vez. Como pygame por defecto maneja por su cuenta estos objetos, utilizarlos es completamente opcional. sintaxis: pygame.mixer.Channel(id): return Channel play Comenzará a reproducir un sonido en un canal específico. Se interrumpirá cualquier sonido que esté sonando en este canal. El argumento loops tiene el mismo significado que en Sound.play(): es el número de veces que se repetirá el sonido luego de sonar la primera vez. Si vale 3, entonces el sonido se reproducirá 4 veces (la primera y luego 3 veces mas). Si loops vale -1, entonces el sonido se repetirá indefinidamente. Como en Sound.play(), el argumento maxtime se puede usar para detener la reproducción de sonido luego de un tiempo determinado (indicado en milisegundos). sintaxis: Channel.play(Sound, loops=0, maxtime=0, fade_ms=0): return None Nota: Al igual que Sound.play(), el argumento fade_ms se puede usar para alterar progresivamente el volumen de un sonido. Stop Detiene la reproducción de sonido en el canal. Luego de interrumpir la reproducción el canal quedará disponible para que nuevos sonidos puedan sonar en él. sintaxis: Channel.stop(): return None pause Detiene de forma temporal la reproducción de sonido en un canal. Este sonido se puede reanudar nuevamente mediante la función Channel.unpause(). sintaxis: Channel.pause(): return None unpause Continúa la reproducción en un canal que está en pausa. sintaxis: Channel.unpause(): return None 10
  • 11. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com fadeout Detiene la reproducción de un canal luego de reducir progresivamente el volumen de un sonido en el tiempo indicado por el argumento time (en milisegundos). sintaixs: Channel.fadeout(time): return None set_volume Define el volumen, o latencia, de un sonido. El nivel de volumen se reinicia cuando un canal comienza a reproducir nuevamente. Esta función solo afecta al sonido actual. El argument value debe ser un número entre 0.0 y 1.0 Si se pasa un solo argumento, este se interpretará como el volumen de ambos parlantes. Si se pasan dos argumento y el módulo mixer usa el modo estéreo, entonces el primer argumento será el volumen del parlante izquierdo y el segundo argumento será el volumen del parlante derecho. (Si el segundo argumento es None, entonces el primer argumento se interpretará como el volumen de ambos parlantes.) sintaxis: Channel.set_volume(value): return None Channel.set_volume(left, right): return None get_volume Retorna el volumen del canal para el sonido que es está reproduciendo. Esta función no tiene en cuenta la separación estéreo que se ha utilizado en Channel.set_volume. El objeto Sound también tiene su propio volumen que se mezcla con el del canal. sintaxis: Channel.get_volume(): return value get_busy Consulta si el canal está activo. sintaxis: Channel.get_busy(): return bool get_sound Obtiene el sonido que se está reproduciendo actualmente. Retorna el objeto Sound que se está reproduciendo en este canal. Retornará None si el canal está inactivo. sintaxis: 11
  • 12. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com Channel.get_sound(): return Sound queue Un objeto Sound comienza a reproducirse inmediatamente después de otro si se coloca en la cola de reproducción del canal. Cada canal solo puede tener un sonido en cola al mismo tiempo. El sonido en cola solo se reproducirá si el sonido actual finaliza normalmente. En otro caso, si se llama a Channel.stop() o Channel.play(), el sonido en cola se cancelará. El sonido comenzará a reproducirse inmediatamente si no hay otro sonido en curso. sintaxis: Channel.queue(Sound): return None get_queue Se retornará el sonido que esté en cola para este canal. Una vez que el sonido comienza a reproducirse ya no estará en la cola de reproducción. sintaxis: Channel.get_queue(): return Sound set_endevent Hace que el canal envíe un evento cuando la reproducción finalice. Cuando se define un evento de terminación para el canal, se enviará un evento a la cola de eventos cada vez que un sonido termine de reproducirse en este canal (no solo la primera vez). Use la función pygame.event.get() para recibir el evento de terminación una vez que halla sido enviado. Note que si ha llamado a Sound.play(n) o Channel.play(sound, n), el evento de terminación se enviará una sola vez, luego de reproducirse “n+1” veces (vea la documentación de Sound.play). Se enviará el evento de terminación inmediatamente si se llama a Channel.stop() o Channel.play() mientras el sonido está en reproducción. El argumento type indica el identificador de evento para enviar a la cola de eventos. Puede ser válido usar cualquier tipo de evento, aunque una buena elección debería ser optar por un valor entre pygame.locals.USEREVENT y pygame.locals.NUMEVENTS. sintaxis: Channel.set_endevent(): return None Channel.set_endevent(type): return None El canal dejará de enviar eventos si se llama a esta función sin argumentos. get_endevent 12
  • 13. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com Obtiene el evento que un canal emite cuando finaliza la reproducción. Retorna el tipo de evento que se enviará cada vez que el canal termina de reproducir un objeto Sound. Esta función retornará pygame.NOEVENT si el canal no tiene asignado un evento para emitir. sintaxis: Channel.get_endevent(): return type La verdad de la Milanesa :P Traducido significa lo que en verdad nos tiene que interesar si son como yo y no tienen conocimientos avanzados sobre audio pero aun asi les interesa agregar sonidos a sus juegos. En resumen, pygame.mixer nos brinda los controles generales sobre el resto de los modulos de niveles inferiores en el manejo de audio, Ademas nos da 2 posibilidadeso formas para reproducir sonidos, la primera es directa y mas sencilla utiliza el modulo pygame.mixer.music pero tiene la dificultad de que solo puede reproducir un sonido o tema a la ves, a lo sumo los diferentes sonidos se podrian ir agregando a la cola de reproducion, el unico problema es que es necesario cargar desde archivo cada ves que se quiere reproducir. Bien ahora un poco de codigo de ejemplo sobre pygame.mixer.music, pero este sera un poco interactivo para no tener que escribir demasiado. >>> import pygame >>> pygame.init() #inicializamos la mayoria de los modulos entre ellos mixer (6, 0) >>> pygame.mixer.music.load('after_in_the_dark.ogg') #al archivo lo tengo en el path de python por eso no pongo la ruta >>> pygame.mixer.music.play(2) #el tema se reproducira 3 veses >>> pygame.mixer.music.queue('nirvana_seigyo_fortnoug.ogg') #agregamos el archivo a la cola de reproducion En fin lo que hicimos fue, primero como siempre importar e inicializar pygame, con ello tanbien automaticamente logramos inicializar pygame.mixer con los parametros por defecto. Lo siguiente fue cargar un tema en OGG (por algun motivo con este metodo cuando intento cargar otra cosa que no sea un OGG como un WAV me da error, me dice que no lo puede cargar). Luego le decimos que reprodusca el tema actual, si queremos que se reprodusca 1 vez pasamos 0, si queremos que se reprodusca 2 veses pasaremos un 1 y haci sucesivamente, si quisieramos que se reprodujera el tema indefinidamente tendriamos que pasar -1 como parametro. por ultimo agregamos otro archivo a la cola de reproducion, este comenzara a reproducirse automaticamente despues de que el ultimo archivo termine de reproducirse. La segunda forma, diria la recomendada (Usar los Objectos Chanels Solo si saben como hacerlo, sino estaran apostando a su suerte :P) es reproducir los sonidos que emita nuestro juego mediante el uso de objectos Sound y dejar que pygame se encargue del manejo de de los canales osea los objectos Chanels, su manejo basico es sencillo y se crean de la siguiente manera: 13
  • 14. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com back = pygame.mixer.Sound('background.ogg') #suponer que este es el sonido de fondo sound1 = pygame.mixer.Sound('sound.wav') #sonidos para los efectos #.... otros sonido que quieran agregar Sonido de Fondo (Background) Es el sonido que se reproducira todo el tiempo para anbientizarnos con el ecenario, es el mas sencillo de implementar, al comienzo del bucle principal (antes de entrar en el) del juego solo tendrian que comenzar a reproducir indefinidamente el sonido de fondo, seria razonable que la duracion del sonido que usaremos como fondo sea dentro de todo larga. back.play(-1) #reproducir indefinidamente loop = True while lopp: screen.fill(BLANCO) .... por ende al salir de dicho bucle llamar al metodo stop() para detener su reproducion back.stop() Efectos de Sonidos Los efectos de sonido normalmente son lanzados por ejemplos cuando una pelota coliciona con la parede, aceleramos un auto, un diparo coliciona contra un tanque y por ejemplo tenemos que lanzar la animacion de una explosion junto con el sonido, en fin podemos hacer varias cosas, definer los efectos de sonido por cada objecto, cosa que no es muy logico ya que eston objectos no son unicos en el juego y tenderan a repetirse, la otra solucion es tener un mini modulo donde precargariamos todos nuestros efectos de sonidos por ejemplo en un dicionario, creariamos una sencilla funcion que reproduciria un sonido determinado por una cadena de caracteres que por ejemplo coincidiria con la clave (en el dicionario) del objecto sonido que queremos reproducir en fin algo como: SONIDOS = { 'shoot' : pygame.mixer.Sound('sonidos/shoot.wav'), 'explode' : pygame.mixer.Sound('sonidos/explocion.wav'), 'clic' : pygame.mixer.Sound('sonidos/clic.wav'), # etc... } def reproducir(tema): SONIDOS[key].play() Despues solo importariamos el mini modulo dentro del archivo donde por ejemplo definiriamos la clase que maneje a nuestro personaje, y cuando querramos reproducir un sonido determinado por ejemplo siguiendo con la explocion: #extracto de codigo de lo que podria ser una clase que maneje los objectos disparo, esto es solo para ejemplificar 14
  • 15. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com def colicion(self, target): if self.colliderect(target.rect): self.explode() #lanza la animacion de explocion self.enable = False #reproducimos el sonido reproducir("explode") Otra opcion mas elegante seria que cuando ocurra algo como esto, lancemos un evento (para algo esta pygame.event y no es un simple modulo que comente por comentar) de la siguiente forma: #creamos un evento personalizado evt = pygame.event.Event(pygame.USEREVENT, {'play':'explode'}) pygame.event.post(evt) #lo colocamos dentro de la cola Nota: En los eventos creados por el usauario podemos aceder al dicionario de parametros mediante el atributo 'dict' Luego en la secion donde normalmente leemos todos los eventos en busca de algun evento pygame.QUIT podriamos agregar unas cuantas lineas para que esta secion se encargue de reproducir todos los sonidos, osea capturar lo eventos del tipo pygame.USEREVENT y reproducir el tema definido por play: for evento in pygame.event.get(): #capturamos los eventos creados if evento.type == pygame.USEREVENT: reproducir(evento.dict['play']) elif evento.type == pygame.QUIT: loop =False pygame.sprite Bueno el ultimo modulo de pygame que veremos en este capitulo se llama pygame.sprite el cual a rasgo generales nos permite manejar grupos de objecto, y que son esos objectos que mencionamos, bueno este termino no se refiere explicitamente a la POO sino al manejo de Objectos Sprites osea todos los elementos que interactuan en nuestro juego. El uso de este modulo es opcional, particularmente no lo uso por que prefiero escribir mis propias clases para manejo de Sprites, esto no es reinventar la rueda, solo es hacer soluciones a medida. Se espera que la clase Sprite se utilice como clase base para los diferentes tipos de objetos en el juego. También hay una clase Group básica que simplemente almacena sprites. Un juego podría crear nuevos tipos de clases Group que operen sobre instancias de objetos Sprite personalizadas. La clase Sprite básica puede dibujar los sprites que contiene sobre una superficie. El método Group.draw() requiere que cada que cada Sprite tenga los atributos image y 15
  • 16. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com rect. El método Group.clear() requiere estos mismos atributos para poder borrar todos los sprites con fondo de pantalla. También hay grupos mas avanzados, por ejemplo pygame.sprite.RenderUpdates() y pygame.sprite.OrderedUpdates(). Los sprites y los grupos manejan sus relaciones con los métodos add() y remove()'. Estos métodos pueden aceptar una o varias instancias de objetos. Los inicializadores para estas clases también aceptan uno o varios objetos para insertar. Es seguro agregar y eliminar el mismo Sprite de un grupo. Mientras es posible diseñar clases de sprite y grupos que no deriven desde las clases Sprite y AbstractGroup de mas arriba, es extremadamente que herede de ellas cuando agregue una clase de grupo o sprite. Los sprites no son seguros para operar desde diferentes hilos, por lo tanto debe bloquearlos usted mismo si está usando hilos. spritecollide Encuentra sprites en el grupo que están en contacto con otro sprite. Retorna una lista que contiene todos los sprites en un grupo que están colisionando con otro sprite. La intersección se determina comparando el atributo Sprite.rect de cada sprite. El argumento dokill es un valor booleando. Si vale True todos los sprites que colisionan se eliminarán del grupo. El argumento collided es una función que se utiliza para calcular si dos sprites están en contacto, esta función debería tomar dos sprites como agumentos y retornar un valor True o False indicado si están colisionando. Si no se especifica el valor para el argumento, todos los sprites deberán tener un valor rect, que es el rectángulo del área de sprite, que se usará para calcular la colisión. Funciones de colisión: • collide_rect • collide_rect_ratio • collide_circle • collide_circle_ratio • collide_mask sintaxis: pygame.sprite.spritecollide(sprite, group, dokill, collided = None): return Sprite_list collide_rect Consulta la colisión entre dos sprites. Usa la función colliderect del módulo rect para calcular la colisión. Está diseñada para ser enviada como una función de colisión a las funciones generales de colisión. Los sprites deben tener atributos rect. sintaxis pygame.sprite.collide_rect(left, right): return bool collide_rect_ratio 16
  • 17. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com Verifica colisiones entre dos sprites usando usa versión reducida de los rectángulos de sprite. Se generan con un radio, y la instancia retornada está diseñada para ser enviada como una función de colisión a las funciones generales de colisión. El argumento ratio es un número real, 1.0 indica que será del mismo tamaño, 2.0 es el doble de grande y 0.5 es de la mitad de tamaño. sintaixis: pygame.sprite.collide_rect_ratio(ratio): return collided_callable collide_circle Verifica la colisión entre dos sprites, verificando si dos círculos centrados en los sprites están en contacto. Si el sprite tiene un atributo radius este se usará para crear en círculo, en caso de que no exista se creará un círculo lo suficientemente grande para contener todo el rectángulo del sprite indicado por el atributo rect. Esta función está diseñada para ser enviada como función de colisión a las funciones generales de colisión. Los sprites deben tener los atributos rect y radius sintaixis: pygame.sprite.collide_circle(left, right): return bool collide_circle_ratio Verifica colisiones entre dos sprites usando usa versión reducida de los círculos de sprite. Se generan con un radio, y la instancia retornada está diseñada para ser enviada como una función de colisión a las funciones generales de colisión. El argumento ratio es un número real, 1.0 indica que será del mismo tamaño, 2.0 es el doble de grande y 0.5 es de la mitad de tamaño. El objeto creado verifica la existencia de colisión entre dos sprites, comprobando si los dos círculos con centro en los sprites están en contacto luego de haberlos alterado de tamaño. Lo los sprites tienen un atributo radius este se usará para crear el círculo, en otro caso se creará un círculo lo suficientemente grande grande para contener por completo el rectángulo de sprite según su atributo rect. Está diseñada para ser enviada como función de colisión a las funciones generales de colisión. Los sprites deben tener los atributos rect y radius (este último es opcional). sintaixis: pygame.sprite.collide_circle_ratio(ratio): return collided_callable collide_mask Verifica la colisión entre dos sprites, probando si sus máscaras de bits se superponen. Si el sprite tiene un atributo mask, este atributo se usará como máscara, en otro caso se creará la máscara a partir de la imagen del sprite. Esta función está diseñada para ser enviada como función de colisión a las funciones generales de colisión. Los sprites deben tener un atributo rect y un atributo opcional de nombre mask. 17
  • 18. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com sintaixis: pygame.sprite.collide_mask(SpriteLeft, SpriteRight): return bool groupcollide Esta función encontrará intersecciones entre todos los sprites de dos grupos. Las intersecciones se determinan comparando los atributos Sprite.rect de cada Sprite. Cada sprite dentro del grupo group1 se agrega al diccionario de retorno como clave. El valor de cada elemento será una lista de los sprites del grupo group2 que colisionan con el primero. sintaixis: pygame.sprite.groupcollide(group1, group2, dokill1, dokill2): return Sprite_dict spritecollideany Consulta si el sprite dado colisiona con algún sprite en el grupo. La intersección se determina comparando el atributo Sprite.rect de cada sprite. Esta prueba de colisión puede ser mas rápida que pygame.sprite.spritecollideany() dado que tiene menos trabajo para hacer. Retornará al encontrar la primer colisión. sintaixis: pygame.sprite.spritecollideany(sprite, group): return bool Sprite Como comente arriba, pygame.sprite.Sprite es la clase base de cualquier objecto en un juego, por defecto esta clase posee 2 atributos image y rect. sobre-escribirán el método Sprite.update() y asignarán un valor a los atributos Sprite.image y Sprite.rect. El constructor puede aceptar cualquier número de objetos Group a donde se insertará el objeto. sintaxis: pygame.sprite.Sprite(*groups): return Sprite update La implementación por defecto de este método no hace nada; es solo un hueco conveniente que puede sobreescribir. Este método se llama desde Group.update() con cualquier argumento que se le envíe. sintaxis: Sprite.update(*args): #tiene que redefinirse este metodo 18
  • 19. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com add Inserta el sprite a los grupos. sintaixis: Sprite.add(*groups): return None remove Elimina un sprite de los grupos. sintaixis: Sprite.remove(*groups): return None kill Elimina el Sprite de todos los grupos. El Sprite será eliminado de todos los grupos a los que pertenezca. No se cambiará nada acerca del estado del Sprite. Es posible continuar usando el Sprite luego de haber llamado a este método, incluyendo agregarlo a otros grupos. sintaixis: Sprite.kill() return None alive Consulta si el sprite pertenece a algún grupo. sintaxis: Sprite.alive(): return bool groups Lista los grupos que contienen este sprite. sintaixis: Sprite.groups(): return group_list Group Un contenedor simple para objetos Sprite, es el mas basico de todos los grupos contenedores que posee pygame.sptrite. Se puede heredar de esta clase para crear contenedores que tengan comportamiento mas específico. El constructor toma cualquier número de sprites para agregar en el grupo. El grupo soporta las siguientes operaciones estándar de python: in, len, bool iter 19
  • 20. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com sintaixis: pygame.sprite.Group(*sprites): return Group sprites Retorna una lista con todos los sprites contenidos en el grupo. También puede obtener un iterador para el grupo, aunque no podrá iterar en el grupo mientras lo modifica. sintaixis: Group.sprites(): return sprite_list copy Duplica el grupo. crea una copia en ves de una referencia del grupo. sintaixis: Group.copy(): return Group add Agrega cualquier número de sprites a este grupo. Esta función solo agregará sprites que aún no sean miembros del grupo. sintaixis: Group.add(*sprites): return None remove Elimina cualquier número de sprites del grupo. Esta función solo elimina sprites que son miembros actuales del grupo. sintaxis: Group.remove(*sprites): return None has Consulta si un grupo contiene sprites. sintaixis: Group.has(*sprites): return None update Llama al método update()) en todos los sprites incluidos en el grupo. La clase base Sprite tiene un método update que toma cualquier número de argumentos y no hace nada. 20
  • 21. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com Los argumento que se pasan a Group.update() se pasarán a cada Sprite. sintaixis: Group.update(*args): return None draw Dibuja los sprites contenidos sobre el argumento Surface. Para ello utiliza el atributo Sprite.image para la superficie fuente y Sprite.rect para la posición. El grupo no almacena los sprites en orden, por lo tanto el orden al momento de dibujar es arbitrario. sintaixis: Group.draw(Surface): return None clear Borra los sprites usados en la última llamada a Group.draw(). La superficie destino se limpia pintando con el fondo de pantalla sobre las posición anterior del sprite. El fondo de pantalla es generalmente una Superficie que tiene las mismas dimensiones que la superficie destino. De todas formas, también puede ser un nombre de función que tome dos argumentos, la superficie destino y un area a limpia. La función background se llamará varias veces para limpiar la pantalla. sintaixis: Group.clear(Surface_dest, background): return None empty Elimina todos los sprites de este grupo. sintaixis: Group.empty(): return None Grupos Avanzados de Sprites Ademas de la clase basica Group, pygame provee un grupo de clases especificas para manejar distintos tipos de sprites, todos ellos heredan los atributos y metodos basicos que heredan de Group, estos son: GroupSingle Grupo contenedor que almacena un solo Sprite, para que sirve, es simple este es el grupo que almacenara al Heroe. Existe una propiedad especial, GroupSingle.sprite, que accede al sprite que un grupo contiene. Puede ser None cuando el grupo está vacío. Incluso 21
  • 22. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com la propiedad se puede utilizar para asignarle un sprite y que éste se almacene dentro del contenedor GroupSingle. LayeredDirty El grupo LayeredDirty está diseñado para objetos DirtySprite que es una subclase con algunas cosas mas que Sprite, osea trabaja con sprites que utilizan la tecnica de rectangulo Sucio, y es subclase de LayeredUpdates. Este grupo utiliza una técnica de marcas dirty, por lo tanto es mas rápido que los grupos pygame.sprite.RenderUpdates si usted tiene varios sprites estáticos. Además cambia automáticamente entre dos modalidades de actualización: pantalla completa o actualización dirty rectangles, por lo tanto no tendrá que preocuparse de que tendría que ser mas rápido. LayeredUpdates Grupo que pemite dibujar los Sprites mediante capas, osea se define el orden de dibujo de cada sprite usando el argumento para indicar a que capa pertenece. Si el sprite que se agrega al grupo tiene un atributo de nombre layer, entonces se utilizará ese atributo para determinar en que capa se va a agregar el sprite. Si el argumento kwarg contiene el parámetro layer entonces los sprites se agregarán a esa capa (ignorando el atributo sprite.layer). Se utilizará la capa por defecto para insertar los sprites si no se utiliza ninguna de las formas descritas mas arriba. RenderUpdates Clase de grupo que utiliza el procedimiento 'dirty rectangles'. Dibuja las imágenes de objetos Sprite y guarda información de las áreas modificadas. Dibuja todos los objetos Sprite en la superficie, al igual que Group.draw(). Aunque este método retorna una lista de áreas rectangulares de la pantalla que han sido modificadas. Los cambios devueltos incluyen áreas de la pantalla que han sido afectadas por llamadas previas a Group.clear La lista de objetos Rect devuelta se podría utilizar para llamar a pygame.display.update. Esto ayudará a mejorar el rendimiento del programa en modos de video gestionados por software. Este tipo de actualización solamente es útil en pantallas sin fondos animados. OrderedUpdates Esta clase deriva de pygame.sprite.RenderUpdates(). Mantiene el orden en que se agregaron los objetos Sprite al grupo para imprimirlos. Esto produce que agregar y eliminar objetos del grupo sea un poco mas lento que en los Grupos normales. Bueno los ejemplos de trabajo con Sprites y Grupos son sencillos, yo los dejo para que los vean mas abajo, cuando muestre el codigo de como crear animacion sencilla. 22
  • 23. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com Animacion de Sprites Esto es bastante simple, aquí aparece el concepto de frame o cuadro, que corresponde a una de las imágenes que forman la animación completa de un sprite. Podemos pensar en una secuencia de imágenes que son dibujadas rápidamente, que engañan al ojo humano dando el efecto de un movimiento fluido. Es el mismo método que se utiliza para los dibujos animados. Si alguna ves trabajaron con Flash o hicieron un gif animado creo que sabran de que estamos ablando. El número de frames dibujados en un periodo de tiempo se conoce como frame rate (tasa de frames), siendo un aspecto muy importante en la animación, ya que de esto depende la calidad de animación que obtendremos. Si cada uno de los frames se muestra muy rápido o muy lento, la ilusión del movimiento se perderá y el usuario verá cada uno de los frames como una imagen separada. Una animación muy común puede ser la de un personaje caminando, saltando, o realizando cualquier otra acción. Esto también debe ser representado de alguna forma inteligente en nuestro videojuego, utilizando algún tipo de estructura de datos adecuada, como un vector o lista. Normalmente el sprite tendrá como atributo una lista de animaciones (las acciones del personaje, enemigo, etc.), donde cada animación corresponderá a otra lista con cada uno de los frames. La totalidad de los frames que forman un personaje, suele lmacenarse en un solo archivo de imagen, a esto se le llama sprite sheet, es decir, una imagen donde tenemos secuencias de frames para las diferentes acciones que puede realizar un personaje en un videojuego. La siguiente imagen lo ilustra claramente. 23
  • 24. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com ¿Que es un Frame (Cuadro)? Durante todo este tiempo estubimos ablando de Frame Rate o Cuadros por Segundo, un Frame vendria a ser el estado de una animacion (en este caso nuestro juego) en un momento de tiempo determinado, para mayor sencilles un frame es un estado de la ecena (en este caso nuestro personaje) que es remplazada tan rapidamente que no hace parecer que tenemos un efecto de fluides en el movimento del personaje. A modo de ejemplo los frames vendrian a ser las capturas de los diferentes estados de una imagen como la de mas abajo, si los vemos por separados no tiene sentiedo, pero si los juntamos y hacemos que cambie cada determinado intervalo de tiempo lograremos un efecto de animacion en la pelota. Animacion Completa vs Animacion Limitada En el cine existe un estándar de 24 imágenes por segundo. Esa es la tasa a la que graban las cámaras y proyectan los proyectores. Se toma una fotografía de la imagen cada veinticuatroavo de segundo. En la animación, sin embargo, las imágenes no se toman sino que se producen individualmente, y por ello no tienen que cumplir necesariamente con el estándar del cine. Una película de animación tiene siempre 24 fotogramas por segundo, pero no necesariamente todos esos fotogramas muestran imágenes diferentes: en la animación, las imágenes suelen repetirse en varios fotogramas. Así pues, tenemos varias tasas de animación: • En unos: cada imagen es diferente, sin repetición. 24 imágenes por segundo, 1 imagen cada fotograma. • En doses: cada imagen se repite dos veces. 12 imágenes por segundo, 1 imagen cada 2 fotogramas. • En treses: cada imagen se repite tres veces. 8 imágenes por segundo, 1 imagen cada 3 fotogramas. Se ha calculado que el umbral visual por debajo del que ya no se capta un movimiento sino imágenes individuales es de 7 imágenes por segundo. Animación completa es cuando se anima en unos o en doses. Es el estándar de la animación estadounidense para salas de cine, principalmente las películas de Walt Disney, y 24
  • 25. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com también los largometrajes europeos. Generalmente, se animan las escenas con muchos movimientos rápidos en unos, y el resto en doses (la pérdida de calidad es imperceptible). Animación limitada es cuando se anima en una tasa inferior. El estándar del animé japonés es animación en treses. La pérdida de calidad ya es perceptible si se es observador. El concepto de animación limitada también afecta a otros aspectos diferentes de la tasa. Por ejemplo, es animación limitada cuando se repiten ciclos: pensemos en Pedro Picapiedra corriendo mientras al fondo aparecen una y otra vez las mismas casas en el mismo orden. Hay que tener en cuenta que diferentes elementos de la imagen (un personaje, otro personaje, un objeto móvil, un plano del fondo, otro plano del fondo) se animan por separado, y que por tanto dentro de la misma escena puede haber elementos con diferentes tasas de animación. Un Ejemplo Sencillo Veremos como almacenar varios cuadros de animación en un solo archivo para realizar una animación muy simple (como mencionamos arriba). Esto nos resultará de utilidad para manejar animaciones y comprender los próximos artículos. Creando los gráficos del personaje Para mostrar una animación tendremos que imprimir uno a uno varios cuadros de animación. Nos resultará de mucha utilidad almacenar cada uno de estos cuadros en un único fichero gráfico. Cuando nos queramos referir a la imagen que contiene todos los cuadros le llamaremos grilla, porque contiene varios rectángulos de igual tamaño con los cuadros de animación de nuestro personaje. Aunque no todos los cuadros y o capturas de nuestro personaje obligatoriamete tienen que tener el mismo grosor, pero al hacerlo nos evitaremos complicaciones en el codigo, bien las imagen con todos los cuadros que usaremos para este ejemplo es un poco reducida (solo unos poco cuadros). Como vemos nuestro ejemplo contendra 5 cuadros, para claridad los enumeraremos de 0 a 4 (por que de 0 a 4 y no de 1 a 5, es simple cuando animemos y hagamos desplazamiento nos sera mas sencillo). Para dibujar algunos de los cuadros necesitamos al menos conocer la siguiente información: • Cantidad total de Filas y Columnas, en nuestro caso 1, fila y 5 columnas • El ancho y alto Completo de la imagen, en este ejemplo 240x35 pixels Con estos datos ya podemos calcular el ancho y alto de cada cuadro: frame_ancho = imagen_ancho // num_filas frame_alto = imagen_alto // num_columnas 25
  • 26. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com en nuestro caso: frame_ancho = 240 // 5 # 48 frame_alto = 35 / 1 # 35 Ahora bien supongamos que queremos calcular el area a dibujar de un frame o cuadro en particular por ejemplo el frame 3 (vendria a ser el cuarto cuadro), conocemos el ancho y alto del frame solo nos falta conocer el desplazamiento vertical (en realidad en este ejemplo no hay osea es 0 ya que tenemos una sola fila) y horizontal, como todos los cuadros o frames son del mismo tamaño este calculo del desplazamiento es simple y solo tenemos que multiplicar el nro de frame actual por el ancho o alto dependiendo la situacion. frame_num = 3 #para el ejemplo dy = 0 #como dijimos en este ejemplo no tenemos desplazamiento vertical dx = frame_num * frame_ancho # 3 * 48 = 144 Con eso ya tenemos el area de recorte para mostrar en pantalla y usando el metodo surface.blit seria: area_recorte = pygame.Rect(dx, dy, frame_ancho, frame_alto) surface.blit(imagen, (x, y), area_recorte) Por ultimo hay que definir un ciclo de animacion, en nuestro ejemplo el ciclo de animacion sera el siguiente: 0,1,2,3,4,5,0,1,2,3,4,5,1,2,3.... Bien ahora veamos el codigo completo de como se veria una clase Sprite basica que represente una animacion: class SpriteAnimado(pygame.sprite.Sprite): def __init__(self, imagen, filas=1, columnas=1): pygame.sprite.Sprite.__init__(self) #grilla que contendra todos los cuadros o frames self.image = pygame.image.load(imagen) self.image.set_colorkey(MAGENTA) #como tengo pocos cuadros tengo que agregar un contador #adicional para que los cuadros no pasen tan rapido self.cont = 0 self.filas = filas self.columnas = columnas self.frame_num = 0 self.frame_ancho = self.image.get_width() / self.columnas self.frame_alto = self.image.get_height() / self.filas self.rect = pygame.Rect(0, 0, self.frame_ancho, self.frame_alto) 26
  • 27. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com def update(self, *argv): self.cont += 1 if self.cont > 10: self.frame_num += 1 self.cont = 0 if self.frame_num >= 5: self.frame_num = 0 def draw(self, surface): dx = self.frame_num * self.frame_ancho dy = 0 area_recorte = pygame.Rect(dx, dy, self.frame_ancho, self.frame_alto) surface.blit(self.image, self.rect, area_recorte) A estas alturas no creo que sea necesario explicar el resto del codigo, y como veran este ejemplo ademas nos sirvio como ejemplo de como crear una clase derivada del modulo sprite.Sprite, como veran modifique ademas el metodo draw (habran notado que a lo largo de este curso use drawn en ves de draw para el metodo que dibuja el sprite sobre la superficie, se que esta mal expresado como lo escribo, pero diria que es solo una cuestion de gustos.) en fin aca tienen una captura del ejemplo corriendo: (vease ejemplo_animacion.py) Bueno con esto doy por finalizado este Modulo de Introducion a la Programacion de Juego, mas explicitamente al sub Curso Aprender a usar PyGame, Ahora bien el curso completo no termina aquí, le sigue el segundo modulo donde ya nos dedicaremos explicitamente al tema programacion de juegos, aunque seguiremos usando pygame, el uso o no de esta librería no tendra tanta relevancia, en fin algunos de los temas que vienen en la segunda parte de este curso, aunque no os digo que los publique en ese orden: • IA (Inteligencia Artificial) Introducion a la Inteligencia Artificial aplicada a la programacion de Juegos • Scroling (Mapas compuestos por tiles) • Juegos en Red (como utilizar Sockets en nuestros juegos) 27
  • 28. Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → l2radamanthys@gmail.com • mas... Saludos, y nos vemos en la segunda parte del curso... 28