Pygame: cual es la mejor manera de hacer una animación?

Consulte acerca de programas, técnicas, algoritmos etc.

Pygame: cual es la mejor manera de hacer una animación?

Notapor endaramiz » Mié Sep 26, 2007 4:28 pm

Hola. He hecho una animación (en pygame) gracias a los consejos de Hugo (gracias!). He utilizado una lista con las imágenes a modo de cola (como indica en la documentación de python http://pyspanishdoc.sourceforge.net/tut/node7.html ) en la que la primera pasa a la ultima.
Código: Seleccionar todo
import pygame
from pygame.locals import *

def main():
   pygame.init()
   screen = pygame.display.set_mode((800,600))
   imagen1 = pygame.image.load("imagen1.png")
   imagen2 = pygame.image.load("imagen2.png")
   animacion = [imagen1, imagen1, imagen1, imagen2, imagen2, imagen2]
   imagen_rect = imagen1.get_rect()
   
   clock = pygame.time.Clock()
   while True:
      screen.fill((0,0,0))
      
      screen.blit(animacion[0], imagen_rect)
      b = animacion.pop(0)
      animacion.append(b)
      

      pygame.display.flip()
      clock.tick(30)

if __name__ == '__main__': main()


De esta manera funciona como quiero pero me preguntaba si esta es la mejor manera de hacerlo.

Saludos.
Avatar de Usuario
endaramiz
 
Mensajes: 283
Registrado: Vie Ago 31, 2007 9:25 am
Ubicación: Barcelona

Notapor hugoruscitti » Vie Sep 28, 2007 5:30 pm

Saludos; creo que está muy bien tu implementación, se puede hacer de
muchas otras formas, y es ahí donde se pone divertido compartir el código...

Te comento algunos cambios que se podrían hacer. Nota que uno generalmente
se acostumbra a hacer las cosas de "una forma" y por ello lo que sugiero
aquí puede se una mala idea... estas advertido.

- Velocidad:

Para comenzar, la función "pygame.image.load" puede generar superficies de
un formato de color diferente al de la superficie principal (o "screen" en
este caso). Eso puede traer un pequeño problema de rendimiento a la hora
de ejecutar el juego a mucha velocidad; dado que cuando la función "blit"
recibe dos superficies de distintos formatos de color debe realizar una
conversión "al vuelo" (sin avisar). Esa "conversión" demora muy poco
tiempo, pero se realiza cada vez que haces "blit", por lo tanto si tienes
un juego que imprime muchas veces en pantalla se puede poner bastante lento.

La solución es simple, utiliza el método "convert" luego de cargar una
imagen con "load", por ejemplo:

Código: Seleccionar todo
imagen1 = pygame.image.load("imagen1.png").convert()


o si quieres hacerlo en dos pasos puedes escribir:

Código: Seleccionar todo
imagen_original = pygame.image.load("imagen1.png")
imagen1 = imagen_original.convert()


el método "convert" procura convertir la superficie a un formato de color
optimizado para imprimir rápidamente. Así, el método "blit" la tiene mas
fácil, no necesitará convertir nada antes de imprimir sobre la pantalla
u otras superficies. La conversión del formato de color se realiza una
sola vez: al momento de invocar al método "convert".

Si la imagen original (.png) tiene "canal alpha" (píxeles transparentes
en el archivo original), deberías utilizar el método "convert_alpha" en
lugar de "convert", de otra forma pierdes la transparencia original.

- lista de imagenes:

Aquí estoy en duda, creo que la lista que utilizas se puede reducir a
dos elementos. Pero de esa forma la animación "correrá" a mayor velocidad.

La lista del código anterior es:

Código: Seleccionar todo
animacion = [imagen1, imagen1, imagen1, imagen2, imagen2, imagen2]


entonces, ¿que se puede hacer?. Al menos yo tengo como costumbre utilizar
variables auxiliares como contador, de esa forma puedo alterar la
velocidad de las animaciones y conocer el cuadro de animación actual. Para
realizar una animación tal vez habría hecho algo así:

Código: Seleccionar todo
animacion = [imagen1, imagen2, imagen3]
cuadro = 0
max_cuadro = len(animacion) - 1

while True:
    cuadro += 1

    if cuadro > max_cuadro:
        cuadro = 0
   
    screen.blit(animacion[cuadro], (0, 0))

    # flip y/o restauración del fondo.


En este caso la variable "cuadro" adquiere valores como 0, 1, 2, 0, 1, 2 ...
representando el cuadro de animación que se debe imprimir en pantalla.

Si quieres alterar la velocidad de la animación puedes hacer dos cosas:

1 - cambiar el argumento del método "tick" (al final del bucle). Ahora indica
30, lo que significa que el juego funcionará a 30 cuadros por segundo. Puedes
colocar valores mas pequeños para que funcione mas lento o valores mas grandes
para lograr mayor rapidez.

2 - puedes colocar otra variable adicional, que indique la demora de la
animación. Esto es útil si quieres que la animación del personaje sea lenta
pero sus movimientos (generalmente un cambio de posición) funcionen muy
rápido. La idea es similar a la del código anterior, solo que ahora debes
evitar aumentar el valora de la variable "cuadro" algunas veces:

Código: Seleccionar todo
animacion = [imagen1, imagen2, imagen3]
cuadro = 0
max_cuadro = len(animacion) - 1
tiempo_demora = 5
delay = 0

while True:

    if delay < 0:
        cuadro += 1
        delay = tiempo_demora
    else:
        delay -= 1

    if cuadro > max_cuadro:
        cuadro = 0
   
    screen.blit(animacion[cuadro], (0, 0))

    # flip y/o restauración del fondo.


Ahora "delay" junto con la variable "tiempo_demora" hacen que la variable
"cuadro" avance de 0 a 2 a menor velocidad. Estos son los valores que
produce "0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1...." (tal vez me faltó un 0).



Ahora bien, creo que no contesté tu pregunta, hacer la cosas como sugiero mas
arriba no parecen muy elegantes, uso muchas variables auxiliares y queda poco
claro como funciona cada una... suelo hacer cosas mediante contadores todo
el tiempo y ahora que lo veo con atención creo que lo hago por costumbre
y no por considerarlo "la mejor forma de hacerlo"... me has dejado pensando...


Saludos.
Avatar de Usuario
hugoruscitti
Site Admin
 
Mensajes: 1242
Registrado: Dom Jul 30, 2006 3:57 am
Ubicación: Buenos Aires, Argentina

Notapor endaramiz » Mié Oct 24, 2007 7:55 pm

Gracias Hugo! Se que lo he escrito con muchos días de retraso pero es que lo leí y se me fue de la cabeza. Aunque sea tarde con el tiempo que te tomas en enseñar, esto es lo mínimo que puedo hacer.

Es cierto que en tu código se utilizan mas variables pero creo que de este modo luego se pueden hacer cambios mas fácilmente. Por ejemplo el control del tiempo de demora que solo hace falta cambiar el valor de la variable y del otro modo habría que ir añadiendo imágenes a la lista. Supongo que dependiendo del caso una sera mas útil que la otra.

Me alegro de haberte hecho pensar, al fin y al cabo esa es una de las utilidades de los foros. :D

Saludos.
Avatar de Usuario
endaramiz
 
Mensajes: 283
Registrado: Vie Ago 31, 2007 9:25 am
Ubicación: Barcelona


Volver a General

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados

cron