Sincronizar animación al Frame-rate

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

Sincronizar animación al Frame-rate

Notapor Metator de Arkalot » Vie Ene 02, 2009 7:20 pm

Llevo una semana y no logro solucionarlo: Quiero que si el juego corre
a 10, 40 o 100 fps una animación de movimiento se vea siempre igual,
o sea que, si la animación tiene 24 frames por segundo (la hice en
blender), y dura 2 segundos, el juego sepa determinar como mostrar las
imagenes: Si va a 12fps, que se salte frames, para que la animación
dure lo mismo, o que durante varios ciclos muestre el mismo cuadro
en caso de que valla muy rapido.

Imáginemos que tengo una animación que tiene 24 frames por cada
segundo que dura la animación:

fps_sprite = 24
duracion = 1666 # en milisegundos, o sea, en total son 40 frames
fps = 40 # El frame-rate actual del juego

Cambiar_de_cuadro_cada: fps * duracion / fps_sprite
Se supone que esto devuelve cada cuantos ciclos debemos mostrar
el siguiente cuadro de animación, pero a veces me da un flotante chico
o muy grande y no me salen las cuentas ñ_ñ, ¿alguien me ayuda?
nota- También habia pensado darle a caba animación un objeto .Clock,
el cual devuelve cuando milisegundos han pasado desde la ultima
vez que se llamo a reloj.tick(), pero me parece más complicado.
Avatar de Usuario
Metator de Arkalot
 
Mensajes: 34
Registrado: Mié Abr 23, 2008 2:17 am
Ubicación: México ñ_ñ !!

Re: Sincronizar animación al Frame-rate

Notapor hugoruscitti » Sab Ene 03, 2009 1:42 am

Saludos, por tu comentario del objeto Clock imagino que usas pygame, ¿cierto?.

Si ese es el caso te comento una forma sencilla de controlar con exactitud
la velocidad de tu juego:

Una forma sencilla, y que permite mucha exactitud, es utilizar el objeto
Clock y el retorno de su método tick. Por ejemplo, imagina que tienes
un rectángulo y quieres moverlo 50 pixels por segundo, en una
aplicación que corre a 60 cuadros por segundo (FPS):

Código: Seleccionar todo
[...] # creación del rectangulo y la pantalla principal

clock = pygame.time.Clock()

while True:                 # bucle principal.
    dt = clock.tick(60)     # solicita un rendimieto de 60 cuadros por segundo.
    dt = dt / 1000.0        # lleva 'dt' a la unidad de segundos.
                            #
                            # Por ejemplo:
                            # Si estuviera usando un contador, y a este le
                            # sumo 'dt' en cada ciclo, este contador
                            # aumentaría en 1 por cada segundo.

    rect.x += 50 * dt       # 50 es la cantidad de pixeles que queremos que
                            # avance el rectangulo. A todo calculo numérico lo
                            # deberíamos afectar con 'dt', ya que este nos
                            # asegura la velocidad constante.
   
    [...]                   # impresión y todo lo demas...


Este ejemplo muestra como aplicar un movimiento relacionando "tiempo",
"rendimiento" (fps) y "velocidad".

En el caso de tu animación los cálculos se podrían hacer en este esquema, por
ejemplo: Tú tienes una variable que indica el cuadro actual de animación,
digamos 'step', y una velocidad de animación deseada que te ha dado el
programa blender, digamos 'speed = 24'. Podrías hacer el cálculo así:

Código: Seleccionar todo
[...] # carga e inicialización.
clock = pygame.time.Clock()
step = 0                    # comienza en el cuadro 0 de animación.
speed = 24                  # velocidad de animación.

while True:                 # bucle principal.
    dt = clock.tick(50)     # solicita un rendimieto de 50 cuadros por segundo.
    dt = dt / 1000.0        # lleva 'dt' a la unidad de segundos.

    step += speed * dt
    screen.blit(frames[int(step)], x, y)     # suponiendo que 'frames' es una
                                             # lista con los cuadros de
                                             # animación, se toma el
                                             # correspondiente al cuadro
                                             # actual y se imprime.

    [...]                   # todo lo demás.


ah, por cierto, suele ser útil mostrar el rendimiento del juego en
cuadros por segundo (fps) en la barra de título de la ventana. Utiliza
esta sentencia dentro del bucle para lograrlo:

Código: Seleccionar todo
fps = str(int(clock.get_fps()))
pygame.display.set_caption("FPS:" + fps)


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

Notapor Metator de Arkalot » Sab Ene 03, 2009 9:47 pm

Perfecto, era justo lo que buscaba. El unico fallo que le vi fue
que al pausar el juego este se aceleraba, solucionado con:

Código: Seleccionar todo
if quitar_pausa:
    reloj.tick()
    continue


Así es, blender me exporta las animaciones como una secuencia
de imágenes. Intenté unirlas con pygame, pero no me va, creo que es
porque necesito de las "banderas especiales" para mezclar el valor
alfa de las imágenes al usar la función blit(), de lo contrario obtengo
un "halo" alrededor de estas, al quedar modificado el color que usaba
como colorkey :shock:. ¿hay docu sobre esas funciones? (BLEND_ADD,
BLEND_SUB, etc) ya que no encontre na de na.

-*- -*-

Aprovechando este tema, quisiera saber si alguien del foro tiene
experiencia haciendo sprites con aplicaciones 3d, ya que me da lata
el antialiasing, pues, como saben, pygame utiliza un colorkey para
la transparencia, el cual, segun unas pruebas que hice, es mucho más
rápido que usar RGBA. Pues al hacer render con antialiasing los bordes
de la imágen siempre me quedan mezclados con el fondo, causando
el "halo", mientras que al usar key o sin antialias (funciones de blender),
me queda la figura dentada, como de sierra. Nisiquiera me han ayudado
en http://www.blender.guanajuato.net
Avatar de Usuario
Metator de Arkalot
 
