O Game Loop - parte 2
October 3rd, 2007
Conforme prometido, vamos começar a partir do básico o ensino dos conceitos. O “Game Loop” (Laço do jogo) é o principal deles.
Atenção: depois de entender o conceito do Game Loop, você poderá programar pequenas “animações”, terá uma noção geral de como se estrutura um jogo e principalmente terá um pouco de experiência. Mais tarde com esse conceito “dominado”, se você aprender um pouco de detecção de colisão e como pegar a entrada do jogador já poderá fazer jogos simples.
O foco deste artigo será no desenvolvimento de um Game Loop utilizando a linguagem C e a biblioteca Allegro. Não ensinarei como você poderá fazer para compilar o código fonte e nem instalar o ambiente (veja no final do artigo a seção de Referência para maiores detalhes).
Para estudar este artigo eu recomendo:
- digitar os códigos fontes (ao invés de apenas ler e colar)
- ler com calma e ir praticando (isso não fará sentido em um ou dois dias, você não pegará de imediato e conforme for experimentando (ESSENCIAL) aprenderá muito mais do que o artigo ensinou)
- se possível imprima o conteúdo para poder ir lendo e digitando
O Game Loop é o coração de um jogo, nele se encontra a organização do fluxo que permite um jogo continuar rodando baseado nas condições em que foi programado & exposto. Para entender o Game Loop é necessário primeiro entender um outro conceito básico em programação de computadores:

