Obtener el tiempo en milisegundos?

Started by KeiDash, November 03, 2017, 06:48:30 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

KeiDash

Hola a todos,

Estoy trabajando en una parte de código en la que se deben ejecutan procesos cada "x milisegundos". Entre estos milisegundos, el código no debe detenerse, es decir, no es un Wait al uso, es simplemente un contador de milisegundos mientras van ocurriendo otras cosas.

He estado mirando la documentación oficial y veo que disponemos de la función time(), que devuelve el tiempo en segundos (según la documentación oficial es así) y la variable timer. No logro entender correctamente como funciona timer y no se si me podría ayudar realmente para lo que quiero.

¿Alguien me podría aclarar este asunto a ver si puedo obtener el tiempo debidamente en milisegundos? :D

Gracias,

Futu-block

¿Seguro que quieres usar tiempo real? lo digo porque al principio me pasaba como a ti, venía del game maker donde le metía una variable de tiempo y a cada cierto tiempo pasaba algo en cuestión. Como al fin y al cabo (en ese tiempo) habia que picar codigo me pasé a bennu, hice la misma pregunta que tu (mas o menos) y me aconsejaron que usara un contador. No se si sabes como vá pero te lo explico una mijita

Despues del loop pones la variable a sumar:
var_tiempo ++;
luego cuando llegue a la cantidad deseada ejecuta la acción indicada, incluso reiniciarlo si quieres

Lo digo mas que ná por si hay algun pequeño fallo, el programa se regirá por el tiempo y puede que te dé un salto tremendo, de esta forma, con el contador, si hay algun fallo no habrá salto sino relentización del programa.


gecko

Con la struct global timer podés averiguar el tiempo que pasó en centésimas de segundo.

Lo de programar en base al tiempo es algo un poco complicado ya que no hay garantias en cuanto a que tu codigo se va a ejecutar tan rapido, o exactamente tan rapido como vos querés.

Lo que tenes que pensar es que las condiciones en lugar de ser "pasaron x milisegundos" deberian ser algo del estilo "pasaron al menos x milisegundos, pero pueden ser muchos más" y ese muchos mas depende de cosas externas que uno no tiene control (recursos del sistema, carga del sistema, sistema operativo, etc etc etc...). Y bueno, pensando las cosas de esta forma que te digo, queda en vos hacer los chequeos o cuestion que hagan falta para lograr lo que querés.

Usando la variable timer, podes medir el tiempo que haya pasado desde algun evento. Esto es pseudocodigo, pero deberia ser algo así:

timer[0] = 0; // punto inicial en el tiempo, reinicio el contador
loop
if ( timer[0] >= 1000 ) // la condicion no deberia ser nunca con ==
ejecutar_cada_segundo();
timer[0] = 0;
end
end
Torres Baldi Studio
http://torresbaldi.com

KeiDash

Quote from: Futu-block on November 03, 2017, 07:57:44 PM
¿Seguro que quieres usar tiempo real? lo digo porque al principio me pasaba como a ti, venía del game maker donde le metía una variable de tiempo y a cada cierto tiempo pasaba algo en cuestión. Como al fin y al cabo (en ese tiempo) habia que picar codigo me pasé a bennu, hice la misma pregunta que tu (mas o menos) y me aconsejaron que usara un contador. No se si sabes como vá pero te lo explico una mijita

Despues del loop pones la variable a sumar:
var_tiempo ++;
luego cuando llegue a la cantidad deseada ejecuta la acción indicada, incluso reiniciarlo si quieres

Lo digo mas que ná por si hay algun pequeño fallo, el programa se regirá por el tiempo y puede que te dé un salto tremendo, de esta forma, con el contador, si hay algun fallo no habrá salto sino relentización del programa.

Gracias por las respuestas chicos.

Con el tema de usar un bucle y un contador no lo veo del todo (quizás por mi conocimiento), por el siguiente hecho:

Quote"¿Y si el proceso donde se está ejecutando el bucle que hace el contador  se bloquea por unos segundos por sobrecarga en el procesador y el contador también se realentiza?"

Y otra cosa

Quote¿Cómo se en ciclos de un bucle y contadores a cuánto tiempo equivale?
Los procesos no se ejecutan nunca al mismo segundo, puede existir alguna diferencia mínima que haga que la cantidad de tiempo ya no sea igual.

No estoy echando atrás tu idea, es que no se como equiparar el tiempo a contadores de un bucle y limitar "el tiempo" en ciclos de un bucle, cuando un bucle puede que no siempre se ejecute a la misma velocidad ¿O sí?


Quote from: gecko on November 03, 2017, 08:23:18 PM
Con la struct global timer podés averiguar el tiempo que pasó en centésimas de segundo.

