Allegro para Iniciantes


Tutorial de Allegro com C++ utilizando o BloodShed DevC++
Por: Thiago "weissengeist" | [email protected]
Colaboradores: rodrigozk | [email protected]
gamemasterbr | [email protected]


Objetivo: O objetivo deste tutorial é contribuir para que interessados em desenvolvimento de jogos possam iniciar seus estudos de maneira objetiva. Este tutorial apresenta os conceitos básicos de programação gráfica 2D, voltada para jogos. Por sua simplicidade, o Allegro é o ponto de partida para iniciação à programação de jogos, mas é bom ressaltar que jogos comerciais são desenvolvidos com API's mais avançadas que oferecem muitos outros recursos. Para o desenvolvimento de um jogo, por mais simples que seja, é necessário muito estudo e dedicação. Este tutorial não ensina a criar jogos, mas provavelmente vai dar uma boa noção do funcionamento de funções comuns em muitas das bibliotecas gráficas recomendadas para o desenvolvimento. Ao final deste estudo, o leitor deverá ser capaz de:

Requerimentos:

Instalação: Iniciando nosso estudo, vamos instalar o DevC++ e o pacote do Allegro. Depois iremos testar um código padrão para verificar se a instalação foi feita corretamente.

- Clique duas vezes no programa de instalação do BloodShed DevC++ e faça a instalação;



- Clique duas vezes no pacote do Allegro e faça a instalação utilizando o Packman*;
(* Packman é o gerenciador de pacotes de atualização do DevC++, é apenas um assistente de instalação).



- Se você preferir, pode instalar o pacote do Allegro pelo próprio DevC++, para isso, clique no menu Ferramentas e escolha Package Manager:



(Essa opção irá abrir um assistente de instalações de pacotes do DevC++)

- Clique no botão Install e selecione o caminho onde você salvou o pacote de instalação do Allegro:



- Siga todo o processo de instalação:


(DevC++ Package Installation Wizard)

- Agora, certifique-se de que o Allegro foi instalado com sucesso. Crie um Novo Projeto no DevC++, Selecione a aba MultiMedia, e clique em Allegro Application(static):


(Selecione o tipo de aplicação na aba MultiMedia, nomeie o Projeto e clique em OK)

Após selecionar o Tipo de projeto e nomeá-lo, clique em Ok. O programa pedirá que você salve o projeto. Considere criar uma pasta com o nome do projeto onde você irá salvar todos os arquivos fonte e classas do programa, assim como imagens e sons. Neste projeto não iremos gerar tantos arquivos, pois é apenas um projeto teste para verificar se o pacote foi instalado corretamente. Então escolha um diretório, salve o projeto e o arquivo main.cpp.

Agora pressione F9 ou clique no botão Compilar & Executar. O código padrão será compilado e executado pelo DevC++ e se tudo estiver correto, seu programa não apresentará erros nem warnings, e uma janela vazia será mostrada:


(Janala vazia gerada pelo código padrão da aplicação Allegro)

- Utilize a tecla ESC para fechar a janela.

- Apenas a título de conhecimento, veja o código gerado com comentários:

#include <allegro.h> /* Adiciona as funções do Allegro */

/* As 2 linhas seguintes são chamadas de funções por prototipação */
void init();
void deinit(); int main() { /* Essa linha vai iniciar o programa assim como em C/C++ */
init(); /* Essa linha chama a função que inicializa as opções de vídeo*/
while (!key[KEY_ESC]) { /* enquanto a tecla pressionada for diferente de ESC a janela continua ativa*/

/* put your code here (adicionaremos nosso código aqui)*/
}

deinit(); /* função para limpar o buffer */
return 0 ; /* Finaliza o Programa sem erros*/
}
END_OF_MAIN(); /* Este é o comando utilizado para finalizar a função main() */ void init() { /* declaração da função*/
int depth, res; /* variáveis da função*/
allegro_init(); /* chama função do allegro */
depth = desktop_color_depth(); /* Atribuição de valor tirado de função*/
if (depth == 0 ) depth = 32 ; /* verifica valor, caso ele seja zero, a variável receve um valor pré-estipulado*/ set_color_depth(depth); /* função de utilização de cores, recebe valor pré-estabelecido */
res = set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640 , 480 , 0 , 0 ); /* Detecta placa de vídeo e
define resolução(640x480) */
if (res != 0 ) { /* so res for diferente de zero, é por que houve erro */
allegro_message(allegro_error); /* então é exibida uma mensagem de erro gerada pela função */
exit( -1 ); /* sai do programa informando erro */
}
/* as 3 linhas a seguir, são funçoes para tempo, utilização de teclado e mouse */
install_timer();
install_keyboard();
install_mouse();
/* add other initializations here (se for necessário, tem como adicionar outros tipos) */
} void deinit() { /* a função que foi prototipada acima */
clear_keybuf(); /* função para limpar o buffer do teclado */
/* add other initializations here (se for necessário, tem como adicionar outros tipos) */

}

(Código de main.cpp do projeto de exemplo com comentários)


Pronto, agora podemos começar com exemplos de utilização do Allegro.

A Sintaxe da Biblioteca: Vamos agora entender os principais comandos do Allegro. Estudaremos as funções de inicialização da biblioteca, da placa de vídeo e do teclado. Veremos também a função END_OF_MAIN(), que é a função necessária para indicar o fim de main. Para um estudo deste assunto iremos escrever um código totalmente novo. Então apague todo o conteúdo do arquivo main.cpp, do projeto que você acabou de criar, e siga as instruções a seguir.

- Vamos carregar protótipos e as difinições do Allegro, carregando o arquivo allegro.h:

#include <allegro.h>

- Como sabemos, ao declarar o arquivo de cabeçalho, teremos acesso às funções pré programadas que facilitam o desenvolvimento do código. O arquivo incluído foi allegro.h, que é a biblioteca gráfica a qual estamos estudando.

- Vamos agora declarar a função principal do nosso programa, a main():

#include <allegro.h>

int main() {

}

