SYNCronizar velocidad juego (variable FRAMES)

Software para o relacionado con el core ZX Spectrum / Software for or related to the ZX Spectrum core
Avatar de Usuario
Hark0
Mensajes: 683
Registrado: 27 Sep 2015, 00:31
Ubicación: Cornellà de Llobregat - BCN
Contactar:

SYNCronizar velocidad juego (variable FRAMES)

Mensaje por Hark0 » 01 Dic 2016, 10:48

Buenas!

No se si lo estoy haciendo como toca, pero os comento aquí a ver si alguien tiene alguna solución / alternativa para ajustar la velocidad de un juego.

Actualmente estoy haciendo lo siguiente (z88dk):

Inicio una variable para leer el contador FRAMES del sistema:

unsigned int dir_peek_FRAMES;
unsigned char reloj_A;
unsigned char reloj_B;
unsigned char reloj_diff;


Inicio más cosas y me meto en el mainloop, que contiene rutina de pintado, control teclado y lógica programa.

Antes del mainloop hago:

dir_peek_FRAMES = 23672; // Dirección variable FRAMES ZX-Spectrum
*dir_peek_FRAMES = 0; // "POKE" a esa dirección con valor 0



Inicio mainloop

reloj_A = *dir_peek_FRAMES;

// RUTINAS PROPIAS DE RENDER, CONTROL, LOGICA...

reloj_B = *dir_peek_FRAMES;

reloj_diff = reloj_B - reloj_A;

reloj_A =0;
reloj_B =0;
*dir_peek_FRAMES = 0;

Fin mainloop


Y obtengo esto que veis... me tarda 13 "FRAMES" en realizar todo el bucle, ver animación GIF:

Imagen


Vale, hasta aqui todo bien como veis... PERO... va demasiado rápido (el GIF no le hace justicia)... y el tema de añadir WAIT no me convence...

¿Alguna idea para aprovechar ese timer de cara a que todo esté sincronizado?

Espero haberme explicado, anticipadas ;)
http://www.zxuno.com
ZX-Uno · Clon de ordenador ZX Spectrum basado en FPGA.

Avatar de Usuario
jsj
Mensajes: 336
Registrado: 21 Nov 2015, 12:48

Re: SYNCronizar velocidad juego (variable FRAMES)

Mensaje por jsj » 01 Dic 2016, 11:42

Una cosilla. El "tiempo" (número de ticks de 1/50 segundo) se almacena en las direcciones 23672 a 23674. Es decir es un dato de 24 bits... de 0 a 16.777.216. Con este rango de valores cicla cada 93 horas aproximadamente.

Todo esto suponiendo el funcionamiento a 50Hz. Por tanto no sé si tal y como coges el valor de esas direcciones de memoria estás teniendo en cuenta esto. Porque si no ese cálculo de "frames" que haces puede no ser del todo correcto.

Imagino que nadie va a tener su Spectrum arrancado casi 4 días (93 horas) ya que sino tendrías que complicar el cálculo de ciclos dado que el valor de esa variable del sistema pasará de su valor máximo a 0 cada 93 horas desde que se encendió el Spectrum.

Dicho esto, y por los datos que das tu bucle principal tarda 13/50 de segundo en ejecutarse. Si estás haciendo un pintado en pantalla cada pasada del bucle no me cuadra algo ya que estaría pintando como unas 4 veces por segundo... es decir, debería verse todo a 4 FPS. Y da la sensación de que es mucho más. Por eso algo no me cuadra en el dato ese de 13 "frames". O algo se me está escapando... :?:

Avatar de Usuario
Hark0
Mensajes: 683
Registrado: 27 Sep 2015, 00:31
Ubicación: Cornellà de Llobregat - BCN
Contactar:

Re: SYNCronizar velocidad juego (variable FRAMES)

Mensaje por Hark0 » 01 Dic 2016, 13:45

Estuve mirando las 3 posiciones de memoria que "gestionan" FRAMES... como bien comentas....

