Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Frames por segundo [para EX3]

Iniciado por bnl, 14 de Julio de 2006, 07:19:26 PM

« anterior - próximo »

bnl

Ex3, sobre lo que estuvimos hablando ayer en la quedada de forzar un número de frames por segundo te paso el codigo en VB 6.0 de como lo monte en un motor juego de rol que medio monte hace años.


   salir = False
   Do While Not salir
       numTicks = GetTickCount
       
       manejarEntradas 'de raton y de teclado
       If Not pausado Then
           ActualizarJuego
       End If
       
       Render 'dibuja
       While GetTickCount - numTicks <= 15
           DoEvents
       Wend
       
       DoEvents
   Loop



Te paso tambien el codigo que utilice en un juego para moviles. Como puedes ver utilice tanto el wait como el sleep. No se cual será mejor.
El codigo esta lleno de instrucciones comentadas que utilice para depurar, pero creo q se entiende.




       while (hiloActual == hiloConcurso) {
           try {
               //System.out.println("Concurso>>Ciclo1");
               tiempoInicial = System.currentTimeMillis();                  
                       
               //Si se esta mostrando una ventana del sistema que tapa nuestra
               //ventana no actualizamos el juego ni la pantalla
               if (isShown()) {                    
                   //System.out.println("Concurso>>Ciclo2");
                   actualizarMundo();
                   //System.out.println("Concurso>>Ciclo3");
                   dibujarPantalla();    
                   //System.out.println("Concurso>>Ciclo4");
                   dibujarInformacionDepuracion();    
                   //System.out.println("Concurso>>Ciclo5");
               }                                
               
               //System.out.println("T>>" + tiempoTranscurrido);                
               //System.out.println("Concurso>>Ciclo6");
               
               conta ++;                
               if (tiempoProcesoTranscurrido > maximoTiempoProcesoTranscurrido ){
                   maximoTiempoProcesoTranscurrido = tiempoProcesoTranscurrido;
                   conta = 0;
               }else{                                        
                   if (conta==40){                        
                       maximoTiempoProcesoTranscurrido = 0;
                   }
               }
               
               flushGraphics();
               //System.out.println("Concurso>>Ciclo7");
               
               tiempoTotalTranscurrido = System.currentTimeMillis() - tiempoInicial;
               if (tiempoTotalTranscurrido > maximoTiempoTotalTranscurrido ){
                   maximoTiempoTotalTranscurrido = tiempoTotalTranscurrido;
                   conta = 0;
               }else{                                        
                   if (conta==40){                        
                       maximoTiempoTotalTranscurrido = 0;
                   }
               }
               if (conta==40){                        
                       conta = 0;
               }
               
               if (tiempoTotalTranscurrido < MILISEGUNDOS_POR_CICLO) {
                   synchronized (this) {
                       //Si el ciclo se ha ejecutado en menos tiempo del que hemos
                       //establecido esperamos el tiempo restante para que el
                       //juego no vaya muy rapido
                       wait(MILISEGUNDOS_POR_CICLO - tiempoTotalTranscurrido);                                                
                       
                       /*
                       try {
                           hiloActual.sleep(MILISEGUNDOS_POR_CICLO - tiempoTranscurrido);
                       } catch (InterruptedException e) {
                           System.out.println(e.toString());
                       }
                        */                        
                   }
               } else {
                   // Cedemos el procesador por si tienen q ejecutarse otros hilos
                   hiloActual.yield();
               }              
           }
           catch(Exception e){
               System.out.println(e);
           }
       }
       if (Estado.Pausado){
           this.dibujarPausa();
       }
       if (Estado.JuegoTerminado){
           this.dibujarJuegoTerminado();
       }
       System.out.println("Concurso>Run>Sale");
   }

Mi web: http://www.brausoft.com/
No sabían que era imposible, así que lo hicieron.

[EX3]

Al final te acordastes, gracias por la aportacion :) Voy a esperar a que empiece la semana para probarlo y estudiarlo con calma, que el finde como que no da tiempo ni ocasion a mucho que digamos :lol:

De momento el primer codigo es el ejemplo que te comente que vi en muchas paginas que indican un tiempo maximo en milisegundos en vez de un numero determinado de cuadros por segundo para limitar el numero de los mismos. Yo busco lo 2º, indicarle un numero de fps y que no pase de el. Me he vuelto loco intentando cosas como ir incrementando una variable para realizar la espera y cosas semejantes y no he logrado resultados muy satisfactorios que digamos :(

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

[EX3]

Mira que he buscado de veces por google, mira que no son pocas las veces que he buscado ejemplos de metodos que no limitaran a partir de un valor de tiempo si no de fps y basta que me diese por mirar hoy para encontrar un pdf muy interesante para SDL que entre otras cosas trata este asunto de forma muy clara y sencilla :)

[PDF] SDL con cafeına Metiendo mano a la POO

Version en HTML

El codigo en concreto es este:
//espera hasta el siguiente frame
void Manager :: WaitFrame () {
while(( fps_timer.GetTicks()-old_ticks)
< ((float) 1.0/ fps *1000)) {
//no hacer nada
}
old_ticks=fps_timer.GetTicks (); // actualizar old_ticks
}

Va de lujo excepto por un ligero margen de error de 10 fps, poniendo un maximo de 60 fps me limita a 50 fps en los ejemplos que he probado, que no es algo apreciable pero aun asi voy a ver si soy capaz de "afinarlo" para ser algo mas exacto.

Aqui lo dejo para el que le interese, que supongo que alguno mas aparte de mi le podra ser util :)

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

bnl

En el codigo de VB6.0 no estoy muy seguro de que se deba hacer asi, lo de meterlo en un bucle que no haga nada no me acaba de gustar (eso si con el do events para no tostar la CPU, como comentamos)

Lo de calcular los segundos para un determinado fps es sencillo. Si queremos 100fps y como un seg tiene 1000 milisegundos eso implicaria que cada 10 milisegundos (1000/100) tendriamos que dibujar un frame. Que es lo que hacen en el codigo que has posteado.
Mi web: http://www.brausoft.com/
No sabían que era imposible, así que lo hicieron.

Sante

Buenas, a ver si puedo aportar mi granito de arena...  :roll:

No se como será en móviles, pero al menos en PC, creo que GetTicksCount (y por lo tanto, SDL_GetTicks) tiene problemas de precisión con tiempos muy pequeños, me parece que cuando eran inferiores a unos 10 mseg o asi.

Lo más probable es que ese error en el número de fotogramas pueda venir por ahí. Lo que yo recomiendo es usar un contador de alta precisión, basado en QueryPerformanceFrequency y QueryPerformanceCounter, que funcionan de lujo.

El típico sleep (tiempoQueFalte) tampoco suele ser una buena idea, al menos en PC. La razón es que sleep no garantiza que se espere el tiempo indicado, sino al menos ese tiempo. Esto es, que si haces un sleep (10), eso puede esperar 10 mseg, o 15, o 17...

En mi opinión la mejor solución es un bucle de espera que esté continuamente preguntando si ya ha transcurrido el tiempo, basado en un contador de alta precisión. Y para evitar bloquear la CPU, se mete un sleep (0), que permite al SO seguir ejecutando sus tareas.

Espero que pueda ayudar en algo :D

[EX3]

Cita de: "bln"En el codigo de VB6.0 no estoy muy seguro de que se deba hacer asi, lo de meterlo en un bucle que no haga nada no me acaba de gustar (eso si con el do events para no tostar la CPU, como comentamos)
Esta es la implementacion que hice en VB6:
Private Sub WaitFrame(MaxFrames As Integer)    
   Do While (Global_Mod.GetTickCount() - Old_Ticks) < (1# / MaxFrames * 1000)
       'No hacer nada:
       DoEvents
       
   Loop
   
   Old_Ticks = Global_Mod.GetTickCount() 'Actualizar old_ticks

End Sub

Exceptuando el DoEvents para evitar cuelgues no creo que sea muy diferente.

Cita de: "Sante"Lo más probable es que ese error en el número de fotogramas pueda venir por ahí. Lo que yo recomiendo es usar un contador de alta precisión, basado en QueryPerformanceFrequency y QueryPerformanceCounter, que funcionan de lujo.
Lo estuve pensando ya que hace tiempo me hablaron de estas funciones, pero tambien recuerdo que me contaron que en portatiles daban problemas por temas de la frecuencia y tampoco me gustaria oviamente que la libreria diera problemas en portatiles. no recuerdo bien exactamente el tema, alguien que lo confirme o lo desmienta?

Habiendo problema o no llevo algun tiempo pensando en implementar los contadores de alta precision en la dx_lib32 por que no es la primera vez que me doy de morros por temas de precision, que esos temas de precision tambien se los achaco a la velocidad de ejecucion de VB6.

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

bnl

Acabo de encotrar esta pagina para el tema de los tiempos. Lo mismo te es de utilidad

http://elguille.info/NET/vs2005/como/stopwatch_clase_calcular_tiempos.htm
Mi web: http://www.brausoft.com/
No sabían que era imposible, así que lo hicieron.

StraT

La autora del PDF que habéis puesto arriba forma parte del grupo ganador de la fast compo de la campus, ;).

Saludos
quot;Solo hay dos cosas infinitas, el universo y la estupidez humana, aunque de lo primero no estoy muy seguro\\\" Einstein

[EX3]

Gracias por la info, bnl aunque al final implemente el sistema que se describe en el pdf que linke arriba y usando los QueryTimers como me sugirio Sante y va a la suma perfeccion. La proxima version de la libreria ya tendra disponible la configuracion de fps maximos entre algunas posibles mejoras como calculos de rotaciones por coordenadas polares como me ha sugerido un conocido mio.

Por cierto, StraT, si no me equivoco, que lo dudo, LadyBenko o Benko a secas como creo que se hacia llamar, regentaba los foros de DivSite, no?

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

shephiroth

Buenas. A ver si puedo aportar mi granito de arena.


int maxfps=60;
int fps=0;
() old_ticks=0;
...
//bucle de pintado
if (old_ticks=0) old_ticks=GetTickCount;
if (GetTickCount-old_ticks>=(fps*1000/max_fps))
{
fps++;
ActualizarDatos();
PintarJuego();
//lo q se necesite
}
if (fps==maxfps)
{
fps=0;
old_ticks=0;
}

Basicamente lo que hace es en vez de esperar x tiempo entre frame y frame, tener encuenta cuanto tiempo a transcurrido desde el frame 0 hasta el frame actual, y comprobar si le toca dibujar o no.
La unica pega que le veo es q si quereis crear una pausa o algo, pero con poner fps=0 y actualizar el old_tick se soluciona.

SALUDOS ^^






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.