- Agora vamos fazer as definições e chamadas de funções importantes para a utilização do Allegro. A primeira função que devemos chamar é allegro_init(), que inicializará as funções da biblioteca. Logo após esta função, devemos chamar uma função para interpretar os comandos dos dispositivos de entrada, no nosso caso, a função install_keyboard(), referente ao teclado, e se for necessário, outros dispositivos de entrada, como por exemplo o mouse. A função install_keyboard() interpreta os valores do teclado de forma diferente das funções de input padrão de outras bibliotecas, como por exemplo, stdio.h entre outras. Mais definições da função, serão abordadas no tópico referente a movimentação de bitmaps com o teclado. Vejamos agora a utilização das funções:

#include <allegro.h> 

int main() { allegro_init();
install_keyboard();
}


- O próximo passo, está relacionado às definições de video. Vamos definir atravéz da utilização da função set_color_depth(), qual será a profundidade de cores utilizada. Essa função pode receber valores pré estabelecidos de 8, 15, 16, 24 e 32 cores. Este número, é regido por RGB, ou seja, variação de tonalidade de 3 cores primárias que possibilitam a utilização de outras cores. O significado de RGB é na verdade Vermelho(Red), Verde(Green) e Azul(Blue), e é utilizado como padrão para preenchimento de cores em Bitmaps. Exemplo:


(A côr vermelha é formada atravez da RGB [255,0,0] como mostra a imagem)

- Na imagem acima, vemos o princípio da utilização de RGB. Ao Vermelho foi atribuido o número máximo de tonalidade, enquanto ao Verde e Azul, não foi atribuido nenhum número. Como a tonalidade do Verde e Azul é nula, o Vermelho não se mistura com nenhuma outra cor, permanacendo nesta tonalidade.

- Voltando ao Allegro, o que temos que fazer, é informar à função set_color_depth(), quantos bits de cores serão utilizados:

set_color_depth(32);


- A função set_color_depth() deve ser utilizada sempre antes da função set_gfx_mode(). Caso contrário, as cores de algum Bitmap, não serão exibidas corretamente.

- A próxima definição de vídeo a ser feita, é a definição da placa de vídeo e de sua resolução. Para isso utilizaremos a função set_gfx_mode(), que tem como parâmetro inicial a detecção do modo de vídeo, a definição da resolução em que a aplicação será exibida:

set_gfx_mode(GFX_AUTODETECT, 640 , 480 , 0 , 0 );


- Na linha acima, vemos a função sendo utilizada, com o parâmetro de detecção automática da placa de vídeo com uma resolução 640x480. Os proximos campos, onde vemos dois zeros, são respectivamente a altura e largura virtuais da tela, ou seja, partes do mapa de um jogo que não aparecem no display. Estas áreas virtuais são acessadas por meio de uma função de scrowling, ou seja, rolamento de tela. Neste exemplo não utilizaremos a área virtual, por isso não daremos importância para ela agora.

- Veremos agora alguns dos modos de vídeo possíveis e suas descrições:

GFX_TEXT retorna para o modo texto
GFX_AUTODETECT faz com que o Allegro escolha o driver gráfico mais apropriado (normalmente tem problemas com placas de vídeo mais recentes)
GFX_VGA modo VGA (320x200, 320x100, 160x120, 80x80)
GFX_MODEX uma versão planar do modo VGA (tweaked)
GFX_VESA1 usa o driver VESA 1.x
GFX_VESA2B usa o driver VBE 2.0 em modo banked
GFX_VESA2L usa o driver VBE 2.0 com framebuffer linear
GFX_VESA3 usa o driver VBE 3.0
GFX_VBEAF usa o acelerador de hardware API VBE/AF
GFX_XTENDED usa o driver 640x480 unchained


- Como podemos perceber, os modos de video acima são definições divididas em duas partes, GFX, que se refere ao modo gráfico, e os modos propriamente ditos, como por exemplo AUTODETECT. Porém, existe outro sub-parâmetro pode ser utilizado; caso você queira deixar seu jogo em modo fullscreen(tela cheia), você deve declarar o modo, e no final acrescentar o sub-parâmetro FULLSCREEN. Caso não o faça, a função irá assumir default, executando seu jogos em uma janela. Você pode especificar que quer seu programa especificamente em uma janela acrescentando WINDOWED. Veja exemplos:

set_gfx_mode(GFX_AUTODETECT, 640 , 480 , 0 , 0 ); /* default */
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640 , 480 , 0 , 0 ); /* força janela */
set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 640 , 480 , 0 , 0 ); /* força fullscreen */


- Uma vez definidos estes parâmetros, podemos iniciar uma rotina para inserir os gráficos. Como estamos utilizando a biblioteca allegro.h, não podemos exibir texto da mesma forma que fazemos com cout ou printf(), pois não fazem parte desta biblioteca. Para imprimir texto utilizaremos o seguinte comando:

textout(screen, font, "texto", 1,1, makecol(255,0,0 ) );


- Vamos analizar a função textout() e seus parâmetros:

- Existem outras funções para exibição de texto, porém, não serão exploradas neste tuturial introdutório. Mais informações sobre exibição de texto podem ser encontradas nos links relacionados no final desta página.


- Vamos ver como fazer para inserir estes códigos em nosso programa utilizando a diretiva de condição while():

#include <allegro.h> 

int main() { allegro_init();
install_keyboard();

set_color_depth(32);
set_gfx_mode(GFX_SAFE, 800 , 600 , 0 , 0 );
while(!key[KEY_ESC]) {
textout(screen, font, "texto", 1,1, makecol(255,0,0 ) );
};
return 0;
}
(O código acima não pode ser executado ainda pois falta a função END_OF_MAIN())

- Agora vamos ver como fazer para inserir uma imagem na janela. O procedimento é um pouco mais complexo, porém, é muito simples de se fazer. O primeiro passo para se exibir uma imagem, é ter uma imagem, então, vamos criar uma para nosso exemplo:


(Imagem a ser utilizada no exemplo, formato bmp de 24 bits)

O procedimento para adicionar a imagem são:

1
2
3

PALETTE pal; /* declaração uma variável tipo PALETTE */
BITMAP *img = load_bitmap("c:\\teste.bmp",pal);/* Ponteiro BITMAP carrega imagem */
draw_sprite(screen, img, 30,80 ); /* função para imprimir imagem */


1: Aqui temos a declaração da variável pal, tipo PALETTE, que é utilizada na linha seguinte também. Variáveis do tipo PALETTE, são utilizadas para definir as cores que o BITMAP está utilizando. O Allegro oferece algumas variáveis PALETTE padrão que podem facilitar o trabalho dos programadores de diversas formas; Neste caso, a utilização de pal torna-se desnecessária pois estamos utilizando 32 bits e poseriamos utilizar o argumento NULL. A utilização de uma variável tipo PALLETE não está errada neste caso, porém não há necessidade. Quando a profundidade de cores é de 8 bits(256 cores), torna-se necessário utilizar uma variável tipo PALETTE, para definir as cores que serão utilizadas. Existem formas de manipular a Paleta de Cores, porém não as abordaremos neste tutorial. No nosso exemplo vamos utilizar a paleta mesmo sem a sua necessidade.

2:
Nesta linha temos a declaração de um ponteiro do tipo BITMAP, que nomeamos *img. Esta variável recebe, atravéz da função load_bitmap(), o arquivo de imagem que iremos carregar, teste.bmp, seguido do parâmetro pal, descrito acima.

3: A função draw_sprite() é a função que carrega a imagem na tela. Seus parâmetros são similares às da função textout(), porém não utiliza os parâmetros font e makecol(r,g,b). Mas em contrapartida, utiliza as declarações feitas nas duas linhas anteriores. Nesta linha, o parâmetro img
é a imagem propriamente dita, e os números a seguir são coluna e linha respectivamente.

- Agora vamos inserir estas linhas em nossso código; também vamos reduzir consideravelmente o tamanho do código se comparar-mos com o código gerado pelo automaticamente pelo Allegro. Vejamos como fica o novo código:

#include <allegro.h> 

int main() {
allegro_init();
install_keyboard();
set_color_depth(
32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED,
640,480,0,0); PALETTE pal; BITMAP *img = load_bitmap("c:\\teste.bmp",pal); while(!key[KEY_ESC]) { clear_bitmap(img);
textout(screen, font,
"Exemplo", 30,20, makecol(255,0,0 ) );
draw_sprite(screen, img,
30,30 );
};
return
0;
}

(Código alterado para exibir imagem e texto)

No código acima, pode-se notar a diferença do código padrão do Allegro mostrado anteriormente, isto por que várias outras funções que não utilizaremos foram retiradas, assim como install_mouse(), clear_keybuf() entre outras; ou seja, o código que você está vendo acima é o mais enxuto possível para imprimir uma imagem e um texto numa janela. A definição da janela está em 640x480, mas poderia ser mudada para qualquer resolução desejada, contanto que a placa de vídeo seja capaz de executar na resolução desejada.

- Um ultimo comando deve ser incluso ao código para para que o programa execute corretamente. A função END_OF_MAIN() faz com que o Allegro entenda que é o fim da função main(), ou seja, o fim do programa. A não inclusão da função END_OF_MAIN() fará com que o DevC++ apresente uma mensagem de erro. Observe o código completo com comentários:

#include <allegro.h> /* Adiciona as funções do Allegro */ 

int main() {
allegro_init(); /* função de inicialização do allegro */
install_keyboard(); /* função de inicialização de teclado, agora dentro da main() */
set_color_depth(32); /* função de profundidade de cores, definição em 32 cores */
set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0); /* seleciona o tipo da placa e resolução do vídeo */ PALETTE pal; /* declaração uma variável tipo PALETTE */ BITMAP *img = load_bitmap("c:\\teste.bmp",pal);/* Ponteiro BITMAP img e atribui seu valor */ while(!key[KEY_ESC]) { /* Enquanto tecla diferente de ESC */
clear_bitmap(img); /* Limpa o ponteiro */
textout(screen, font, "Exemplo", 30,20, makecol(255,0,0 ) ); /* função para imprimir texto */
draw_sprite(screen, img, 30,30 ); /* função para imprimir imagem */
}; /* fim do while() */
return 0; /* Sai da função main() sem erros fazendo com que o programa finalize */
}
END_OF_MAIN() /* Finaliza a execução do Allegro neste programa */

(Código comentado e pronto para execução)

- Ao executarmos este código, a seguinte janela será exibida:


(Janela de aplicação Allegro exibindo a palavra 'Exemplo' e o desenho de um Aviãozinho)

Desenhando Bitmaps: Agora vamos ver algumas das funções de desenho geométrico primitivo do Allegro. Estas funções são utilizadas para desenhar retas, circulos, retangulos e diversas outras formas atravez de pixels. O que se deve saber a respeito deste tipo de desenho, é a forma com que ele é exibido.

- Vamos apagar uma parte de nosso código, deixando apenas a inicialização das funções do Allegro e a diretiva while():


#include <allegro.h> 

int main() {
allegro_init();
install_keyboard();
set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0); while(!key[KEY_ESC]) {

};
return 0;
}
END_OF_MAIN();


- Para desenhar uma imagem, é necessário criar um ponteiro do tipo BITMAP, que será utilizado como um buffer para a execução da função. Neste ponteiro, será definido o tamanho máximo da imagem que será desenhada. A definição e feita atravéz da função create_bitmap(), que recebe como parâmetro dois números inteiros referente à resolução utilizada na janela. Iremos então criar um BITMAP:

#include <allegro.h> 

int main() {
allegro_init();
install_keyboard();
set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0);
BITMAP *img = create_bitmap(640,480); /* Cria o BITMAP */ while(!key[KEY_ESC]) {

};
return 0;
} END_OF_MAIN();

- O próximo passo será definir a dimensão e a cor de nossa linha. Para isto, iremos utilizar a função padrão de criação de linha do Allegro, line(), que recebe como parâmetro o ponteiro que criamos(BITMAP), os pontos de início e fim da linha(int), e a função de côr da linha(makecol()). Desta forma a sintaxe da função seria esta:

line(BITMAP *img, int x_inicial, int y_inicial ,int x_final,int y_final, makecol(int,int,int ));

- E esta seria sua utilização:

line(img, 10,10, 100,100, makecol(255,0,0 ) );


- Agora vamos entender como são desenhados os Bitmaps, comparando o plano de Bitmaps(se é que podemos chamar assim), e o plano Cartesiano:


(Comparação entre plano cartesiano e Plano de Pixels utilizado por Bitmaps)

- Como podemos perceber, os vetores X e Y, estão posicionados da maneira diferente quando comparamos os planos, desta forma, quando desenharmos a linha, devemos ter em mente a direção do traço. Vamos adicionar a função ao nosso código:

#include <allegro.h> 