La dirección 23672 es la que cambia más rápido... cuando alcanza 256, pasa a 0

y suma +1 en la dirección 23673... cuando éste alcanza 256, pasa a 0

y suma +1 en la dirección 23674


Con lo que... he pensado usar solo la 23672... inciandolo a 0 en cada bucle.

..............

¿Qué hace mi programa en el mainloop?
1. Pinta la pantalla (NO ENTERA, sólo las zonas que cambian)
2. Comprueba que haya evento en marcha (tecla pulsada o acción asignada al personaje). Si hay un evento asignado al personaje NO leo el teclado.
3. Lógica + IA del juego
4. Goto 1

Lo que pretendo es "ralentizar" el loop ya que evidentemente no tarda lo mismo en pintar 4 tiles, que pintar 30...

No se si te aclaro algo.
http://www.zxuno.com
ZX-Uno · Clon de ordenador ZX Spectrum basado en FPGA.

Avatar de Usuario
jsj
Mensajes: 336
Registrado: 21 Nov 2015, 12:48

Re: SYNCronizar velocidad juego (variable FRAMES)

Mensaje por jsj » 01 Dic 2016, 14:24

Se me ocurre que quizá puedes calcular los "frames" que tarda tu rutina de pintado, que serán variables en función de lo que tenga que pintar.

Con ese dato meter un retardo, o no, para ralentizar el bucle si va demasiado rápido. O no meterlo si la carga de pantalla a pintar es mucha.

La opción para no meter retardos o "waits" sería usar interrupciones. Y poner la rutina de pintado que sea llamada cada 1, 2, 3 interrupciones. Si tiene algo que pintar que lo pinte.

Son ideas al "azar". Que sin saber más de la lógica del juego pues puede que no te sirvan de nada.

Avatar de Usuario
jsj
Mensajes: 336
Registrado: 21 Nov 2015, 12:48

Re: SYNCronizar velocidad juego (variable FRAMES)

Mensaje por jsj » 01 Dic 2016, 14:29

Se me ocurre otra cosa. Igual el tema está en que los frames de animación son los que van rápidos.

En ese caso calcula cada cuantos 1/50 de segundo debería avanzar cada frame de animación. Por ejemplo cada 20/50. Para que la animación vaya a una velocidad constante.

Cuenta con el temporizador si se ha llegado al 50avo de segundo correspondiente y avanza el frame.

No sé si me explico.

Avatar de Usuario
Uto
Mensajes: 1394
Registrado: 17 Dic 2015, 16:39

Re: SYNCronizar velocidad juego (variable FRAMES)

Mensaje por Uto » 01 Dic 2016, 14:54

¿Estas cosas no se hacen normalmente poniendo un HALT y punto?

Quiero decir, la variable frames se actualiza cada 0,020 segundos, es decir, 50 veces por segundo, es decir, lo hace la rutina de interrupción. un HALT lo que hace es esperar a una interrupción (o reset), así el bucle sería:

1. haz tu rollo
2. halt
3. goto 1

Eso sí, "tu rollo" tiene que caber en 0,020 segundos si quieres máxima velocidad dentro de la sincronización. Si tardara 0,025 el juego iria realmente a un "tu rollo" cada 0,040 segundo, lo cual tampoco tiene por que ser malo . Es más, si a 0,040 te parece que va rapido, supongo que puede poner dos HALT.


Supongo que en Z88dk habrá algo que haga un halt, o sino se podrá hacer una funcion en assembler que tenga un halt (o incluso ponerlo inline)

Código: Seleccionar todo

ASM
{
 HALT
}
(o como se ponga)

Lo mismo me estoy pasando de listo, pero todo ese rollo de andar mirando la variable frames me parece un poco rebuscado.

Avatar de Usuario
jsj
Mensajes: 336
Registrado: 21 Nov 2015, 12:48

Re: SYNCronizar velocidad juego (variable FRAMES)