Lo de programar en base al tiempo es algo un poco complicado ya que no hay garantias en cuanto a que tu codigo se va a ejecutar tan rapido, o exactamente tan rapido como vos querés.

Lo que tenes que pensar es que las condiciones en lugar de ser "pasaron x milisegundos" deberian ser algo del estilo "pasaron al menos x milisegundos, pero pueden ser muchos más" y ese muchos mas depende de cosas externas que uno no tiene control (recursos del sistema, carga del sistema, sistema operativo, etc etc etc...). Y bueno, pensando las cosas de esta forma que te digo, queda en vos hacer los chequeos o cuestion que hagan falta para lograr lo que querés.

Usando la variable timer, podes medir el tiempo que haya pasado desde algun evento. Esto es pseudocodigo, pero deberia ser algo así:

timer[0] = 0; // punto inicial en el tiempo, reinicio el contador
loop
if ( timer[0] >= 1000 ) // la condicion no deberia ser nunca con ==
ejecutar_cada_segundo();
timer[0] = 0;
end
end


Entiendo lo que me dices pero, entonces si quiero ejecutar 2 procesos que deben ejecutarse entre ellos con una diferencia de 1'02 segundos ¿Cúal es la mejor vía?

SplinterGU

si lo que buscas es precision de ejecucion exacta cada X milisegundos, no podras hacerlo en bennugd.

los procesos no son hilos/threads como tales, son simulados, asi si ejecutas un frame, para la siguiente ejecucion tienes que esperar que todos los demas procesos se ejecuten, y tambien el render de video y demas callbacks del motor.

si no tienes frame en la funcion/proceso, los otros procesos no se ejecutaran hasta que tu proceso ejecute un frame.

o sea, que si tu programa es lo suficientemente rapido, con ningun proceso que consuma mucho y ejecutandose en un equipo lo suficientemente rapido, podrias obtener lo que quieres, pero nadie puede asegurarte un heartbeat de X milisegundos

sin mencionar la granularidad de los timers del sistema operativo.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

panreyes

También tienes que tener en cuenta el retraso mínimo entre la ejecución de un frame y del siguiente.

Por ejemplo, a 60fps tienes un retraso mínimo de 16,66 ms entre cada ejecución (o frame) del engine.

Esto es menos problemático en un motor que no dependa de un número de frames fijo (si alcanzara 120fps, el retraso mínimo sería de 8ms) o que se ejecute de una forma que no dependa de los frames en pantalla (por ejemplo, 120 "ticks" del engine, 60 frames en pantalla).

KeiDash

Puesss...me habéis dejado como quien dice "con el culo torcido" xDDDD

La cosa es que estoy implementando un juego tipo dance dance revolution en donde las teclas hay que pulsarlas al ritmo de la música..

¿Alguna idea para lo que es el proceso de que las teclas aparezcan al ritmo de la música?

FreeYourMind

primero define la base, como resolucion y fps, despues create un reloj en pantalla y haz pruebas de rendimiento en varias maquinas con la musica/video rulando, si ves que todo marcha bien ya podrias empezar a mapear en el tiempo las teclas a pulsar

Futu-block

Si, es muy buena idea, primero de trabajar bien con el motor y luego ''decorarlo

Quote from: KeiDash on November 03, 2017, 08:30:30 PM
Quote"¿Y si el proceso donde se está ejecutando el bucle que hace el contador  se bloquea por unos segundos por sobrecarga en el procesador y el contador también se realentiza?"

Es igual que una cinta de casete en un valkman con las pilas gastadas, la canción sigue sonando exactamente igual pero mas lento, ya tendra pilas nuevas y oirá a su ritmo

Quote from: KeiDash on November 03, 2017, 08:30:30 PM
Y otra cosa

Quote¿Cómo se en ciclos de un bucle y contadores a cuánto tiempo equivale?
Los procesos no se ejecutan nunca al mismo segundo, puede existir alguna diferencia mínima que haga que la cantidad de tiempo ya no sea igual.

Si pones un contador que se actualice cada frame (var_contador++; ) en ( set_fps(60,0); ) cada vez que la variable llegue a 60 pasará un segundo, igual te puedes guiar por eso, si sincronizas varios procesos con estas dos cosas, ya lo tienes

KeiDash

Pues chicos sinceramente muchas gracias por la ayuda, me habéis ayudado mucho.

Lo que haré será probar primero rendimiento a ver que tal y en base a eso pues veré como lo hago. Digo yo, que si el rendimiento es bueno en el juego, el uso de timer[0] o como dice Futu, usar cada frame (var_contador++; ) en ( set_fps(60,0); ) , debería ir medianamente bien ¿No?