Mensajes: 34
Registrado: Mié Abr 23, 2008 2:17 am
Ubicación: México ñ_ñ !!

Notapor hugoruscitti » Dom Ene 04, 2009 7:02 pm

Metator de Arkalot escribió:Así es, blender me exporta las animaciones como una secuencia
de imágenes. Intenté unirlas con pygame, pero no me va, creo que es
porque necesito de las "banderas especiales" ...


¿podrías enviarnos un ejemplo de esas imagenes?, tal vez lo
podamos resolver mas fácil analizandolo gráficamente.


Metator de Arkalot escribió:Aprovechando este tema, quisiera saber si alguien del foro tiene
experiencia haciendo sprites con aplicaciones 3d, ya que me da lata
el antialiasing, pues, como saben, pygame utiliza un colorkey para
la transparencia, el cual, segun unas pruebas que hice, es mucho más
rápido que usar RGBA. Pues al hacer render con antialiasing los bordes
de la imágen siempre me quedan mezclados con el fondo, causando
el "halo", mientras que al usar key o sin antialias (funciones de blender),
me queda la figura dentada, como de sierra. Nisiquiera me han ayudado
en http://www.blender.guanajuato.net


Sí, hace varios años contruí un juego 2D con gráficos pre-construidos
(o renderizados) con un software de modelado 3D. Uno de los detalles
que nos encontramos para resolver fueron exactamente los bordes de
cada Sprite. Hay varias soluciones, aunque al menos para nosotros,
la que producía mejores resultados es conservar la transparencia
alpha de las imágenes (es decir, dejarlas en formato RGBA), pero
transformalas al formato de colores de pantalla para que se puedan
imprimir rápido. La función que puedes en pygame que logra
este resultado es "convert_alpha":

http://www.pygame.org/docs/ref/surface. ... vert_alpha

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

Notapor Metator de Arkalot » Lun Ene 05, 2009 7:27 pm

¿podrías enviarnos un ejemplo de esas imagenes?, tal vez lo
podamos resolver mas fácil analizandolo gráficamente.


Aquí esta el archivo con el que estoy haciendo las pruebas:

[url]http://www.hotlinkfiles.com/files/2190136_hqvvc/gus_walk.rar]gus_walk.rar[/url]

Antes usaba un simple bucle para adjuntar imágenes con
colorkey, haciendo blit y guardando como png, pero con las
imágenes alfa no se como podria juntar todos esos cuadros,
ya que son MUCHOS.

Probe haciendo blit sobre una superficie alfa (con bandera SCALPHA),
pero no funciono. Además no encuentro nada sobre las opciones
especiales de mezcla en pygame, no se si puedan servir de algo...
hum, ahora se me acaba de ocurrir algo, hacer un super blucle que
lea el valor exacto de cada pixel de las imágenes y lo copie en el
lugar que le corresponde en la nueva superficie, ¿que les parece...?
Avatar de Usuario
Metator de Arkalot
 
Mensajes: 34
Registrado: Mié Abr 23, 2008 2:17 am
Ubicación: México ñ_ñ !!

Notapor hugoruscitti » Mar Ene 06, 2009 7:21 pm

Metator de Arkalot escribió:Así es, blender me exporta las animaciones como una secuencia
de imágenes. Intenté unirlas con pygame, pero no me va, creo que es
porque necesito de las "banderas especiales"...



Si, exacto, si quieres crear una superficie grande para integrar todos
los cuadros de animación puede surgir algun problema: en principio
cuando generas un objeto surface con pygame.Surface((ancho, alto)), esta
imagen será completamente negra, y al imprimir sobre ella los pixeles
alfa se fundirán con el color negro y dejarán de ser transparentes.

Por ello, para construir la superficie tienes que combinar dos atributos,
que sea de 32 bits y tenga canal alfa. La siguiente sentencia construye
una superficie con canal alpha y luego pinta una de tus imágenes sobre
ella:

Código: Seleccionar todo
surface = pygame.Surface((100, 100), pygame.SRCALPHA, depth=32)

image = pygame.image.load('0001.png')
surface.blit(image, (0, 0))


Eso sí, como tu quieres imprimir todos los cuadros sobre la superficie,
primero tendrías que calcular el tamaño deseado para la superficie grande
(sumando el tamaño de todos los cuadros de animación) y luego imprimir
cada cuadro sobre la superficie.

Luego, para agilizar la velocidad de impresión es muy recomendable adaptar
la superficie al formato de la pantalla. Para adaptar la superficie tienes
que definir el modo de video y luego ejecutar esta sentencia:

Código: Seleccionar todo
surface = surface.convert_alpha()


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

Notapor Metator de Arkalot » Mar Ene 06, 2009 7:39 pm

Si, ya me funciono y todo esta perfecto. La animación es
constante y las imágenes las guardaré como PNG/RGBA.
Cuando tenga más avanzado el proyecto que estoy haciendo
lo publicaré por aquí. Por ahora estoy ocupado haciendo un
efecto de cámara para mapas extragrandes y también
implementando pathfinding... Nos vemos y Gracias :D
Avatar de Usuario
Metator de Arkalot
 
Mensajes: 34
Registrado: Mié Abr 23, 2008 2:17 am
Ubicación: México ñ_ñ !!


Volver a General

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron