quinta-feira, 17 de junho de 2010

Hello World (Olá Mundo) em C++ com Allegro

E aí estudantes de C/C++, como estão?

Hoje vou mostrar como se faz o programa mais básico de todos em qualquer linguagem de programação: o famigerado Hello World! (ou Olá Mundo para os amantes da Língua Portuguesa). Mas não é simplesmente um Hello World usando o bom e velho printf (em C) ou cout (em C++). É um Hello World usando a biblioteca Allegro, a melhor biblioteca para desenvolvimento de jogos que existe na face da terra. Nesse pequeno programa você vai aprender a inicializar a biblioteca, a compôr cores e a escrever textos numa janela.

Antes de mais nada, você já instalou a biblioteca Allegro no seu ambiente de desenvolvimento? Eu assumo que você está usando a IDE Dev-C++, que é a melhor IDE pra programar em C e C++. Caso você ainda não saiba como instalar Allegro no Dev-C++ pra usar nos seus programas, leia antes a minha outra postagem que mostra como fazer isso:


Bom, agora que você já instalou e configurou Allegro no Dev-C++, vamos ao código do Hello World. No quadro abaixo eu mostro o código completo. Depois eu explico cada parte do código. Pra ficar fácil de acompanhar, copie e cole esse código no Dev-C++ e compile pra ver.


#include "allegro.h"

//--------------------------------------------------------------------
// PROTOTIPOS DAS FUNCOES
//--------------------------------------------------------------------
void inicializar_allegro( bool );

//--------------------------------------------------------------------
// FUNCAO MAIN
//--------------------------------------------------------------------
int main()
{
inicializar_allegro( false );

const int BRANCO = makecol(255, 255, 255);

textout_centre_ex( screen, font, "Hello World!",
SCREEN_W/2, SCREEN_H/2, BRANCO, 0 );

readkey();
}

END_OF_MAIN()

//--------------------------------------------------------------------
// IMPLEMENTACAO DAS FUNCOES
//--------------------------------------------------------------------
void inicializar_allegro( bool tela_cheia )
{
allegro_init();
set_color_depth(32);

if ( tela_cheia )
set_gfx_mode( GFX_AUTODETECT_FULLSCREEN, 640, 480, 0, 0 );
else
set_gfx_mode( GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0 );

set_window_title( "Hello World com Allegro" );

install_keyboard();
}


Então, o que faz esse código afinal? Vamos por partes:

A primeira coisa é a inclusão do cabeçalho da biblioteca Allegro. Veja que a primeira coisa que se vê no arquivo é o #include "allegro.h". Sem isso o programa nem compila.

Depois, vem o protótipo da única função além de main, que é inicializar_allegro. Essa função, como o próprio nome diz, serve para inicializar a biblioteca Allegro. Qualquer programa escrito usando essa biblioteca vai ter que inevitavelmente invocar estas funções (que eu encapsulei numa função só, pra ser chamada de dentro do main). Um detalhe, o argumento bool que essa função recebe indica se o programa roda em tela cheia ou numa janelinha do sistema. Um argumento true faz o programa rodar na tela cheia. Um argumento false, faz o programa rodar numa janela.

Vamos pular a função main por agora, e vamos direto à implementação da função inicializar_allegro.

As funções invocadas aqui são referentes à inicialização da biblioteca Allegro, que nada mais é do que uma forma de passar as informações sobre o tamanho da tela, a profundidade de cores, o modo gráfico, o título da janela (se for rodar numa janela), inicializar os outros módulos da biblioteca, etc.

A função allegro_init é onde tudo começa. Sem isso, nada funciona usando Allegro. Essa função não recebe nenhum argumento. Sempre use isso antes de invocar qualquer outra função da Allegro, ou o programa pode (e vai) encerrar e/ou travar.

Depois vem set_color_depth. Essa função recebe como argumento a profundidade de cores da tela. Em geral, você pode simplesmente passar o valor 32 (32bpp - 32 bits por pixel) pra essa função. Essa função também deve ser invocada sempre antes de usar qualquer função que gere gráficos na tela, senão não vai aparecer nada.

Em seguida, vem uma estrutura de decisão que eu implementei pra decidir se o programa deve rodar numa janela ou em tela cheia. A função set_gfx_mode é obrigatória também antes de tentar desenhar qualquer coisa na tela. Essa função recebe cinco argumentos, mas somente os três são importantes aqui. Na seguinte ordem: modo gráfico, largura da tela, altura da tela. Os dois últimos argumentos você pode passar o valor 0 (zero) sempre, que não vai dar problema nenhum.

O modo gráfico se refere basicamente ao modo gráfico :P Apenas duas constantes (já definidas na biblioteca Allegro por padrão) são importantes pra nós. E essas constantes são GFX_AUTODETECT_WINDOWED e GFX_AUTODETECT_FULLSCREEN. Dependendo de qual desses valores você passar, o programa vai pra tela cheia ou fica numa janela do sistema.


GFX_AUTODETECT_WINDOWED = O programa roda numa janela.
GFX_AUTODETECT_FULLSCREEN = O programa roda em tela cheia.


Os argumentos largura da tela e altura da tela, se referem justamente ao tamanho da tela. Em geral, eu passo sempre os valores 640 e 480 respectivamente, porque é o tamanho que é mais conveniente pra mim. Mas depende do seu caso qual tamanho especificar.

E por fim, os outros dois argumentos, como citei antes, pode deixar como 0 (zero). Caso você esteja curioso pra saber o que eles significam, dê uma olhada na documentação que vem junto com a biblioteca, ok? Mas te garanto que eles não fazem falta nenhuma.

Agora, a próxima função invocada é set_window_title. Se o seu programa roda somente em tela cheia, então nem precisa se preocupar com essa função, uma vez que ela só serve pra colocar um nome na barra de título da janela, quando o programa roda numa janela. Não é obrigatório chamar essa função aqui, você pode invocá-la em qualquer lugar no seu programa, e pode alterar a hora que quizer. Se não quizer colocar um título na sua janela, então nem se preocupe com essa função. O único argumento que ela recebe é uma string contendo justamente o título da janela.

A seguir, a última função invocada para inicializar Allegro é importantíssima! A função install_keyboard é a responsável por inicializar as rotinas de manipulação do teclado. Ela não recebe nenhum argumento. Sem invocar essa função, nenhuma função relacionada à entrada pelo teclado vai funcionar. Caso você não chame essa função pelo menos uma vez durante a execução do seu programa, ele simplesmente vai ignorar qualquer tentativa de ler entradas do teclado. Muitas vezes eu esqueço de chamar essa função, então lembre-se sempre, se você estiver tentanto obter pressionamento de teclas e não funcionar nenhuma função, dê uma olhada se você não esqueceu de chamar install_keyboard antes de qualquer outra função relativa ao teclado.

Bom, essa foi a inicialização da Allegro. A partir daí, você pode usar a maioria das funções. Digo a maioria das funções, porque se você for usar rotinas relacionadas ao mouse ou relacionadas a áudio (rotinas de som), você vai precisar chamar outras três funções na inicialização da Allegro:


install_mouse = O programa pode usar rotinas relacionadas ao mouse.
install_timer = O programa pode usar rotinas relacionadas ao mouse e ao timer.
install_audio = O programa pode usar rotinas relacionadas a som e áudio.


Mas como o nosso Hello World não usa o mouse, nem som, nem o timer, então não precisa perder tempo com essas funções. Mas fica a dica: caso queira usar rotinas de áudio, de mouse ou de timer, lembre-se de invocar as funções de inicialização correspondentes antes de qualquer coisa.

Voltando agora ao main, essa como todos sabem é a função principal, que é invocada automaticamente pelo sistema operacional ao executar o programa. A primeira função invocada em main é a inicializar_allegro, que como eu já expliquei antes, inicializa as rotinas da Allegro e todo programa que você for fazer você deverá ter uma função semelhante a essa, pra inicializar tudo.

Em seguida, depois de inicializar Allegro, vem a definição de uma constante inteira. É aqui que eu componho a cor que será usada pra escrever na tela. Daí você me pergunta, "como assim compôr a cor?"... Calma, eu vou explicar.

As rotinas da Allegro que lidam com gráficos primitivos, como pixels (pontos), linhas, retângulos, elipses, textos, etc. precisam que você especifique a cor do objeto em questão. A cor de um objeto na verdade nada mais é do que um enorme número inteiro que só faz sentido pro sistema operacional. Veja como eu defini a constante nesse programa:


const int BRANCO = makecol( 255, 255, 255 );


Pois então, pra compôr uma cor nós usamos a função makecol, que recebe três argumentos - números inteiros entre 0 e 255 - na seguinte ordem: intensidade de vermelho, intensidade de verde, intensidade de azul. Você lembra como se faz a cor amarela? Mistura-se vermelho com verde. Lembra como se faz a cor roxa? Mistura-se vermelho com azul. Pois é assim que funciona essa função. Você deve indicar nos argumentos as intensidades das três cores primárias vermelho, verde e azul, para compôr uma cor que será usada nos objetos que você vai desenhar na tela.

No exemplo anterior, makecol( 255, 255, 255 ) está passando para a função os três valores máximos dos argumentos, que vão de 0 até 255. Se você mistura vermelho com verde e com azul, ou seja, todas as cores primárias, nas suas intensidades máximas, aqui você obtém a cor branca. E como você pode ver no exemplo, foi justamente esse o nome que eu dei pra cor: BRANCO.

