nada, no me aguanto y tenia que compartirlo ya con uds porque estoy RE emocionado.
El otro día en la ducha tuve una iluminacion y me puse como idiota a anotar todo en papel antes de que se me olvide, y este fin de semana pude implementarlo.
Estaba pensando en lo choto que es tener que setear FPS fijos en Bennu para nuestros juegos, porque tiene dos desventajas grandes. En maquinas lerdas, los juegos se alerdan, lo que nos obliga a usar FPS bajos, pero no podemos aprovechar la potencia de las maquinas grandes que pueden mostrar mas. Sin decir lo feo que se ven los juegos a 25/30 FPS. Este es un problema que tenemos en Anarkade, ya que al ser un juego competitivo, necesitamos que se vea lo mas fluido posible.
Bueno, como les decía, me estaba duchando mientras pensaba en esto, y se me ocurrió que de la misma forma que 3D Studio te calculaba los frames intermedios de una animacion, y nosotros solo necesitamos definir los Key Frames, podemos considerar los frames de nuestro juego como Key Frames, y tener una funcion en bennu que nos calcule cuantos frames intermedios la maquina puede agregar, y renderizarlos!
Y bueno acabo de implementarlo en anarkade y va de lujo!! pronto mas noticias!
Muchas ganas de verlo en acción Javis, suena mágico :)
A los demás: Le comenté por Twitter si era algo parecido al delta time de Unity, pero me ha dicho que no es necesario modificar el juego, simplemente una función que se encargará de hacer las interpolaciones...
exactamente, estoy preparando el código ahora para compartirlo, quiero hacerlo hoy porque en la semana se complica por el trabajo.
Pronto mas novedades!
Bueno, acabo de subirlo al Repo: https://bitbucket.org/pixelatom/bennu_framework/src/11b35d5cc5a2a90a7bff81b22ad0783810ff325b/library/dynamic_fps.inc?at=master&fileviewer=file-view-default
se usa así:
* se bajan el framework (ponen la carpeta library afuera de la de su juego)
* incluyen include "../library/dynamic_fps.inc";
* reemplazan set_fps() con dynamic_fps()
//set_fps(30,0); // vamos a usar frames dinamicos! :D
dynamic_fps(30);
Eso es todo!! :D
Consideraciones:
* esta en desarrollo y hay cosas por resolver y tunear
* dynamic_fps es un proceso, se puede matar con señales FORCE o con let_me_alone(), asi que si usan este ultimo, recomiendo usar signal(ALL_PROCESS ,S_KILL); en su lugar
* avisen como les va!
Impresionante :|
Lo he probado con el propio eXplosive Dinosaurs (sobre PixTudio y aceleración GPU), que es un proyecto bastante gordo y que podría dar infinitos problemas, y he podido comprobar que funciona a la más absoluta perfección! :O
Lo único que he tenido que hacer es limitar el número máximo de FPS, ya que se iba a 3000 y dynamic_fps no funcionaba como debería.
Y ya digo que es notable, no es simplemente el numerito de FPS: lo he probado en un monitor de 144hz y se ve una mejora en la fluidez de los movimientos.
¡Alucinante! :D Enhorabuena, ¡gran trabajo!
(http://forum.bennugd.org/index.php?action=dlattach;topic=4729.0;attach=4117)
Si, me imagino que hay algún bug que otro, he subido todo muy rapido sin probar bien jaja, ahora toca revisar tranquilo!
No entendí nada xD, conozco 3ds y he releido el post 2 veces pero sigo sin entender a la práctica para que sirve. Un ejemplo sería de agradecer :D
Ok! En la semana voy a subir un ejemplo más evidente, después de solucionar un par de detalles que me quedan. :)
Quote from: Arcontus on August 26, 2018, 09:04:09 PM
No entendí nada xD, conozco 3ds y he releido el post 2 veces pero sigo sin entender a la práctica para que sirve. Un ejemplo sería de agradecer :D
Yo te explico. Olvida 3ds, planteamos un ejemplo de un juego en Bennu:
Tienes un personaje en pantalla que si pulsas las flechas se mueve 10 píxeles por imagen a 30fps, 300 píxeles por segundo.
Si cambiases el set_fps de 30 a 60fps, la velocidad del movimiento sería 600 píxeles por segundo y avanzaría mucho más rápido, ¿no?
Pues con esta función, y sin cambiar nada más del código, podrás hacer que el juego funcione a 60 imágenes por segundo sin avanzar mucho más rápidamente.
Lo que hace esta función es guardar información sobre la posición anterior del proceso, la posición actual y añade un frame interpolado.
Dicho de otra forma que se entenderá mejor: el personaje se moverá 5 píxeles por imagen a 60fps, 300 píxeles por segundo, sin que tú tengas que modificar tu código porque la función de dynamic_fps se encarga de hacer ese intervalo automáticamente (sólo a efectos de visualización, eso sí).
Acabo de subir un ejemplo en donde se ve muy evidente el efecto del dynamic_fps:
Tan solo clonen el repositorio y prueben el siguiente archivo: https://bitbucket.org/pixelatom/bennu_framework/src/5d4592efeb2fc55e20543525d697748d28a7be16/test_hardness/basics.prg?at=master&fileviewer=file-view-default (https://bitbucket.org/pixelatom/bennu_framework/src/5d4592efeb2fc55e20543525d697748d28a7be16/test_hardness/basics.prg?at=master&fileviewer=file-view-default)
Como veran, el ejemplo está diseñado para andar a 5 FPS, pero tiene comentado set_fps:
//set_fps(5,0);
dynamic_fps(5);
si descomentan set_fps y comentan dynamic_fps, van a ver como tiene que andar el juego originalmente con frames fijos, y van a ver como funcionan los frames intermedios agregados por la libreria
:) cuentenme que les parece!
Edit: de paso le dan una ojeada al motor de durezas que usamos en anarkade ;)
Holas :)
Yo también he hecho un ejemplo:
https://www.dropbox.com/sh/exzfn7w7hkaz2ml/AABfSFWQ8xaeQDKEz5fNCMQra?dl=0
Vídeo en funcionamiento: https://youtu.be/MHFl3MHOsbw
Un nave programada a 5fps, interpolada a 60fps :)
Este es el código:
include "..\..\common-src\fenix.h";
include "../library/dynamic_fps.inc";
Private
id_txt;
Begin
full_screen=1;
set_mode(1280,720);
fpg_load("general.fpg");
set_fps(5,0);
write(0,0,40,0,"Press SPACE to change between SET_FPS and DYNAMIC_FPS.");
id_txt=write(0,0,80,0,"SET_FPS");
write_int(0,0,0,0,&fps);
loop
if(not exists(type texto)) texto(); end
if(key(_space))
delete_text(id_txt);
if(id_dynamic_fps==0)
dynamic_fps(5,60);
id_txt=write(0,0,80,0,"DYNAMIC_FPS");
else
id_dynamic_fps=0;
set_fps(5,0);
id_txt=write(0,0,80,0,"SET_FPS");
end
while(key(_space)) frame; end
end
frame;
end
End
Process texto();
Begin
graph=1;
y=300;
angle=-90000;
while(x<1100) x+=60; frame; end
End
Genial! Ese ejemplo es mucho más simple! Gracias!
¡¡Es una pasada!!
no veo el sentido, es lo mismo que usar skip, solo que consume mas proceso de la VM, hay mas logica, y esa logica demora un poco mas... y no solo eso, sino que el motor interamente no solo tiene en cuenta cuando la CPU va mas rapido, sino que tambien cuando la CPU no le da y va mas lento... con set_fps(0,0), vas a dibujar todos los frames, con skip, salta frames cuando no alcanza.
perdon por ser pesimista.
quiero aclarar, skip en el set_fps, no obliga a skipear frames, sino es el valor maximo que frames que puede skipear... si no necesita skipear no skipea.
El problema de skip es que no solo se skipea renderizado si no también la lógica de los frames, lo que puede ser bastante problemático
Quote from: JaViS on August 31, 2018, 02:06:30 AM
El problema de skip es que no solo se skipea renderizado si no también la lógica de los frames, lo que puede ser bastante problemático
no, no, no, no, no.... la logica de los frames no se skipea... seria una locura! si skipeara logica se iria todo al carajo... solo se skipea visualmente...
no, no...
Chan! Que raro en las pruebas que había hecho me había dado esa impresión!
Voy a volver a probar!
el skip solo salta el render... los procesos se ejecutan en cada uno de los frames... si pones set_fps(60,10), puede llegar a dibujar 6 frames (si es una cpu lenta), pero los procesos se ejecutaran 60 veces... si o si...
De todas formas, dynamic_fps y el frameskip de Bennu no es exactamente lo mismo.
En el caso del Anarkade de Javis, un juego programado a 30fps que no pide muchos recursos y que puede funcionar bien hasta en una Raspberry Pi, si en vez de este invento usase un set_fps(300,280), el juego iría bien en las plataformas potentes que puedan soportar la lógica a 300fps (PC y poco más), pero no funcionaría en Raspberry PI o en Android, por ejemplo.
Si, ciertamente son dos approach diferentes, con skip tenes un máximo posible de FPS y de ahí para abajo, y con este método, la cantidad no está limitada para arriba, pero tenés un mínimo.
Una cosa que noté que me llamó la atención, es que mismo sin los cuadros intermedios, agregando frames El juego se notaba mucho más fluodo, todavía no entiendo por qué.
Quote from: JaViS on August 31, 2018, 12:33:01 PM
Una cosa que noté que me llamó la atención, es que mismo sin los cuadros intermedios, agregando frames El juego se notaba mucho más fluodo, todavía no entiendo por qué.
Yo también lo he notado con eXplosive Dinosaurs en PixTudio. Debe haber algún bug en el código de limitación de FPS :\
Si, es notable, por ejemplo, en mi PC tengo un monitor a 60 fps y el juego da la impresion que salta frames, incluso cuando está diseñado a andar a 30, y tengo activado VSYNC.
Ahora agregando frames (pero no posiciones intermedias) con la libreria, este problema desaparece, y el juego anda mucho mas fluido.
Que puede estar pasando?
Ni idea, pero si te apetece investigarlo... :)
https://sourceforge.net/p/bennugd/code/HEAD/tree/modules/librender/g_frame.c
lo ideal es usar el skip adecuado...
Quote from: SplinterGU on August 31, 2018, 02:29:30 PM
lo ideal es usar el skip adecuado...
Lo siento Splinter, pero de verdad no lo estás entendiendo :)
Quote from: SplinterGU on August 31, 2018, 02:29:30 PM
lo ideal es usar el skip adecuado...
No no, sacando el skip de lado. Mi Desktop es capaz de renderizar muchos mas frames que los 30 originales, y sin embargo, el juego no se ve fluido.
Cuando agrego frames extras, 60 por ejemplo, sin agregar las posiciones intermedias, lo que quiere decir que estoy repitiendo los frames, el juego se ve como originalmente debería, en mi opinión, ya que 30 frames son lo suficientemente fluidos.
Cuando no agrego los frames, está ocurriendo algo que evita que los 30 sean mostrados con fluides, o enteros, no se como explicarlo bien, pero es evidente al verlo, el juego da 'saltos'
Respecto al Skip FPS, suscribo en que se calculan todos los frames y se pintan "los que se pueden", pero yo también observo "saltos" a intervalos más o menos regulares. Personalmente lo había achacado a otros procesos que pudiera estar utilizando mi PC, pero este sintoma lo he observado también en otros PC' por lo que no se que pensar...
Un saludo!
Otra cosa que estoy pensando es que sería ideal sería que esta función no corra en un proceso del plano del programador para que precisamente no le afecten kills ni let_me_alone. No tengo ni idea de si esto es factible o no, pero molaría un montón.
Esta hecho para que no le afecten los skill. Solo las señales force las afectan.
El problema de skill y let_me_alone para cosas como ésta, lo he resuelto con una local llamada "unkillable" y una let_me_alone a medida, que sólo elimine los procesos que tengan unkillable a 0. Aparte de que luego utilizo otra local, llamada action, en la que casi siempre el -1 significa que el proceso debe cerrarse por sí mismo.
Panreyes, Muy bien pensado, la verdad.Javis, bien que no le afecten los kill, pero molaría más que funcionara como el setfps(), independiente a los procesos, aun que entiendo que si esto fuera fácil de hacer ya lo habrías hecho.
pues si, queria comentarles que sigo trabajando en la funcion y pronto habrá mas novedades :)
Hola a todos:
Sí, hace tiempo que no me paso por aquí ^^U Pero ya lo comenté, el trabajo me tiene sin ganas de programar al llegar a casa.
No obstante tengo que aplaudir la idea de Javis. Es cuanto menos original e interesante. Ya lo de elegante o no, no sé qué decir porque, claro, es elegante en el ámbito en que no hay que tocar nada del resto del código, pero un poco chapuzas porque está triplicando el espacio de memoria de los procesos dedicados a posicionamiento y demás :D
Aun así, es una muy buena solución para el programador medio de Bennu, y cualquier DivLike en general.
Lo que no alcanza a comprender Splinter es que, a diferencia del frameskip, se pueden tener más frames que los que se han especificado originalmente: tu indicas los FPS a los que andaba el juego inicialmente, y él te interpola el juego para que funcione al máximo número de frames que soporte la máquina. Es como poner un set_fps(1000,1000), pero sin que el juego vaya nunca a una velocidad diferente para la que fue diseñado.
De todas formas, a mi me plantea algunas dudas, que, en estos momentos, no puedo llegar a explicar (estoy trabajando, y escribo mientras compila el programa :D). Por ejemplo, si la animación del prota depende del número de frames entre imagen e imagen ¿eso se puede controlar? ¿Y otras cosas que dependan del tiempo, es decir, del número de frames?
Aparte de eso, yo siempre he desaconsejado el uso de let_me_alone y de las señales *_tree para todo el árbol de ejecución (en todo caso para un proceso tipo prota, y todos sus hijos, como accesorios, armas, control..., o para un enemigo, o escuadrón...). Es mejor que se controlen los tipos de procesos generados desde un proceso de control.
Por ejemplo, yo siempre tengo una función para enviar señales a los procesos del juego, en el que manda esa señal individualmente a todos los procesos prota, enemigo1, enemigo2, objeto1... y así con todos los procesos que intervienen en la parte jugable... A veces son más de una función, para tener grupos de procesos, porque me puede interesar congelar a los enemigos, pero no al prota, o a ambos, pero no a los items del juego.
Es un peñazo porque el proceso es muy largo de escribir y tienes que estar muy atento cuando creas un nuevo proceso, porque es muy susceptible a olvidos, pero el control total es imprescindible en programación.
Dicho lo cual, me vuelvo a mi cueva :D
Ya sabéis que tengo Telegram, por si queréis contactar conmigo :P
Drumpi, no sabes lo que te pierdes por no estar en el Discord xD
Hola Drumpi! gracias por el mensaje!!
paso a responder algunas de tus dudas!
> si la animación del prota depende del número de frames entre imagen e imagen ¿eso se puede controlar?
la pregunta es, como estas contando los frames? La interpolacion se hace dentro de una función aparte que no deberia tocar ninguna variable tuya.
> ¿Y otras cosas que dependan del tiempo, es decir, del número de frames?
Si controlas con TIMER, por ejemplo, no deberia verse afectada, porque la interpolacion respeta la velocidad original del juego. Con respecto al numero de frame, me quedo con la duda de como los contas. Hasta donde yo se, no existe un contador general de frames en Bennu.
> Aparte de eso, yo siempre he desaconsejado el uso de let_me_alone y de las señales *_tree para todo el árbol de ejecución (en todo caso para un proceso tipo prota, y todos sus hijos, como accesorios, armas, control..., o para un enemigo, o escuadrón...). Es mejor que se controlen los tipos de procesos generados desde un proceso de control.
Por ejemplo, yo siempre tengo una función para enviar señales a los procesos del juego...
Si, yo tengo funciones especiales tambien para ese trabajo.
Si te interesa probarlo avisame y actualizo la version en el framework. Ademas de hacer algunas mejoras le cambié el nombre a "interpolated_fps" porque es mas descriptivo de lo que hace
Yo me refiero a que, por ejemplo, yo tengo un código similar a este para controlar las animaciones:
//Bloque de animaciones
cont_anim++;
if (cont_anim >= 4)
cont_anim = 0;
if (graph < 8) graph++; else graph = 1; end
end
Y como eso, varias cosas controladas mediante contadores, que están fuertemente ligados a los frames.
Supongo que tendría que crear unas variables en tu código, como has hecho con X, Size y demás, para controlar esto.
Eso va a andar bien, no te preocupes :)
No me importaría tener algo así integrado directamente en el engine :D
Por cierto Javis, ¿también se interpolan las posiciones de los scrolls?
Si :) el scroll también se interpola
Genial, gracias, Javis ;)
Karma++, que te lo has ganado, que hace eones que no pongo uno :D
no se por que desaconsejan funciones let_me_alone y señales tree... quisiera argumentos...
Yo en particular tengo mi propia funcion para respetar el estado que el proceso tenia antes de dormirlo y despertarlo de vuelta. asi la interpolacion respeta el codigo y su funcionalidad original.
@drumpi muchas gracias! hoy voy a actualizar el repo asi tienes la ultima version.
Saludos!
Quote from: SplinterGU on June 10, 2019, 02:29:04 PM
no se por que desaconsejan funciones let_me_alone y señales tree... quisiera argumentos...
Por buenas prácticas:
Si usas let_me_alone o un kill_tree, ciertamente eliminas todos los procesos referentes a la ejecución de algo (un nivel, una pantalla, etc...) pero he comprobado que si haces eso, en muchos casos puedes cerrar procesos que no te conviene cerrar (control de teclado, control de sonido...) o que si cerrases como debe ser, verías que tienes un proceso o dos que no has guardado su ID.
No sería la primera vez que, después de cerrar un nivel, se me ha quedado algún proceso de objeto vivo y se ha generado otro al volver a entrar al nivel, con el consiguiente problema de, yo que se, tener a los enemigos que no saben cuál proteger.
Básicamente, para obligar al programador a llevar un control absoluto de qué procesos se crean y cuáles se destruyen.
Aparte que, salvo salir del juego, no le veo uso práctico al let_me_alone.
Por otro lado, está el tema de los recursos: si son los propios procesos los encargados de gestionar los gráficos, música, punteros, etc que se cargan y descargan, hacer que desaparezcan desde fuera puede provocar que dichos recursos no se liberen correctamente.
Por eso desaconsejo su uso... hasta que se tenga un muy buen dominio del tema de los procesos y de la gestión de recursos, pero mientras se sea un novato, mejor que se aprenda a llevarlo todo bajo control desde el primer minuto. Luego ya se usará el onexit y demás herramientas :D
Lo digo por experiencia propia :P
Actualizada libreria, ahora se usa del siguiente modo
include "../library/interpolated_fps.inc";
Process Main()
Begin
//set_fps(30,0);
interpolated_fps(30, 120); // arguments: original FPS, max fps (0 = unlocked)
End