int main() {
allegro_init();
install_keyboard();
set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0);
BITMAP *img = create_bitmap(640,480); /* Cria o BITMAP */ while(!key[KEY_ESC]) { clear_bitmap(img);
line(img, 10,10, 100,100, makecol(255,0,0 ) ); /* Define dimensão e cor da linha */
};
return 0;
}
END_OF_MAIN();


- Após feita a definição das dimensões de nossa linha, devemos chamar a função blit(), que é responsável pela impressão da linha. Esta função recebe como parâmetros o BITMAP que criamos, que na verdade é a imágem propriamente dita; em seguida, um outro ponteiro, que é definido pela função set_gfx_mode(), o ponteiro screen, seguido de quatro campos inteiros, e por último, a largura máxima e altura máxima da janela, ou seja, a resolução. Esta é a sintaxe da função blit():

blit(BITMAP *bitmap, BITMAP *bitmap,int,int,int,largura,altura);


- E é utilizada assim:

blit(img, screen,0,0,0,0,640,480);


- Estes quatro campos inteiros que foram declarados com zero, são na verdade informações das posições de X e Y que são passados à biblioteca draw.h, utilizada pelo Allegro, porém neste exemplo estas definições não são aplicáveis, pois a definição feita na função line() já é suficiente para nosso exemplo. Agora vamos incluir esta função ao nosso código:

#include <allegro.h> 

int main() {
allegro_init();
install_keyboard();
set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0);
BITMAP *img = create_bitmap(640,480); /* Cria o BITMAP */ while(!key[KEY_ESC]) { clear_bitmap(img);
line(img, 10,10, 100,100, makecol(255,0,0 ) ); /* Define dimensão e cor da linha */ blit(img, screen,0,0,0,0,640,480); /* Imprime a linha */
};
return 0;
}
END_OF_MAIN();

(Código comentado para geração de uma linha em diagonal utilizando Allegro)

- Executando este código, teremos o seguinte resultado:


(Janela de aplicação Allegro exibindo uma linha diagonal com base nos valores de X e Y iniciais e finais da função)

- Como mencionado anteriormente, existem outras funções gráficas específicas para construção de figuras geométricas. Estas funções funcionam da mesma forma que funções matemáticas e são relativamente simples de se executar, basta que o programador tenha conhecimento de matemática, especificamente de geometria. Vamos ver alguns exemplos das funções:

- Círculo:
O circulo, é feito atravéz da função circle(), que tem como parâmetro o ponteiro BITMAP, sua posição X e Y, seu raio e finalmente sua côr:

circle(img, 15,150,100, makecol(255,0,0 ) );

- Retângulo: O retângulo, é construido com a função rect(), e recebe como parâmetros um ponteiro de tipo BITMAP, as posições de X e Y do seu início que é no lado superior esquerdo, a posição de terminação, que é o lado inferior direito, e sua côr:

rect(img, 10,10, 100,100, makecol(255,0,0 ) );


- Preenchimento: Figuras como o retângulo e círculo, não tem preenchimento, sendo desenhadas apenas suas bordas, desta forma o programador terá que utilizar a função de preenchimento referente a figura para que a mesma tenha seu interior preenchido com alguma côr, caso contrário será apenas uma borda. Vejamos um exemplo:

#include <allegro.h> 

int main() {
allegro_init();
install_keyboard();
set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0);
BITMAP *img = create_bitmap(640,480); /* Cria o BITMAP */ while(!key[KEY_ESC]) { clear_bitmap(img);
rect(img, 10,10, 100,100, makecol(255,0,0 ) ); /* Define dimensão e cor da retêngulo */ blit(img, screen,0,0,0,0,640,480); /* Imprime o retângulo */
};
return 0;
}
END_OF_MAIN();

(código para gerar o retângulo)

- Executando este código, temos a seguinte janela:


(Janela de aplicação Allegro exibindo um retângulo)

- Para inserir uma cor de preenchimento, devemos utilizar a seguinte função:

rectfill(img, 11,11,99,99, makecol(0,0,255 ) );


- Note que na função rectfill(), os valores das posições de X e Y estão diferentes da função anterior. As coordenadas do preechimento devem ser calculadas para que desenho não sobreponha sua borda. O preenchimento será um pixel menor em todos os lados. O retângulo está sendo desenhado um pixel abaixo no eixo Y e um pixel a frente no eixo X; e sua terminação está um pixel acima no eixo Y e um pixel antes no eixo X. Desta forma temos a seguinte imagem:


(Janela de aplicação Allegro exibindo um retângulo de bordas vermelhas e preenchimento azul)

- Triângulo: O triângulo é uma figura geométrica com 3 pontas, isto significa que para desenharmos um triângulo, além de chamar o ponteiro BITMAP para a construção da imagem, deveremos declarar 3 vértices, de posições X e Y, e por último a côr do triângulo. Esta figura geométrica não é formada por linhas, e sim uma imagem sólida, não podendo ser utilizada a função de preenchimento como nos desenhos anteriores. A função do triângulo é triangle(), e sua sintaxe é:

triangle(img,150,150,350,350,10,350, makecol(255,0,0 ) );

- Retas: Além da linha desenhada no primeiro exemplo, com a função line(), existem dois outros tipos de linhas que podem ser utilizados no Allegro; linhas verticais, vline(), e linhas horizontais, hline(), que tem como parâmetro o ponteiro que fará a contrução da imagem, o ponto onde será iniciada a reta, de acôrdo com o tipo escolhido, os pontos X e Y que definirão a extensão da reta, e por último, a cor da linha:

// sintaxe
void
vline(BITMAP *bitmap, int x1, int y1, int x2, makecol(int,int,int ) );

void hline(BITMAP *bitmap, int y1, int y2, int x1, makecol(int,int,int ) );
// utilização
vline(img, 10,10,100, makecol(255,0,0 ) );
hline(img, 10,10,100, makecol(255,0,0 ) );

- Exisitem outras funções para gráficos geométricos no Allegro, porém neste Tutorial, apenas estas serão abordadas. Se quiser aprender mais sobre estas e outras funções, visite um dos links relacionados no final desta página.

Mover Bitmaps com o Teclado: Agora chegamos numa parte um pouco mais complexa, e para obter resultados com a leitura e necessário que tenha lido os tópicos anteriores. Vamos falar do input pelo teclado, especificamente da forma com que os valores das teclas são obtidos. Vamos aprender como movimentar bitmaps atravez do teclado. Antes de começar, é importante seber de alguns conceitos de utilização do teclado.

- A biblioteca Allegro não possui uma função que armazena o valor digitado pelo usuário em uma variável, como por exemplo a função
scanf(). O Allegro tem uma forma diferente de representar os valores das teclas, e para ler as mesmas, é necessário a utilzação de uma estrutura alternativa.

- Primeiramente, vamos observar uma forma de utilização da array
key, que é uma espécie de índice de caracteres do Allegro. Cada tecla tem um valor constante correspondente a ela. Para exemplificar, vamos utilizar uma parte do código que fizemos anteriormente, porém, vamos nos concentrar nos parâmetros da função while():

while(!key[KEY_ESC]) { /* Enquanto a tecla não for Esc faça o que está no bloco */ 

};

- O parâmetro desta função é uma array, key, que está na posição [KEY_ESC], que corresponde a tecla ESC de seu teclado. Esta array é utilizada dentro de uma função da biblioteca Allegro, para detectar, por meio de scancode, se uma certa tecla está pressionada ou não(0 ou 1). Atravéz de valores do ponteiro key, pode-se utilizar teclas específicas para certas interações entre o programa e o usuário. Para isso, o programador deverá saber quais são os valores correspondentes as teclas. Vejamos então o conteúdo da array nesta tabela:

Tecla
Código na Array

A, B ... Z

KEY_A, KEY_B...KEY_Z
Teclado Numérico 0 a 9 KEY_0_PAD ... KEY_9_PAD
Teclado Normal 0 a 9 KEY_0 ... KEY_9
Esc KEY_ESC
Enter KEY_ENTER
Seta para a Direita KEY_RIGHT
Seta para a Esquerda KEY_LEFT
Seta para Cima KEY_UP
Seta para Baixo KEY_DOWN
Pause KEY_PAUSE
Barra de Espaço KEY_SPACE
Print Screen KEY_PRTSCR
Shitf Esquerdo KEY_LSHIFT
Shift Direito KEY_RSHIFT
Control Esquerdo KEY_LCONTROL
Control Direito KEY_RCONTROL
Alt esquerdo KEY_ALT
Alt Direito KEY_ALTGR
(Codificação das teclas mais importantes contidas na array key)

- Existem outras teclas que não são mencionadas neste tutorial, pois não serão usadas; mas acredito que esta explicação superficial a respeito da array key, é suficiente por enaquanto.

- Vamos escrever um código que use algumas das teclas mencionadas acima. Mas para isso, vamos entender como fazer para movimentar um Bitmap da forma mais simples.

- Para se desenhar um Bitmap, é necessário informar certos parâmetros à sua função. O principal parâmetro para se movimentar um Bitmap, é a sua posição na tela, ou seja, suas coordenadas X e Y, que dirão onde o Bitmap será desenhado. Então, podemos escrever uma estrutura que vai modificar o valor de X e Y, caso seja pressionada uma tecla de movimentação, definida pelo programador. Vamos exemplificar:

if(key[KEY_RIGHT]) {
x++;
clear_bitmap(img);
circlefill(img,x,y,30,makecol(255,255,255));
blit(img,screen,0,0,0,0,640,480);
}

- O código acima, verifica se a seta para direita foi pressionada; como vimos na tabela de valores da array key, a tecla para direita é representada por KEY_RIGHT. A função circlefill() utiliza variáveis no lugar de valores para X e Y. Caso a seta para direita seja pressionada, o valor de X, será acrecido em 1(um), a circunferência será apagada e redesenhada de acordo com o novo valor de X. Essa estrutura é a estrutura básica para movimento de Bitmaps ou sprites, porém pode ser amplamente melhorada. Vamos criar um código que mostre a leitura das quatro setas direcionais do teclado:

#include <allegro.h> 
#include <stdio.h>

int main() {
allegro_init();
install_keyboard();
set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0);
int x=300, y=190;
BITMAP *img = create_bitmap(640,480);
char txt[40]; sprintf(txt,"X: %d Y: %d", x, y);
circlefill(img,x,y,30,makecol(255,255,255));
blit(img,screen,0,0,0,0,640,480);
textout(screen,font,txt,5,5,makecol(255,0,0));
while(!key[KEY_ESC]) { clear_bitmap(img);
if(key[KEY_RIGHT]) {
x++;
clear_bitmap(img);
circlefill(img,x,y,30,makecol(255,255,255));
blit(img,screen,0,0,0,0,640,480);
sprintf(txt,"X: %d Y: %d", x, y);
textout(screen,font,txt,5,5,makecol(255,0,0));
}
if(key[KEY_LEFT]) {
x--;
clear_bitmap(img);
circlefill(img,x,y,30,makecol(255,255,255));
blit(img,screen,0,0,0,0,640,480);
sprintf(txt,"X: %d Y: %d", x, y);
textout(screen,font,txt,5,5,makecol(255,0,0));
}
if(key[KEY_UP]) {
y--;
clear_bitmap(img);
circlefill(img,x,y,30,makecol(255,255,255));
blit(img,screen,0,0,0,0,640,480);
sprintf(txt,"X: %d Y: %d", x, y);
textout(screen,font,txt,5,5,makecol(255,0,0));
}
if(key[KEY_DOWN]) {
y++;
clear_bitmap(img);
circlefill(img,x,y,30,makecol(255,255,255));
blit(img,screen,0,0,0,0,640,480);
sprintf(txt,"X: %d Y: %d", x, y);
textout(screen,font,txt,5,5,makecol(255,0,0));
}
}; return 0;
}
END_OF_MAIN();

(Estrutura simples para movimento de uma circunferência utilizando o teclado)

- O código utiliza sprintf(), uma função da biblioteca stdio.h que guada texto e valores de variáveis em uma string. Essa string foi usada para que a função textout() pudesse imprimir as posições de X e Y dinamicamente.

Colização entre Bitmaps: Agora estudaremos a Colizao entre Bitmaps; para isso, vamos entender o que vem a ser o termo colisão de bitmaps antes de criarmos nosso código de simples colisão.

- O que nós entendemos por colisão no mundo real, é o encontro físico de dois ou mais objetos ou superficies; pode ser considerado colisão, o momento que um veículo se choca com um poste, ou quando uma pessoa pisa no chão ao caminhar. A colisão no mundo real pode ser explicada por uma das leis da física que diz que dois corpos não poderm ocupar o mesmo espaço ao mesmo tempo.
Da mesma forma que a colisão física; a colisão de bitmaps acontece quando dois ou mais objetos ou superfícies se tocam, ou seja, quando existem pixels de diferentes bitmaps sendo desenhados em uma mesma coordenada. Na colisão virtual, as leis da física tem que ser ensinadas ao computador para que os bitmaps não se sobreponhão.

- Como forma de ilustração rústica e superficial, vamos considerar um retângulo que foi definido com quatro pontos no plano de Bitmaps: 260,190(x e y superiores),360 e 290(x e y inferiores). Para esse retângulo, as coordenadas não serão alteradas. Criaremos então outro retângulo, que será movido pelo teclado, sendo baseado no código utilizado para movimentação do circulo visto anteriormente. Neste código, o círculo será substituido por um retângulo. Este retângulo terá coordenadas que serão armazenadas nas variáveis tipo x, y, x2 e y2.

- O que iremos fazer, é definir uma área na tela que o retângulo manipulável reconhecerá como barreira. Para fazer este tipo de definição, vamos comparar o valor de X e Y do nosso retângulo com as posições do retângulo estático, e se o nosso retângulo invadir esta barreira, ele será empurrado para fora de acordo com a direção que ele tentou entrar. Vamos ver o código completo para depois analizarmos:

#include <allegro.h>

int main() {
allegro_init(); install_keyboard(); set_color_depth(32); set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0); int x=275, y=75, x2=340, y2=140; PALETTE pal; BITMAP *img = create_bitmap(640,480); rectfill(img,x,y,x2,y2,makecol(0,0,255)); /* Retângulo Manupulável Azul */ rectfill(img,260,190,360,290,makecol(255,0,0)); /* Retângulo Estático Vermelho */ blit(img,screen,0,0,0,0,640,480); while(!key[KEY_ESC]) { /* Movimentação por setas do teclado: Início */ if(key[KEY_RIGHT]) { clear_bitmap(img); x++;x2++; rectfill(img,x,y,x2,y2,makecol(0,0,255)); rectfill(img,260,190,360,290,makecol(255,0,0)); blit(img,screen,0,0,0,0,640,480); } if(key[KEY_LEFT]) { clear_bitmap(img); x--;x2--; rectfill(img,x,y,x2,y2,makecol(0,0,255)); rectfill(img,260,190,360,290,makecol(255,0,0)); blit(img,screen,0,0,0,0,640,480); } if(key[KEY_UP]) { clear_bitmap(img); y--;y2--; rectfill(img,x,y,x2,y2,makecol(0,0,255)); rectfill(img,260,190,360,290,makecol(255,0,0)); blit(img,screen,0,0,0,0,640,480); } if(key[KEY_DOWN]) { clear_bitmap(img); y++;y2++; rectfill(img,x,y,x2,y2,makecol(0,0,255)); rectfill(img,260,190,360,290,makecol(255,0,0)); blit(img,screen,0,0,0,0,640,480); } /* Fim da movimentação com Teclado e início das verificações de posicionamento */ if((x >= 259) && (x <= 360)) { if((y2 >= 190) && (y2 <= 354)) { clear_bitmap(img); x++;x2++; rectfill(img,x,y,x2,y2,makecol(0,0,255)); rectfill(img,260,190,360,290,makecol(255,0,0)); blit(img,screen,0,0,0,0,640,480); textout(screen,font,"colisao detectada",250,1,makecol(255,255,0)); } } if((x2 >= 259) && (x2 <= 360)) { if((y >= 125) && (y <= 285)) { clear_bitmap(img); x--;x2--; rectfill(img,x,y,x2,y2,makecol(0,0,255)); rectfill(img,260,190,360,290,makecol(255,0,0)); blit(img,screen,0,0,0,0,640,480); textout(screen,font,"colisao detectada",250,1,makecol(255,255,0)); } } if((y >= 190) && (y <= 290)) { if((x >= 194) && (x <= 359)) { clear_bitmap(img); y++;y2++; rectfill(img,x,y,x2,y2,makecol(0,0,255)); rectfill(img,260,190,360,290,makecol(255,0,0)); blit(img,screen,0,0,0,0,640,480); textout(screen,font,"colisao detectada",250,1,makecol(255,255,0)); } } if((y2 >= 190) && (y2 <= 290)) { if((x >= 196) && (x <= 359)) { clear_bitmap(img); y--;y2--; rectfill(img,x,y,x2,y2,makecol(0,0,255)); rectfill(img,260,190,360,290,makecol(255,0,0)); blit(img,screen,0,0,0,0,640,480); textout(screen,font,"colisao detectada",250,1,makecol(255,255,0)); } } }; return 0; } END_OF_MAIN()

(código de colisão simples não aprefeiçoado)

- Depois de executar o código pudemos perceber que o retângulo menor, de cor azul, pode ser movido pelas cetas do teclado, porém não entra na área do retângulo vermelho. Como podemos observar no código, existe uma sequencia de diretivas condicionais que comparam os valores das coordenadas dos dois retângulos, em todos os lados, fazendo com que eles sejam afastados para dar uma ideia de colisão física.

- O que fizemos foi uma simples comparação das posições, e definimos um procedimento que será executado no caso de um retângulo invadir o outro.

- Claro que este não é o melhor exemplo de uma detecção de colisão, porém, dá uma ideia superficial de como as colizões funcionam. Neste exemplo, foram utilizados retângulos por serem mais fáceis de se trabalhar, e evitam cálculos matemáticos mais compléxos, porém existem algorítimos específicos para certos tipos de colizao, os quais são mais trabalhosos e complexos para um tutorial destinado a iniciantes, que por sua vez foi escrito por um iniciante.

Utilização de Timer, Mouse e Som: Nesta ultima parte de nosso tutorial, vamos entrar em um conteúdo ainda mias complexo. Por isso, é necessário que os conceitos dos tópicos apresentados acima tenham sido compreendidos, e claro, atenção.

- Neste tópico, vamos estudar o funcionamento das funções install_mouse() e install_sound(), que dependem da função install_timer() para funcionar. Então, vamos ver uma a uma:


Timer: O Timer, é basicamente a função contadora de tempo no Allegro. Os eventos de tempo podem ter diversas utilizações, como por exemplo, contar o tempo que o jogador levou para passar um level de um jogo, ou coisas do tipo, porém, outras funções podem utilizar recursos do Timer.

- Os eventos de tempo, simulam um relógio, ou seja, contam o tempo atravéz de interrupção e retomada constante de uma determinada ação. O intervalo entre execução, parada e retomada de execução, é pré-estabelecido pelo programador. Num relógioa, os ponteiros são analógicamente programados, para executarem um movimento que será interrompido e logo em seguida executado novamente e assim por diante.

- Vamos ver os principais comandos de utilização do Timer e sua sintaxe correta, para isso, vamos utilizar nosso primeiro código, de criação de janela vazia e vamos alterá-lo:

#include <allegro.h> 

int main() {
allegro_init();
install_keyboard();

set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED,
640,480,0,0); while(!key[KEY_ESC]) {

};
return 0;
}
END_OF_MAIN();



- Logo abaixo da inicialização do Allegro, vamos inserir a chamada do Timer:

install_timer();


- Agora vamos inserir uma função que utilizaremos como um callback. Esta função não terá retorno, por que o mesmo não é relevante para a execução do programa; é uma função utilizada apenas constar na sintaxe, neste caso é recomendado que se utilize o modificador volatile como vemos na função. Exitem casos, onde a função callback utilizada pelo Timer tem utilidade real.

volatile int a = 0; /* variável global */
void func() { a++;
}



- O programa não tem como definir por si só, qual a função a ser utilizada pelo Timer, então, próximo passo é informar ao qual será a função e a variável a ser utilizada. Estas declarações são feitas dentro da função main():

LOCK_VARIABLE(a); /* variável */
LOCK_FUNCTION(func); /* função */


- Após definir a função e a variável, iremos inserir a seguinte linha de comando:

install_int();


- A função acima recebe dois parâmetros. Primeiro a função callback mostrada acima, seguida do intervalo de tempo em milisegundos. Então a função fica assim:

install_int(func(),100);


- Vejamos agora como fica o código acima com as funções de Timer inclusas:

#include <allegro.h> 

volatile int a = 0; /* variável global */
void func() { a++;
}

int main() {
allegro_init(); install_timer();
install_keyboard(); LOCK_VARIABLE(a);
LOCK_FUNCTION(func);
install_int(func(),100);
set_color_depth(
32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED,
640,480,0,0); while(!key[KEY_ESC]) {

};
return
0;
}

END_OF_MAIN();


- Após este procedimento, a execução deste programa será uma janela vazia, assim como a janela padrão gerada pela Allegro, a diferença é que as funções que utilizam eventos de tempo podem ser utilizadas agora.

Mouse: Agora que o Timer foi executado, vamos ver o procedimento para iniciar o mouse. O mouse nunca funciona sem o Timer.

- Após ter certeza de que o Timer está funcionando, podemos iniciar o Mouse. A função a seguir, serve para carregar os procedimentos do inicialização do Mouse

install_mouse();

- O próximo passo é criar um ponteiro do tipo Bitmap onde o cursor do mouse será desenhado, da mesma forma que as figuras geométricas primitivas. O comando utilizado para isso é:

BITMAP *img = create_bitmap(640,480);

- Para exibir o cursor utilizaremos uma função que recebe como parâmetro o ponteiro que criamos acima:

show_mouse(img);

- Vamos ver o código completo para que tenhamos uma idéia.

#include <allegro.h>

volatile int a = 0; /* variável global */
void func() { a++;
}

int main() { allegro_init();
install_timer(); install_mouse(); install_keyboard();
install_int(func(),100);
LOCK_VARIABLE(a); LOCK_FUNCTION(func); set_color_depth(
32); set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0); BITMAP *img = create_bitmap(640,480);
while
(!key[KEY_ESC]) { clear_bitmap(img);
show_mouse(img); }; return
0; } END_OF_MAIN();


- O Allegro tem procedimentos próprio para detectar qual botão foi pressionado, para isso, a função vai atribuir valores aos botões; que são 1 para o botão esquerdo e 2 para o botão direito. Para detectar o botão, o Allegro faz uma verificação do valor de mouse_b; a estrutura if() é a mais indicada para este tipo de verificação por questões de praticidade:

if(mouse_b & 1) { textout(screen,font,"botao direito",1,1,makecol(255,255,255));
}

- Num jogo, as posições X e Y do cursor do mouse são extremamente importantes em quase 100% dos casos. Por isso, a função do Mouse no Allegro, já tem essas posições dinamicamente armazenadas nas vairáveis mouse_x e mouse_y. Vejamos a utilização:

int main() {
//código... int x,y,x1,y1;
BITMAP *img = create_bitmap(640,480); if(mouse_b & 1) { x = mouse_x;
y = mouse_y;
if(mouse_b & 2) { x1 = mouse_x; y1 = mouse_y; rect(img,x,y,x1,y1,makecol(0,0,255)); }
} //código... }

- Ao executar este programa, as posições X e Y do cursor serão guardadas toda vez que o botão esquerdo for pressionado, e novamente armazenadas quando o direito for pressionado, e por fim desenhará um retângulo.

- Estas são as formas mais básicas de utilização do Mouse.

Sound: Agora veremos o procedimento de utilização do som. A função de som necessita do Timer para funcionar. Existem duas finalidades primárias para utilização de som; a música de fundo e os efeitos sonoros relacionados com ações do jogador. Para música de fundo o Allegro utiliza sons no formato Midi, e para os outros sons decorrentes de ações, podem ser utilizados outros tipos de arquivos, porém, formato Wave é o mais comum. Vamos agora ver como é o procedimento de inicialização do som e execução de arquivos de som.

- Assim como os outros dispositivos de entrada, temos que inicializar o som. Para isto vamos utilizar a função install_sound(), porém com alguns parâmetros:

install_sound(digi_card,midi_card,cfg_path);

- Como parâmetros desta função temos digi_card, que detecta driver de som digital que a placa está usando, em seguida temos midi_card, que detecta o driver de MIDI a ser utilizado. Por último temos cfg_path, que é utilizado para manter compatibilidade de versões mais antigas do Allegro; vamos deixar seu valor em NULL, pois não o utilizaremos.

- Assim como o vídeo, a configuração de som tem alguns valores pré-estabelecidos para entrar como parâmentros desta função. Vejamos alguns dos possíveis valores para digi_card e midi_card:

digi_card:

DIGI_AUTODETECT instrui o Allegro a escolher o driver de som
DIGI_NONE sem som digital
DIGI_SB auto-deteccção de placas Sound Blaster
DIGI_SB10 Sound Blaster 1.0 (8 bit mono)
DIGI_SB15 Sound Blaster 1.5 (8 bit mono)
DIGI_SB20 Sound Blaster 2.0 (8 bit mono)
DIGI_SBPRO Sound Blaster Pro (8 bit stereo)
DIGI_SB16 Sound Blaster 16 (16 bit stereo)
DIGI_AUDIODRIVE ESS AudioDrive
DIGI_SOUNDSCAPE Ensoniq Soundscape


midi_card:

MIDI_AUTODETECT instrui o Allegro a escolher o driver de MIDI
MIDI_NONE sem som MIDI
MIDI_ADLIB auto-detecção de sintetizadores Adlib ou Sound Blaster FM
MIDI_OPL2 sintetizador OPL2 (mono, usado em Adlib e Sound Blaster)
MIDI_2XOPL2 sintetizador OPL2 dual (stereo, usado em Sound Blaster Pro-I)
MIDI_OPL3 sintetizador OPL3 (stereo, usado em Sound Blaster Pro-II e acima)
MIDI_SB_OUT interface MIDI Sound Blaster
MIDI_MPU interface MIDI MPU-401
MIDI_DIGMID sample-based software wavetable player
MIDI_AWE32 AWE32 (EMU8000 chip)

- Vejamos como fica nossa função com um dos valores contidos nas tabelas:

install_sound(DIGI_AUTODETEC,MIDI_AUTODETECT,NULL);


- Vamos ver como carregar e executar arquivos do tipo Wave com o Allegro. Primeiramente, devemos ter um arquivo de som compatível com o Allegro. Os arquivos Wave podem ter até 16 bits, e devem ser carregados em ponteiros do tipo Sample.

- Vamos criar um ponteiro do tipo SAMPLE onde será carregado o nosso arquivo de som. Este ponteiro recebe uma função que indica o caminho do arquivo, load_wav().

SAMPLE *som = load_wav("c:\\som.wav");


- Para executar este som, vamos utilizar a função play_sample(), que recebe como parâmetro o ponteiro criado acima, o volume(0 à 255), o balanço(0 a 255), a frequência(que tem várias configurações, por exemplo 1000 que utiliza a mesma frequência que o arquivo foi gravado) e loop(0:sem loop, 1: loop infinito).

play_sample(som,255,90,1000,0);


- Para parar de tocar um sample, utiliza-se a função:

stop_sample(som);


- Onde som é o ponteiro carregado com o som.

- Vamos agora carregar e executar um arquivo no formato Midi. A execução de Midi é mais simples que a de um Sample, pois tem uma outra finalidade que consistem apenas em executar o arquivo com loop infinito, ou executá-lo apenas uma vez até que chegue ao fim do arquivo.

- Primeiramente, vamos criar o ponteiro onde será carregado o conteúdo do nosso arquivo de som; esse ponteiro é será do tipo MIDI, vamos chamá-lo de mid. Para carregar o arquivo de som, utilizaremos a função load_midi(), que tem como parâmetro a localização do arquivo:

MIDI *mid = load_midi("c:\\fundo.mid");

- Como vimos, o carregamento é similiar ao de um Sample. A execução também é similar, porém não requer a mesma quantidade de parâmetros; apenas o ponteiro do Midi, e se ele vai ter loop ou não:

play_midi(mid,1);

- Na linha acima vemos a função que executará o Midi até que o programa seja encerrado. Caso o segundo parâmetro fosse zero, o arquivo seria executado apenas uma vez.

- Para parar a execução de um Midi, utiliza-se a função:

stop_midi();

- Como o Allegro só executa um Midi de cada vez, não é necessário parâmetro para esta função. Este comando fará com que qualquer arquivo Midi em execução páre imediatamente.

- Vejamos agora um exemplo de utilização de um arquivo de som:

#include <allegro.h>      

volatile int i=0;

void imaismais() {
i++;
}

int main() {
allegro_init();
install_timer();
install_keyboard();
install_sound(DIGI_AUTODETECT,MIDI_AUTODETECT,NULL);
install_int(imaismais,100);
LOCK_VARIABLE(i);
LOCK_FUNCTION(imaismais);
set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0);
SAMPLE *som_w = load_wav("c:\\up.wav"),
*som_s = load_wav("c:\\down.wav"),
*som_a = load_wav("c:\\left.wav"),
*som_f = load_wav("c:\\right.wav");
MIDI *mid = load_midi("c:\\fundo.midi");
while(!key[KEY_ESC]) {
play_midi(mid,1);
if(key[KEY_W]) {
play_sample (som_w, 255, 128, 1000, 0);
}
if(key[KEY_A]) {
play_sample (som_a, 255, 128, 1000, 0);
}
if(key[KEY_S]) {
play_sample (som_s, 255, 128, 1000, 0);
}
if(key[KEY_D]) {
play_sample (som_d, 255, 128, 1000, 0);
}
};
return 0;
}
END_OF_MAIN();


- A partir de agora, você pode começar a escrever seus próprios códigos. Sobretudo, recomendo um estudo mais aprofundado da biblioteca, pois ela ainda oferece muitos recursos não explorados neste tutorial. Recomendo ainda um estudo aprofundado na linguagem C++, pois é essencial para a programação de jogos profissionais. Daqui para frente é com você; boa sorte e bons estudos.


· Agradecimentos:
Agradeço imensamente a rodrigozk, que pacientemente me ajudou a escrever este tutorial, mostrando-se interessado em melhorar a qualidade do material de referência na lingua portuguesa. Agradeço também a gamemasterbr, e outros usuários do fórum da UniDev, pois alguns dos temas abordados neste tutorial foram complementados com definições discutidas no fórum relacionado a Allegro.

· Links Relacionados:

- Allegro Oficial [inglês]
- Allegro.cc [inglês]
- Manual Allegro Vivace [inglês]
- As Funções do Allegro da UFRJ [português]
- UniDev.Com.Br [português]



Hosted by www.Geocities.ws

1