Fluxo de entrada, processamento e saída
Onde:
- ENTRADA: constitui a parte em que o sistema recebe os dados do ambiente
- PROCESSAMENTO: parte em que baseado nos dados que o sistema possui, ele irá processá-los
- SAÍDA: parte em que após o processamento for concluído, o sistema emitirá uma saída com os resultados.
Simples? Sim, na teoria. Este conceito básico nos ajuda a visualizar o Game Loop que nada mais é do que este ciclo executando indefinidamente com uma diferença fundalmental: o ciclo continua executando mesmo que não haja uma entrada no sistema. Conseguiu visualizar? Esta diferença fundamental entre um jogo e um aplicativo convencional nos permite fazer a interatividade de um jogo. Em um Game Loop temos:
- ENTRADA: aqui temos a parte responsável por pegar todos os dados que o jogador envia via teclado, mouse, sensor ótico, tela touch-screen, etc. Aqui também temos que levar em consideração as limitações do dispositivo de entrada (se houver), tempo de leitura das informações, repetições, etc…
- PROCESSAMENTO: aqui temos todo o processamento da lógica do jogo: detecção de colisão, física, carregamento de níveis, cálculos diversos, tomada de decisões baseadas na entrada, cálculo de inteligência artificial, leitura de arquivos e uma infinidade de outras coisas.
- SAÍDA: nesta parte (em alguns casos chamada de renderização) temos todas as informações do jogo exibidos na tela, gravados em um arquivo, etc. Esta área é extremamente extensa e rica (John Carmack que o diga). Podemos ter gráficos 2D, 3D, etc, utilizando APIS gráficas como DirectX, OpenGL, SDL, Allegro… Hoje em dia é comum também a utilização de Shaders para incrementar ainda mais a gama de efeitos de visualização.
Agora que conhecemos como se estrutura um Game Loop, vamos ver na prática como podemos organizar estas informações e testar os nossos próprios conceitos.
O nosso Game Loop se dividirá em duas partes (além das partes descritas acima):
- uma parte responsável pela execução da lógica do jogo (o processamento deve ser totalmente executado antes de haver uma saída)
- uma parte responsável pela saída dos gráficos na tela (no nosso caso utilizaremos uma técnica chamada “Double Buffering”)
Além das partes citadas acima o nosso Game Loop também conterá:
- um contador simples de FPS
- double buffer
Vamos ao código (está comentado detalhadamente):
/*
======================================
Exemplo da implementacao de um Game Loop em Allegro
por Vitor Almeida da Silva
10/2007
Este codigo pode ser utilizado somente para fins educacionais.
======================================
*/
// inclui o header da biblioteca Allegro
#include <allegro.h>
// prototipos das funcoes utilizadas
void Inicializa();
void Finaliza();
bool fimJogo = false; // flag que indica o fim do jogo
int ticks = 0; // esta variavel ira ser um contador de ticks do clock principal
// do jogo
// cada tick a mais significa que um ciclo de logica do jogo
// foi processado
// a funcao do timer do tick apenas incrementa o contador
void ticker() {
ticks++;
}END_OF_FUNCTION(ticker);
int segundos = 0; // esta variavel ira ser um contador de segundos
// a cada segundo passado este contador ira ser incrementado
// basicamente eh a chave para fazer um contador de fps
// pois se tivermos a quantidade de frames desenhados
// e a quantidade de segundos podemos calcular os frames
// por segundo
// a funcao do timer do clock apenas incrementa o contador
void clocka() {
segundos++;
} END_OF_FUNCTION(clocka);// a partir daqui definimos algumas outras variaveis auxiliares
// dimensoes do video
int vid_largura = 640; // quantidade de pixels de largura do video
int vid_altura = 480; // quantidade de pixels de altura do video
int vid_profundidade = 32; // quantidade de bits de profundidade (numero de bits que cada pixel tera)
int frames = 0; // contador da quantidade de frames desenhados na tela
int fps = 0; // contador de fps (frames por segundo)
BITMAP *bmp; // bitmap que ira guardar tudo o que desenharmos (para depois ser "jogado" na tela")
// este bitmap eh de suma importancia pois cada funcao de desenho
// que desenha em um bitmap provavelmente devera ser apontada
// para este bitmap
/*
=======
main
Funcao principal
Aqui temos o ponto de entrada da aplicacao onde o Game Loop sera executado
=======
*/
int main(int argc, char *argv[]) {
// realiza todas as inicializacoes necessarias
Inicializa(); // a partir deste ponto temos a aplicacao pronta para iniciar o game loop
// inicio do game loop
// neste caso o game loop continua executando enquanto nao pressionarmos
// a tecla esc, mas voce pode verificar por uma outra variavel ou condicao
while (!fimJogo) { // inicio do processamento da logica do jogo
while (ticks && !fimJogo) { // aqui iniciamos o processamento da logica do jogo
// neste ponto, voce devera inserir o codigo responsavel
// processamento da logica do seu jogo, isto inclui: deteccao de colisao
// inteligencia artificial, calculos diversos, etc
// aqui esta o segredo:
// a variavel abaixo "ticks" eh decrementada, mas lembre-se que ela
// tambem eh incrementada pela funcao de timer, entao qual eh a logica?
// Lembre-se que o timer do ticks eh executado em um intervalo fixo
// entao o decremento tambem ocorrera em um intervalo fixo, isto garante
// que a logica do jogo sera executada pelo menos N vezes por segundo
// sendo que N eh o intervalo de tempo do timer dos ticks
if (key[KEY_ESC]) fimJogo = true; // se pressionou a tecla esc entao finaliza o jogo
ticks--;
} // fim do processamento da logica do jogo
// quando chegarmos ateh aqui significa que a variavel ticks esta com valor
// zerado, entao ja executamos toda a logica do jogo, agora eh hora
// de exibir o resultado na tela
// para exibir o resultado na tela, toda a saida deve ser desenhada
// no bitmap bmp declarado anteriormente
// para auxiliar, exibimos o fps, note que estamos desenhando no bmp
// e utilizando a fonte padrao (font), e fundo transparente (-1)
// textprintf(bmp, font, 0, 0, -1, " FPS: %i " , fps); // descomente se quiser exibir o fps
// depois que estiver como frame no bmp, copiamos o conteudo inteiro dele
// para a tela
// isto eh realizado pois como esta copia eh feita em memoria, eh muito
// mais rapido
blit(bmp, screen, 0, 0, 0, 0, vid_largura, vid_altura);
// apos a saida concluida, incrementamos o contador de frames, pois
// temos mais um frame desenhado na tela
frames++;
// agora iremos calcular o total de frames por segundo
// a logica eh a seguinte:
// se na aplicacao ja passou um segundo
if (segundos) {
// calcula o fps sendo que o fps sera a quantidade de frames desenhados
// dividido pelo numero de segundos passados (no caso 1)
fps = frames / segundos;
frames = 0; // como ja calculamos o fps, pode zerar a quantidade de frames desenhados
segundos = 0; // e zera tambem o numero de segundos, isso garante que o proximo
// calculo de fps sera executado um segundo depois
}
}
// executa todas as finalizacoes necessarias
Finaliza();
return 0;
}END_OF_MAIN();
/*
=======
Inicializa
Realiza qualquer procedimento necessario para iniciar o jogo
Isto inclui iniciar a janela e deixa-la preparada para ser desenhada, iniciar
o estado do jogo, posicoes iniciais, nivel inicial e tudo o que for necessario
=======
*/
void Inicializa() {
int res;
allegro_init();
set_color_depth(vid_profundidade);
res = set_gfx_mode(GFX_AUTODETECT_WINDOWED, vid_largura, vid_altura, 0, 0);
if (res != 0) {
allegro_message(allegro_error);
exit(-1);
}
install_timer();
install_keyboard();
install_mouse();
// aqui inicializamos o nosso timer de ticks
// trancando o espaco de memoria da variavel ticks e da funcao timer
// assim elas nao sofrem alteracoes externas
// note que a funcao ticker sera chamada 60 vezes por segundo, isto eh,
// a logica do nosso jogo sera executada 60 vezes em um segundo
LOCK_VARIABLE(ticks);
LOCK_FUNCTION(ticker);
install_int_ex(ticker,BPS_TO_TIMER(60));
// aqui ocorre o mesmo processo para o timer dos segundos
// note que o timer sera chamado apenas uma vez por segundo
LOCK_VARIABLE(segundos);
LOCK_FUNCTION(clocka);
install_int_ex(clocka,BPS_TO_TIMER(1));
// cria um bitmap com uma dimensao grande o suficiente para caber na tela
bmp = create_bitmap(SCREEN_W,SCREEN_H);
set_window_title("VSoftGames - Teste do Game Loop");
}
/*
=======
Finaliza
Realiza qualquer procedimento de limpeza para finalizar o jogo
=======
*/
void Finaliza() {
clear_keybuf();
// destroy_bitmap(bmp);
// neste ponto voce devera adicionar qualquer tipo de finalizacao que for
// necessario, limpeza, etc.
}
Após rodar o programa acima, você verá uma tela como a de baixo (observe o contador de fps no canto superior esquerdo):
Conclusão
Em um próximo artigo veremos algumas possiblidades com as funções básicas de renderização de “primitivas” no Allegro e em seguida estudaremos algumas técnicas para entrada, assim já será possível fazer jogos bem simples (mas divertidos).
Fique ligado.
Dicas:
- não tente decorar as funções do Allegro, entenda o conceito, você não conseguirá escrever sem olhar no manual (tive que olhar no manual várias vezes para escrever este código)
- agora que você possui a estrutura básica de um Game Loop, estude as funções de desenho “primitivas” da biblioteca Allegro e tente desenhar alguma coisa que se mova (ou que não se mova)
- se você estudar a função “rand” da biblioteca matemática “math.h” poderá incrementar ainda mais estas animações com efeitos aleatórios
- lembre-se de testar e fazer diversos exemplos.
- não se preocupe em entender todos os detalhes do código agora, o importante é entender o conceito e ir testando com cada parte para solidificar na mente, não perca tempo com decoreba de estruturas complicadas da linguagem e nome de funções (que você só lembrará as que mais utilizar, isto é, as que você digitou com mais frequência
Referências:
- Allegro Vivace: Um dos melhores tutoriais que eu já vi sobre Allegro, se você não viu, veja agora. Em inglês.
- Allegro para Iniciantes: Artigo muito bom do site Unidev que ensina como instalar uma IDE para desenvolvimento em C++ com Allegro e ensina também o básico para desenvolver em Allegro (recomendado, este artigo ensina algumas coisas que ainda não comentei no blog).
- Iniciação de Allegro em C++: Outro artigo, serve como complemento do primeiro.
- BDJogos: Excelente site nacional com diversos tutoriais sobre Allegro. Altamente recomendado.
Espero que tenham gostado. Até o próximo artigo.
Posts Relacionados
Entrada preenchida em: Tutoriais sobre programação de jogos

2 Comentários Adicione um comentário
1. VSoftGames » Trigon&hellip | November 13th, 2007 em 2:43 pm
[...] a parte prática, recomendo a leitura dos artigos “O game loop parte 1″, “O game loop parte 2″ e “Dicas para aprender a programar jogos eletrônicos”, recomendo também uma visita ao [...]
2. VSoftGames » Como f&hellip | September 23rd, 2008 em 1:17 am
[...] Para iniciar crie um projeto chamado Menu e utilize a base inicial deste tutorial; [...]
Deixe um Comentário
HTML permitido:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
Rastreie este post | Se inscreva para receber os comentários via RSS