Conheça a iniciativa da Biblioteca dos Desenvolvedores  
Índice da Biblioteca  
Área dos Usuários  
Fórum de Discussão  
Forúm
 
 


28 - FPS - Quadros por segundo, Frames per second ou Frame Rate


Todo jogo possui animação, isto é fato.
Animações são geralmente quadros de desenhos que vão se mudando ( sobrepondo a antiga ) gerando assim uma animação.

Este é o exemplo de uma animação e alguns de seus quadros, que juntos formam a animação.

=

Esta animação originalmente tem 12 quadros e ela é executada a 100 milisegundos.
Se aumentarmos a taxa de milisegundos de cada quadro em separado, a animação vai ficar ainda mais lenta.
Se diminuirmos a taxa de 100 milisegundos de cada quadro, a animação vai ficar bem mais rápida.

Essa mudança de tempo nos quadros da animação influencia muito os jogos feitos para computadores.
Geralmente, nosso programa roda na velocidade de clock tick do nosso processador. Isto quer dizer que o programa pode rodar mais rápido em algumas máquinas e mais lento em outras máquinas.

Isso influência não só as animações como também a jogabilidade.

Para que o jogo rode igual em qualquer máquina, precisamos criar um controle de Frame Rate ( ou controle de FPS ).
Para isto, primeiro precisamos descobrir como contar os FPS de nosso programa.

 

DICA...

Esta técnica de contar FPS e fazer o programa rodar em um FPS igual para todas as máquinas pode e deve ser aplicado em qualquer tipo de linguagem de programação para jogos ou animações.

Cada linguagem tem uma forma diferente de se chegar nesse resultado, mais a tecnica é a mesma.Vamos aprender em Allegro um código completo.

Em DirectX podemos fazer a mesma coisa usando a função do windows GetTickCount(); que pega o total de ticks.
Em OpenGL podemos fazer a mesma coisa usando as funções do GLUT .

 

VOCÊ PRECISA SABER...

É importante que você tenha lido nosso artigo sobre como instalar timers no Allegro.

- Controle de tempo



CÓDIGO...
#include <allegro.h>

// Exemplo da bolinha com contador de Frames por segundos

// global
int fps = 0;
int fps_antigo = 0;


// prototipo do contador de frames
void frame_rate();

int main()
{
   allegro_init();
   set_color_depth(16);
   install_keyboard();
   set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
   
   
   BITMAP *buffer = NULL;
   
   int x = 0;
   int y = SCREEN_H/2;
   int tamanho = 20;
   
   install_timer();
   
   // a cada 1 segundo mostra quantas vezes a imagem foi impressa na tela
   install_int( frame_rate, 1000 );
   
   
   
   bool colide = false;
   
   int variavel_x = 10;
   int variavel_y = 10;
   
   // Criando BUFFER para double buffer
   buffer = create_bitmap(800,800);
   
   
   
   // Laço principal
   while( !key[KEY_ESC] )
   {
      
      if ( variavel_x == 1 )
      {
         x += variavel_x;
      }
      else
      {
         x -= variavel_x;
      }
      
      if ( variavel_y == 1 )
      {
         y += variavel_y;
      }
      else
      {
         y -= variavel_y;
      }
      
      // limitando o quadrado dentro da tela
      if ( x < 0 )
      {
         variavel_x = variavel_x * (-1);
      }
      
      if ( (x+tamanho) > SCREEN_W )
      {
         variavel_x = variavel_x * (-1);
      }
      
      if ( y < 0 )
      {
         variavel_y = variavel_y * (-1);
      }
      
      if ( (y+tamanho) > SCREEN_H )
      {
         variavel_y = variavel_y * (-1);
      }
      
      // limpa o nosso novo buffer
      clear( buffer );
      
      // escreve a bola no buffer
      ellipsefill(buffer, x, y, tamanho, tamanho, makecol(255,255,0) );
      
      textprintf_ex( buffer, font, 10, 10, makecol(255,0,0), -1, "FPS: %d", ::fps_antigo );
      
            
      
      blit(buffer, screen, 0,0,0,0, SCREEN_W, SCREEN_H);
      
      vsync();
      ::fps++;
      
   }
      
   destroy_bitmap( buffer );
      
   allegro_exit();
   return 0;
}
END_OF_MAIN();
      
void frame_rate()
{
   ::fps_antigo = ::fps;
   ::fps = 0;
}

FIM DE CÓDIGO

No exemplo acima, criamos uma variável global fps que é incrementada sempre após que a imagem é imprimida na tela.
Usando um timer do Allegro, sempre que passar 1 segundo, nós mostramos o total de FPS que o Allegro conseguiu imprimir, tendo assim o total de frames impressos em 1 segundo.