Intetaré ir por ahí a ver, ya os iré comentado que tal va el avance!

Gracias chicos

gecko

Para hacer lo de la detección de pulsaciones se me ocurre que podrías hacer las preguntas con un rango de tiempo. En lugar de preguntar si pasaron "x milisegundos" deberías preguntar si el tiempo actual está entre "x e y milisegundos".

Y suponiendo que tu juego va a ir "a lo máximo" en 60 fps, sabes que el rango mínimo que deberías ponerle a una pulsación son 17ms, y mientras mas largo sea el rango de la pulsación, más jugable va a ser tu juego con maquinas en donde no llegue a los 60 fps.

Que no te asusten las respuestas, es algo que (a grandes rasgos) se puede hacer, pero no es tan fácil como uno lo imagina a simple vista.
Torres Baldi Studio
http://torresbaldi.com

KeiDash

Se puede controlar el rango de pulsación?

Drumpi

Te respondo en mi experiencia que usar timer en Bennu nunca es buena idea, y sin embargo, es imprescindible en otros lenguajes.

Antes de explicarte nada, te digo que en este foro hay gente partidaria de "timer", y gente de contadores. Cada uno tiene sus razones, pero yo soy de contadores.
Hace tiempo implementé un reloj de tiempo real en un jueguecillo llamado Liquid Counter (aun está para Wiz) usando los timer. Básicamente era una variable que sumaba el valor de timer(0) a cada frame (lo siento, no puedo poner corchetes sin que el foro se vuelva loco). Tras unos minutos vi que se retrasaba :S
Luego le metí un contador, y no es que sea exacto, pero apenas se desfasa algún segundo después de un día entero (y se refresca cada vez que arranca el juego).

El problema de los timers es que te dan el tiempo en milisegundos, pero nunca te dan el mismo valor. Por eso, tienes que trabajar con rangos de tiempo, y complican el tema matemático.
La pega de los contadores es, como bien preguntas, si el juego se ralentiza en algún momento, porque entonces el tiempo también lo hace. Pero yo lo prefiero así, porque el juego está sincronizado en todo momento, incluso las entradas de teclado (imagina que el juego se ralentiza y aunque pulses la tecla a tiempo, su respuesta se retrasa porque el código se ha "pausado" y hace las comprobaciones después de tiempo). Es más: imagina que estás jugando a Out Run, el juego se ralentiza porque hay muchos coches en pantalla o porque tienes el antivirus funcionando, pero el reloj es en tiempo real: significa que juegas con un coche más lento que el que fue programado.

Además, sabes que el tiempo que pasa es 1000ms/FPS (o sea, a 50FPS, cada frame son 20ms) con un margen de error inferior al 0'1%

Para un DDR, usar contadores es suficiente. Si habláramos de un FZero o algo de carreras o de velocidad... probablemente te diría lo mismo, y que calcules el momento exacto de cruzar la meta, usando la distancia de más recorrida tras la meta, y la velocidad del vehículo :D

Sin embargo, si trabajas con Unity, el uso del reloj del sistema es obligatorio, ya que los frames por segundo tienen un significado diferente: mientras Bennu trata de mantener una tasa de frames constantes (incluso metiendo tiempos muertos entre medias), y mantiene todos los procesos sincronizados en base a esa tasa de tiempos constantes, Unity intenta ir tan rápido como puede, y es el resto del sistema el que determina la velocidad de ejecución real. El tema de ejecutar "procesos" se hace de forma similar en ambos lenguajes (todos deben ejecutarse antes de pasar al siguiente frame... salvo las físicas en Unity, que van por su cuenta) pero es el tempo el que cambia.
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

SplinterGU

Quote from: KeiDash on November 04, 2017, 10:27:07 AM
Puesss...me habéis dejado como quien dice "con el culo torcido" xDDDD

La cosa es que estoy implementando un juego tipo dance dance revolution en donde las teclas hay que pulsarlas al ritmo de la música..

¿Alguna idea para lo que es el proceso de que las teclas aparezcan al ritmo de la música?

pense que estabas implementando algo que requeria cuestionar algun dispositivo o algo cada X milisegundos... un dance no necesita demasiada precision... no creo que requiera granularidad de 10ms u 8ms... creo que te da tela tranquilamente...

ahora, con respecto a timers... timers, tu lo seteas a 0 y el sistema en cada frame va actualizandolos, segun pase el tiempo.

lo que sugiero es usar get_timer(), que es similar a time(), pero en milisegundos.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

panreyes

Pues yo vengo a contradeciros a todos y recomendarle que use timer.

En caso de que las FPS no sean estables, con timer no tendrá problemas pero con los contadores sí, teniendo en cuenta que la música no parará.