Mensaje por jsj » 01 Dic 2016, 14:59

El problema es si "tu rollo" no se puede hacer en ese 50avo de segundo. Lo cual parece ser el caso.

Avatar de Usuario
Uto
Mensajes: 1394
Registrado: 17 Dic 2015, 16:39

Re: SYNCronizar velocidad juego (variable FRAMES)

Mensaje por Uto » 01 Dic 2016, 15:04

jsj escribió:El problema es si "tu rollo" no se puede hacer en ese 50avo de segundo. Lo cual parece ser el caso.

Si, perdon que he editado para decir una cosa mientras escribias. Aun si "tu rollo" no cabe en 0,020, un HALT lo sincronizarán a 0,040 (porque una interupcion y una no, se ejecutan durante "tu rollo". Si "tu rollo" dura 0,045 entonces se ejecutará cada 0,060, y así sucesivamente, pero siempre con la mismo cadencia.

En el fondo es lo mismo que estar mirando a ver si la variable frames sube de valor, pero no se, me parece más fino :-)

Y como digo, si es que actualizar cada 0,0020 es demasiado rápido y se hace injugable, pues:

Código: Seleccionar todo

HALT
HALT
HALT
HALT
Edito: lo que sí sería un problema sería que "tu rollo" sea tan variable en tiempo que a veces dure 0,0005, a veces 0,0022, a veces 0,0049, etc. Entonces el halt no vale y hay que volver al FRAMES, pero vamos en ese caso quizá sea mejor hacerse una rutina de interrupcion propia que suba una variable propia en vez de andar tocando una variable del sistema y depender de que la actualice la ROM.

Avatar de Usuario
jsj
Mensajes: 336
Registrado: 21 Nov 2015, 12:48

Re: SYNCronizar velocidad juego (variable FRAMES)

Mensaje por jsj » 01 Dic 2016, 17:02

Es que deduzco que el caso es ese. Que "tu rollo" es de duración variable. Por lo que menciona el pintado de pantalla dura más cuantos más "tiles" o "sprites" haya que actualizar. Lógicamente.

Por tanto para obtener cadencia estable hay que medirlo y sincronizarlo de alguna forma.

Sobre usar la variable FRAMES o una rutina de interrupción propia ya no me meto. Mi Z80 está muyyyy oxidado.

Avatar de Usuario
Hark0
Mensajes: 683
Registrado: 27 Sep 2015, 00:31
Ubicación: Cornellà de Llobregat - BCN
Contactar:

Re: SYNCronizar velocidad juego (variable FRAMES)

Mensaje por Hark0 » 01 Dic 2016, 19:27

Leidos los 4 post... muchas gracias por los aportes.

El tema es el siguiente: estoy acostumbrado a usar rutinas de FPS con SDL2.

Suelo escribir el bucle, calcular los FPS... etc.

Como habeis dicho, si mis calculos, logica etc:
a) terminan antes de tiempo... añado pausas/delays para que se sincronice y espere al siguiente loop.
b) si me quedo sin tiempo... modifico/optimizo mis rutinas para que se sincronice y espere al siguiente loop.


En este caso, tengo los dos problemas a la vez:

Si pongo muchos "objetos" a pintar estoy en el caso B.
Si pongo pocos "objetos" a pintar estoy en el caso A.

En Z88DK se puede meter ASM y de hecho en el "Kit Radastan" ya existe una función para añadir HALTs....

Yo he intentado usar FRAMES, porque me parecia más correcto... y creo que es factible siempre que lo que se vaya a pintar+calcular sea más menos siempre lo mismo...

En este caso, como me gustaría añadir un editor de mapas, estoy a merced de que un usuario le de por meter hasta 176 (mapa de 16x11 tiles) objetos animados en pantalla... y en ese caso... imaginaos.
http://www.zxuno.com
ZX-Uno · Clon de ordenador ZX Spectrum basado en FPGA.

Responder