Legal.. já sabemos a quantos quadros nosso programa roda, agora precisamos controlar a taxa de quadros, sem influênciar na jogabilidade.
Nos exemplos anteriores do site, estavamos usando o comando rest() que fazia o compilador esperar.Esta função não deve ser usanda, por que durante a execução do comando rest() as teclas do teclado não são detectadas.

Agora precisamos controlar a taxa de frames de nosso programa.
A descisão da quantidade de frames por segundo o jogo vai rodar é sua, você pode usar 30 FPS que é o limite mínimo para que o olho detecte transação da animação, ou 60 que é o valor mostrado no manual da Allegro.



CÓDIGO...

#include <allegro.h>

// Exemplo da bolinha com limitador de FPS

// global
int fps = 0;

int fps_antigo = 0;
int fps_speed = 0;

// prototipo do contador de frames
void frame_rate();

// prototipo do contador de velocidade
void incrementa_speed();

int main()
{
   allegro_init();
   set_color_depth(16);
   install_keyboard();
   set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
   
   
   BITMAP *buffer = NULL;
   
   int x = 0;
   int y = SCREEN_H/2;
   int tamanho = 20;
   
   install_timer();
   
   // a cada 1 segundo mostra quantas vezes a imagem foi impressa na tela
   install_int( frame_rate, 1000 );
   
   install_int_ex( incrementa_speed, BPS_TO_TIMER(60) );
   
   
   bool colide = false;
   
   int variavel_x = 10;
   int variavel_y = 10;
   
   // Criando BUFFER para double buffer
   buffer = create_bitmap(800,800);
   
   
   
   // Laço principal
   while( !key[KEY_ESC] )
   {
      while ( ::fps_speed > 0 )
      {
         if ( variavel_x == 1 )
         {
            x += variavel_x;
         }
         else
         {
            x -= variavel_x;
         }
         
         if ( variavel_y == 1 )
         {
            y += variavel_y;
         }
         else
         {
            y -= variavel_y;
         }
         
         // limitando o quadrado dentro da tela
         if ( x < 0 )
         {
            variavel_x = variavel_x * (-1);
         }
         
         if ( (x+tamanho) > SCREEN_W )
         {
            variavel_x = variavel_x * (-1);
         }
         
         if ( y < 0 )
         {
            variavel_y = variavel_y * (-1);
         }
         
         if ( (y+tamanho) > SCREEN_H )
         {
            variavel_y = variavel_y * (-1);
         }
         
         // limpa o nosso novo buffer
         clear( buffer );
         
         // escreve o quadrado no buffer
         ellipsefill(buffer, x, y, tamanho, tamanho, makecol(255,255,0) );
         
         textprintf_ex( buffer, font, 10, 10, makecol(255,0,0), -1, "FPS: %d", ::fps_antigo );

         ::fps_speed--;
         ::fps++;
      }
      
      blit(buffer, screen, 0,0,0,0, SCREEN_W, SCREEN_H);
            
      vsync();
      
   }
   
   destroy_bitmap( buffer );
   
   allegro_exit();
   return 0;
}
END_OF_MAIN();
   
void frame_rate()
{
   ::fps_antigo = ::fps;
   ::fps = 0;
}
   
void incrementa_speed()
{
   ::fps_speed++;
}


FIM DE CÓDIGO

O programa acima pode parecer confuso.
Nós criamos um timer para que, a cada 60 clock tick ( usando a macro BPS_TO_TIMER ) o contador de speed seja incrementado.

Quando acontecer os primeiros 60 clocks, o compilador vai entrar no while que atualiza a lógica do jogo.
Enquanto o fps_speed não for menor que 0 ( o while vai fazer ele chegar bem rápido ) ele vai atualizando a lógica do jogo, mais não a tela.

Esta lógica faz com que o contador de FPS fique constante.
Execute o código acima e faça testes alterando o valor que está na macro BPS_TO_TIMER para conferir.

Para fazer com que o teclado obedeça a velocidade em FPS é preciso utilizar um Buffer de teclado, que pode ser lido aqui:
http://www.bdjogos.com/biblioteca_conteudo.php?id=17


Com este tutorial suprimos uma das dúvidas mais cabulosas na criação de jogos, a partir deste capítulo iremos demonstrar outras técnicas importantes na programação de jogos. Qualquer dúvida entre em contato pelo forum.

http://www.bdjogos.com/forum



Download do exemplo 1 - Clique Aqui

Download do exemplo 2 - Clique Aqui



Contribuidor
Adriano Waltrick
15/08/2007


 

« Anterior

 

Próximo »

 
 

01/06/2007 (C) Copyright. Todos os Direitos Reservados. Leia a política de privacidade do portal.
É proibida a cópia de conteúdo deste site de acordo com a Lei Brasileira de Direitos Autorais.