Agora você vai me perguntar: "se BRANCO é uma constante inteira, que valor está lá depois de atribuir o resultado da chamada à função makecol?"... Boa pergunta. A função makecol compõe a cor que você especificou através dos três argumentos, e retorna um número inteiro que é dependente tanto de plataforma quanto da profundidade de cores especificada. Isso quer dizer que não importa pra nós que número representa a cor que você compôs. Isso só importa pro sistema operacional. Quer ver por que? Eu dei uma olhada no número que foi atribuído à constante BRANCO no meu sistema: 16777215. O que significa esse número? Ele representa a cor branca no meu monitor e na profundidade de cores atual. Mas enfim, esse número não interessa pra nada, então não se preocupe com o valor retornado por makecol, apenas trate de dar nomes consistentes às constantes de cor que você compõe, pra ficar fácil de identificar.

Pra você não esquecer a forma de uso dessa função, eu aconselho "brincar" bastante com essa função, ou seja, altere os valores das intensidades de vermelho, verde e azul e rode o programa pra ver as cores que você consegue compôr, quais combinações resultam na cor que você quer, etc. Outros exemplos de cores que você pode querer usar nos seus programas são:


* Lembre-se da sintaxe da chamada à função:

const int COR = makecol( int vermelho, int verde, int azul );


const int BRANCO = makecol( 255, 255, 255 );
const int VERMELHO = makecol( 255, 0, 0 );
const int VERDE = makecol( 0, 255, 0 );
const int AZUL = makecol( 0, 0, 255 );
const int AZUL_CLARO = makecol( 0, 255, 255 );
const int AMARELO = makecol( 255, 255, 0 );
const int ROXO = makecol( 255, 0, 255 );
const int CINZA = makecol( 128, 128, 128 );
const int MARROM = makecol( 128, 64, 0 );
const int LARANJA = makecol( 255, 128, 0 );
const int ROSA = makecol( 255, 128, 128 );


Enfim, o que importa é que agora você pode usar a constante BRANCO (ou qualquer outra que você tenha composto) em qualquer rotina que receba um argumento especificando a cor de um objeto, não só rotinas pra escrever texto, mas qualquer outra rotina usada pra desenhar gráficos primitivos. Vamos ver um exemplo na função textout_centre_ex a seguir.

A função que realmente escreve algo na tela é a textout_centre_ex. O que essa função faz? Ela escreve na tela aquilo que você quizer. Os argumentos devem ser passados na seguinte ordem: bitmap, fonte, string a escrever, coordenada x, coordenada y, cor da letra, cor do fundo.

Bitmap representa o bitmap onde você quer escrever o texto. Passe screen como argumento. screen é um ponteiro pré-definido na biblioteca Allegro que representa o bitmap da tela inteira. Então se quer desenhar ou escrever algo na tela, passe sempre esse ponteiro como argumento.

Fonte é a fonte que você deseja usar pra escrever na tela. Se você não carregou nenhuma fonte, a Allegro já tem uma fonte padrão, e já implementa um ponteiro pra ela que é o ponteiro font. Passe sempre esse ponteiro como argumento quando não tiver carregado outra fonte.

String é justamente a string que você deseja escrever.

Coordenada x e coordenada y são as coordenadas (posição) da tela onde você quer escrever a string. Eu passei como argumento as constantes pré-definidas da Allegro SCREEN_H e SCREEN_W, que representam a altura e largura da tela, respectivamente, e dividí esses valores por 2, fazendo com que a função desenhe a string bem no meio da tela.

Cor da letra é a cor da letra :P Passe como argumento a cor que você compôs anteriormente, ou você pode compôr uma cor dentro da própria chamada à função. Cor de fundo é a cor que aparece ao redor das letras, e aparecem "no fundo" no texto. Se você passar 0 (zero), não vai aparecer cor de fundo nenhuma.

Enfim, por último, a função readkey, que não recebe nenhum argumento, simplesmente "trava" a execução do programa aguardando o pressionamento de alguma tecla. Pressionando qualquer tecla, o programa encerra.

Ah, mais um detalhe, quase ia esquecendo: Você reparou que depois da função main existe um END_OF_MAIN(), né? Pois então, isso nada mais é do que uma macro necessária quando você compila o código usando os compiladores gcc ou g++ (que são os que vêm com o ambiente Dev-C++ por padrão). Lembre-se de que isso não é uma função, portanto, não acrescente o ponto-e-vírgula (;) no final! Mas você não precisa se preocupar com essa macro, porque ela não afeta de forma alguma na execução do seu programa e não tem utilidade nenhuma pra nós (só pro compilador). O importante é que você não deve esquecer de acrescentar isso sempre no final (depois de fechar chaves) da função main.

E terminou o tutorial Hello World em C++ com Allegro. Espero que vocês fucem bastante nesse código e aprendam mais coisas com ele.

E mais pra frente eu vou escrever outros artigos sobre programação em C++ usando Allegro, por exemplo, vou escrever um tutorial mostrando como carregar imagens de arquivos de bitmap, como carregar novas fontes pra escrever, como usar sons e música no programa, como usar rotinas do mouse, etc. Então volte sempre :P


Quer algo mais avançado, como um exemplo de um jogo (protótipo) em Allegro?

Aprenda a programar jogos no protótipo do jogo Glitch's Labyrinth


Bom, qualquer dúvida me perguntem.
Até logo!