Vinicius de Carvalho | [TGL] Dogg
Just a raibow in the dark.
Para criação de jogos e o que mais você achar legal
set/2014
Paulo Henrique Fernandes Leite
Vinicius de Carvalho | [TGL] Dogg
• leite.paulohf@gmail.com
• github.com/Paulo-http
• facebook.com/paulo.http
• tgl_dogg@outlook.com
• github.com/tgl-dogg
• facebook.com/TGL_Dogg
• Introdução à biblioteca gráfica Allegro 5.x
• Introdução à Programação Orientada a Evento
• Exemplos práticos das funcionalidades do Allegro
• Dominação mundial com ajuda dos homens-topeira
(ok a parte dos homens-topeira é mentira)
• Janelas
• Textos
• Imagens
• Mouse e Teclado
• Áudio
• Janelas al_destroy_display()
• Textos al_destroy_font()
• Imagens al_destroy_bitmap()
• Mouse e Teclado al_unregister_event_source()
• Áudio al_destroy_sample() & al_destroy_audio_stream()
#include <stdio.h>
// Biblioteca Allegro
#include <allegro5/allegro.h>
int main() {
// usado para iniciar os recursos do Allegro
al_init();
/* Aqui é onde a magia do Allegro acontece */
return 0;
}
ALLEGRO_DISPLAY *janela = NULL;
ALLEGRO_COLOR cor;
/* usado para criar telas, neste caso
uma tela de 800x600, largura X altura */
janela = al_create_display(800, 600);
/* usado para definir cores em espaço de cor RGB,
vai de 0 á 255 */
cor = al_map_rgb(255, 255, 255);
/* usado para pintar a tela conforme
a cor definida no parâmetro */
al_clear_to_color(cor);
/* ... */
/* ... */
// usado para atualizar a tela
al_flip_display();
/* usado para segura a tela pelo tempo
definido em segundos */
al_rest(10);
// usado para destruir telas criadas
al_destroy_display(janela);
return 0;
}#include <stdio.h>
#include <allegro5/allegro.h>
int main() {
// criando variáveis conforme seu tipo de uso
ALLEGRO_DISPLAY *janela = NULL;
ALLEGRO_COLOR cor;
// usado para iniciar os recursos do allegro
al_init();
// usado para criar telas, neste caso, uma tela de 800x600, largura X altura
janela = al_create_display(800, 600);
// usado para definir cores em espaço de cor RGB, vai de 0 á 255
cor = al_map_rgb(255, 255, 255);
// usado para pintar a tela conforme a cor definida no parâmetro
al_clear_to_color(cor);
// usado para atualizar a tela
al_flip_display();
// usado para segura a tela pelo tempo definido em segundos
al_rest(10);
// usado para destruir telas criadas
al_destroy_display(janela);
return 0;
}
#include <stdio.h>
#include <allegro5/allegro.h>
// Bibliotecas Allegro para as fontes
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_ttf.h>
int main() {
/* ... */
// DESLIGA ESSE CAPS QUE EU NÃO SOU TUAS NEGA
/* ... */
return 0;
} /* ... */
ALLEGRO_COLOR cor_da_fonte;
cor_da_fonte = al_map_rgb(0, 0, 0);
ALLEGRO_FONT *fonte = NULL;
// usado para inicializar fontes do allegro
al_init_font_addon();
al_init_ttf_addon();
/* usado pra carregar a fonte
caminho da fonte, tamanho, flags */
fonte = al_load_font("fonte.ttf", 30, 0);
/* ... */
/* IMPORTANTE !!!1!!1!onze1!1!
faça sempre a checagem se a mesma foi carregada,
evita possiveis erros */
if (!fonte) {
fprintf(stderr, "Falha ao carregar fonte.\n");
al_destroy_display(janela);
return -1;
}http://www.comicvine.com/captain-americas-shield/4055-50737/
/* ... */
// usado para criar texto em tela
al_draw_text(
fonte, // fonte
cor_da_fonte, // cor da fonte
200, // onde começa em X
100, // onde começa em Y
ALLEGRO_ALIGN_CENTRE, // alinhamento
"HELLO WORLD!" // texto
);
al_flip_display();
al_rest(5);
/* ... */ /* usando string para passar o texto na função,
lembrando que neste caso, usa-se CHAR *variavel */
char *texto = "Lembre-se que string em C é char estrela!";
al_draw_text(fonte, cor_da_fonte, 5, 300, 0, texto);
al_flip_display();
al_rest(5);
/* variavel fonte é um ponteiro,
assim como display entre outras,
não esqueça de limpar a memoria depois de usa-las */
al_destroy_font(fonte);
al_destroy_display(janela);
return 0;
}#include <stdio.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_ttf.h>
int main() {
/*------------CODIGO ANTERIOR DO HELLO WORLD------------*/
ALLEGRO_DISPLAY *janela = NULL;
ALLEGRO_COLOR cor;
al_init();
janela = al_create_display(800, 600);
cor = al_map_rgb(255, 255, 255);
al_clear_to_color(cor);
al_flip_display();
al_rest(2);
/*----------------------CONTINUANDO--------------------*/
// criando variaveis para alocar fonte e cor
ALLEGRO_FONT *fonte = NULL;
ALLEGRO_COLOR cor_da_fonte;
// usado para inicializar fontes do allegro
al_init_font_addon();
al_init_ttf_addon();
// usado para carregar a fonte. IMPORTANTE, faça sempre a checagem se a mesma foi carregada, evita possiveis erros
fonte = al_load_font("fonte.ttf", 30, 0);
if (!fonte) {
fprintf(stderr, "Falha ao carregar fonte. Verifique se o caminho esta correto!\n");
al_destroy_display(janela);
return -1;
}
cor_da_fonte = al_map_rgb(0, 0, 0);
// usado para criar texto em tela "al_draw_text(fonte, cor, onde começa em X, onde começa em Y, alinhamento, texto)
al_draw_text(fonte, cor_da_fonte, 200, 100, ALLEGRO_ALIGN_CENTRE, "HELLO WORLD!");
al_flip_display();
al_rest(5);
// usando string para passar o texto na função, lembrando que neste caso, usa-se CHAR *variavel
char *texto = "Lembre-se que string em C é char estrela!";
al_draw_text(fonte, cor_da_fonte, 5, 300, 0, texto);
al_flip_display();
al_rest(5);
// variavel fonte é um ponteiro, assim como display entre outras, não esqueça de limpar a memoria depois de usa-las
al_destroy_font(fonte);
al_destroy_display(janela);
return 0;
}
#include <stdio.h>
#include <allegro5/allegro.h>
// Biblioteca de Imagens
#include <allegro5/allegro_image.h>
// Defines marotos
#define LARG 800
#define ALT 600
int main() {
/* ... */
return 0;
} // Inicia Allegro
al_init();
ALLEGRO_DISPLAY *janela = NULL;
janela = al_create_display(LARG, ALT);
// usado para inicializar recursos de imagens
al_init_image_addon();
// usado para alocar variavel imagem
ALLEGRO_BITMAP *imagem = NULL;
// usado para carregar imagem na memoria
imagem = al_load_bitmap("imagem.png");
/* ... */ // usado para desenhar imagem em tela na posição X, Y
int i, n;
for(i=0, n=0; i<5; i++, n+=50) {
al_draw_bitmap(imagem, 100+n, 100+n, 0);
al_flip_display();
al_rest(1);
}
al_rest(5);
// liberando memoria
al_destroy_bitmap(imagem);
al_destroy_display(janela);
return 0;
}#include <stdio.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>
#define LARG 800
#define ALT 600
int main() {
ALLEGRO_DISPLAY *janela = NULL;
// usado para alocar variavel imagem
ALLEGRO_BITMAP *imagem = NULL;
al_init();
// usado para inicializar recursos de imagens
al_init_image_addon();
janela = al_create_display(LARG, ALT);
// usado para carregar imagem na memoria
imagem = al_load_bitmap("imagem.png");
// usado para desenhar imagem em tela na posição X, Y
int i, n;
for(i=0; i<5; i++) {
al_draw_bitmap(imagem, 100+n, 100+n, 0);
al_flip_display();
al_rest(1);
n+=50;
}
// atualizando a tela e segurando por alguns segundos
al_flip_display();
al_rest(5);
// liberando memoria
al_destroy_bitmap(imagem);
al_destroy_display(janela);
return 0;
}
#include <stdio.h>
#include <allegro5/allegro.h>
// Variáveis constantes
const int LARGURA_TELA = 800;
const int ALTURA_TELA = 600;
// Variável global representando a janela principal
ALLEGRO_DISPLAY *janela = NULL;
int main() {
/* ... */
return 0;
}
// Variável representando a informações de tela
ALLEGRO_DISPLAY_MODE disp_data;
al_init();
// Atribui em disp_data as configurações de tela
al_get_display_mode(0, &disp_data);
// Configura o display
janela = al_create_display(LARGURA_TELA, ALTURA_TELA);
if (!janela){
fprintf(stderr, "Falha ao criar display!\n");
return -1;
}
/* ... */ // Atribui onde o display será posicionado
al_set_window_position(
janela,
(disp_data.width-LARGURA_TELA)/2,
(disp_data.height-ALTURA_TELA)/2);
// Configura o título do display
al_set_window_title(janela, "NOME DA MINHA JANELA!");
// Atualiza a tela
al_flip_display();
al_rest(5);
al_destroy_display(janela);
return 0;
}#include <stdio.h>
#include <allegro5/allegro.h>
const int LARGURA_TELA = 800;
const int ALTURA_TELA = 600;
// Variável global representando a janela principal
ALLEGRO_DISPLAY *janela = NULL;
int main() {
// Variável representando a posição de tela
ALLEGRO_DISPLAY_MODE disp_data;
al_init();
// Atribui em disp_data as configurações de tela
al_get_display_mode(0, &disp_data);
// Configura o display
janela = al_create_display(LARGURA_TELA, ALTURA_TELA);
if (!janela){
fprintf(stderr, "Falha ao criar display!\n");
return -1;
}
// Atribui onde o display será posicionado
al_set_window_position(janela, (disp_data.width-LARGURA_TELA)/2, (disp_data.height-ALTURA_TELA)/2);
// Configura o título do display
al_set_window_title(janela, "AQUI EU ESCOLHO O NOME DA MINHA JANELA!");
// Atualiza a tela
al_flip_display();
al_rest(5);
printf("\nFim da execução!\n");
al_destroy_display(janela);
return 0;
}Algo precisa acontecer
• Usuário clicar com o mouse
• Usuário apertar um botão do teclado
• Usuário desencadear o apocalipse zumbi
http://deadliestfiction.wikia.com/wiki/Zombies_(PvZ)
E alguém deve estar pronto para quando acontecer
http://plantsvszombies.wikia.com/wiki/User:Chickenwrangler369
ALLEGRO_EVENT_QUEUE *interacao = NULL;
ALLEGRO_EVENT evento;
al_init();
ALLEGRO_DISPLAY *janela = al_create_display(LARG, ALT);
/* inicializando eventos
e checando para evitar possiveis erros */
interacao = al_create_event_queue();
if (!interacao) {
fprintf(stderr, "Falha ao criar fila de eventos.\n");
al_destroy_display(janela);
return -1;
} /* ... */
/* usado para registrar os eventos atuais em tela,
neste caso, usa-se o al_get...(janela) como parâmetro */
al_register_event_source(
interacao,
al_get_display_event_source(janela)
);
while (1) {
/* ... */
}
/* ... */ while (1) {
// espera até que um evento ocorra
al_wait_for_event(interacao, &evento);
// se houver evento e se foi um clique no botão fechar
if (interacao
&& evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
break;
}
al_flip_display();
}
al_destroy_display(janela);
return 0;
}#include <stdio.h>
#include <allegro5/allegro.h>
#define LARG 800
#define ALT 600
int main() {
ALLEGRO_DISPLAY *janela = NULL;
// usado para alocar variaveis de interação e eventos
ALLEGRO_EVENT_QUEUE *interacao = NULL;
ALLEGRO_EVENT evento;
al_init();
janela = al_create_display(LARG, ALT);
// inicializando eventos e checando para evitar possiveis erros
interacao = al_create_event_queue();
if (!interacao) {
fprintf(stderr, "Falha ao criar fila de eventos.\n");
al_destroy_display(janela);
return -1;
}
// usado para registrar os eventos atuais em tela, neste caso, usa-se o al_get...(janela) como parâmetro
al_register_event_source(interacao, al_get_display_event_source(janela));
al_flip_display();
// usando laço sempre verdadeiro para rodar o jogo
while (1) {
// espera até que um evento ocorra
al_wait_for_event(interacao, &evento);
// primeira interação, se houver clique no [X] na tela, ele registra o evento e para a execução do jogo
if (interacao && evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
break;
}
al_flip_display();
}
// liberando memoria
al_destroy_display(janela);
return 0;
} ALLEGRO_BITMAP *imagem = al_load_bitmap("imagem.png");
al_clear_to_color(al_map_rgb(255, 255, 255));
al_draw_bitmap(imagem, 100, 50, 0);
// Torna apto o uso de mouse na aplicação
al_install_mouse();
// Atribui o cursor padrão do sistema para ser usado
al_set_system_mouse_cursor(janela,
ALLEGRO_SYSTEM_MOUSE_CURSOR_DEFAULT);
// usado para registrar os eventos do mouse
al_register_event_source(interacao,
al_get_mouse_event_source());// Se for um evento do tipo clique, vê a posição do clique
if (evento.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
/* verifica se o clique foi em cima da imagem,
pegando onde ela começa e onde termina */
if (evento.mouse.x >= 100 &&
evento.mouse.x <= al_get_bitmap_width(imagem) + 100 &&
evento.mouse.y >= 50 &&
evento.mouse.y <= al_get_bitmap_height(imagem) + 50) {
printf("Você clicou na imagem!\n");
break;
}
}
al_flip_display(); /* ... */
/* libera os eventos do mouse
para criação de novos eventos caso exista */
al_unregister_event_source(
interacao,
al_get_mouse_event_source()
);
al_rest(1);
// liberando memoria
al_destroy_display(janela);
return 0;
}#include <stdio.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>
#define LARG 800
#define ALT 600
int main() {
ALLEGRO_DISPLAY *janela = NULL;
ALLEGRO_BITMAP *imagem = NULL;
// usado para alocar variaveis de interação e eventos
ALLEGRO_EVENT_QUEUE *interacao = NULL;
ALLEGRO_EVENT evento;
al_init();
al_init_image_addon();
janela = al_create_display(LARG, ALT);
// inicializando eventos e checando para evitar possiveis erros
interacao = al_create_event_queue();
if (!interacao) {
fprintf(stderr, "Falha ao criar fila de eventos.\n");
al_destroy_display(janela);
return -1;
}
// Torna apto o uso de mouse na aplicação
al_install_mouse();
// Atribui o cursor padrão do sistema para ser usado
al_set_system_mouse_cursor(janela, ALLEGRO_SYSTEM_MOUSE_CURSOR_DEFAULT);
imagem = al_load_bitmap("imagem.png");
al_clear_to_color(al_map_rgb(255, 255, 255));
al_draw_bitmap(imagem, 100, 50, 0);
al_flip_display();
// usado para registrar os eventos do mouse
al_register_event_source(interacao, al_get_mouse_event_source());
// usado para registrar os eventos de tela, ja usado antes
al_register_event_source(interacao, al_get_display_event_source(janela));
al_flip_display();
// usando laço sempre verdadeiro para rodar o jogo
while (1) {
// espera até que um evento ocorra
al_wait_for_event(interacao, &evento);
// Se for um evento do tipo clique, vê a posição do clique
if (evento.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
// verifica se o clique foi em cima da imagem, pegando onde ela começa e onde termina
// usa-se o al_get_bitmap para pegar o tamanho da imagem e soma o valor de onde ela começa pra limitar somente o tamanho da imagem
if (evento.mouse.x >= 100 && evento.mouse.x <= al_get_bitmap_width(imagem) + 100 &&
evento.mouse.y >= 50 && evento.mouse.y <= al_get_bitmap_height(imagem) + 50) {
printf("Você clicou na imagem!\n");
break;
}
}
al_flip_display();
}
// libera os eventos do mouse para criação de novos eventos caso exista
al_unregister_event_source(interacao, al_get_mouse_event_source());
al_rest(1);
// liberando memoria
al_destroy_display(janela);
return 0;
}
fonte = al_load_font("fonte.ttf", 72, 0);
cor_da_fonte = al_map_rgb(0, 0, 0);
fundo = al_load_bitmap("bg.png");
al_draw_bitmap(fundo, 0, 0, 0);
al_flip_display();
// usado para iniciar o teclado
al_install_keyboard();
interacao = al_create_event_queue();
al_register_event_source(interacao,
al_get_keyboard_event_source());
al_register_event_source(interacao,
al_get_display_event_source(janela)); if (evento.type == ALLEGRO_EVENT_KEY_DOWN) {
switch(evento.keyboard.keycode) {
case ALLEGRO_KEY_UP:
al_draw_text(fonte, cor_da_fonte,
50, 250, 0, "Seta para cima!");
break;
case ALLEGRO_KEY_DOWN:
break;
case ALLEGRO_KEY_LEFT:
break;
case ALLEGRO_KEY_RIGHT:
break;
case ALLEGRO_KEY_SPACE:
break;
}
} /* ... */
else if (evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
break;
}
} // fim while
al_flip_display();
al_draw_bitmap(fundo, 0, 0, 0);
al_flip_display();
al_destroy_display(janela);
al_destroy_event_queue(interacao);
return 0;
}#include <stdio.h>
#include <stdbool.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_ttf.h>
#include <allegro5/allegro_image.h>
// declarando variaveis global, neste caso, podem ser usadas em qualquer função abaixo
const int LARGURA_TELA = 800;
const int ALTURA_TELA = 600;
ALLEGRO_DISPLAY *janela = NULL;
ALLEGRO_EVENT evento;
ALLEGRO_EVENT_QUEUE *interacao = NULL;
ALLEGRO_BITMAP *fundo = NULL;
ALLEGRO_FONT *fonte = NULL;
ALLEGRO_COLOR cor_da_fonte;
int main() {
al_init();
al_init_font_addon();
al_init_ttf_addon();
al_init_image_addon();
// usado para iniciar o teclado
al_install_keyboard();
janela = al_create_display(LARGURA_TELA, ALTURA_TELA);
al_set_window_title(janela, "Aprendendo a usar teclado em allegro");
fonte = al_load_font("fonte.ttf", 72, 0);
cor_da_fonte = al_map_rgb(0, 0, 0);
interacao = al_create_event_queue();
al_register_event_source(interacao, al_get_keyboard_event_source());
al_register_event_source(interacao, al_get_display_event_source(janela));
fundo = al_load_bitmap("bg.png");
al_draw_bitmap(fundo, 0, 0, 0);
al_flip_display();
while (1) {
// usado para esperar uma interacao/evento
al_wait_for_event(interacao, &evento);
// verifica se foi um evento partido do teclado conforme os casos analisados abaixo
if (evento.type == ALLEGRO_EVENT_KEY_DOWN) {
switch(evento.keyboard.keycode) {
case ALLEGRO_KEY_UP:
al_draw_text(fonte, cor_da_fonte, 50, 250, 0, "Seta para cima!");
break;
case ALLEGRO_KEY_DOWN:
al_draw_text(fonte, cor_da_fonte, 50, 250, 0, "Seta para baixo!");
break;
case ALLEGRO_KEY_LEFT:
al_draw_text(fonte, cor_da_fonte, 50, 250, 0, "Botão Esquerda!");
break;
case ALLEGRO_KEY_RIGHT:
al_draw_text(fonte, cor_da_fonte, 50, 250, 0, "Botão Direito!");
break;
case ALLEGRO_KEY_SPACE:
al_draw_text(fonte, cor_da_fonte, 50, 250, 0, "Clicou no espaço!");
break;
}
}
else if (evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
break;
}
al_flip_display();
al_draw_bitmap(fundo, 0, 0, 0);
al_flip_display();
}
al_destroy_display(janela);
al_destroy_event_queue(interacao);
return 0;
}#include <stdio.h>
#include <allegro5/allegro.h>
// Bibliotecas de áudio
#include <allegro5/allegro_audio.h>
#include <allegro5/allegro_acodec.h>
const int LARGURA_TELA = 800;
const int ALTURA_TELA = 600;
ALLEGRO_DISPLAY *janela = NULL;
ALLEGRO_EVENT_QUEUE *interacao = NULL;
// variaveis criadas para alocar som
ALLEGRO_AUDIO_STREAM *musica = NULL;
ALLEGRO_SAMPLE *sample = NULL; // usado para iniciar recursos de audio
al_install_audio();
al_init_acodec_addon();
al_reserve_samples(1);
// carrega o som.wav
sample = al_load_sample("oooh.wav");
// carrega o som.ogg
musica = al_load_audio_stream("example.ogg", 4, 1024);
// usado para definir o audio a ser usado
al_attach_audio_stream_to_mixer(
musica,
al_get_default_mixer()
); while (1) {
/* ... */
if (evento.type == ALLEGRO_EVENT_KEY_UP) {
if (evento.keyboard.keycode == ALLEGRO_KEY_SPACE) {
al_play_sample(sample, 1.0, 0.0, 1.0,
ALLEGRO_PLAYMODE_ONCE,
NULL
);
}
}
/* ... */
}
al_destroy_audio_stream(musica);
al_destroy_sample(sample);
return 0;http://publicitariopobre.com/tag/link-falso/
#include <stdio.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_audio.h>
#include <allegro5/allegro_acodec.h>
const int LARGURA_TELA = 800;
const int ALTURA_TELA = 600;
ALLEGRO_DISPLAY *janela = NULL;
ALLEGRO_EVENT_QUEUE *interacao = NULL;
// variaveis criadas para alocar som
ALLEGRO_AUDIO_STREAM *musica = NULL;
ALLEGRO_SAMPLE *sample = NULL;
int main() {
al_init();
al_install_keyboard();
// usado para iniciar recursos de audio
al_install_audio();
al_init_acodec_addon();
al_reserve_samples(1);
janela = al_create_display(LARGURA_TELA, ALTURA_TELA);
// carrega o som.wav
sample = al_load_sample("oooh.wav");
// carrega o som.ogg
musica = al_load_audio_stream("example.ogg", 4, 1024);
interacao = al_create_event_queue();
al_register_event_source(interacao, al_get_keyboard_event_source());
al_register_event_source(interacao, al_get_display_event_source(janela));
// usado para definir o audio a ser usado
al_attach_audio_stream_to_mixer(musica, al_get_default_mixer());
while (1) {
while (!al_is_event_queue_empty(interacao)) {
ALLEGRO_EVENT evento;
al_wait_for_event(interacao, &evento);
if (evento.type == ALLEGRO_EVENT_KEY_UP) {
if (evento.keyboard.keycode == ALLEGRO_KEY_SPACE) {
// usado para dar play no audio, neste caso, so da play quando aperta a tecla espaço do teclado
al_play_sample(sample, 1.0, 0.0, 1.0, ALLEGRO_PLAYMODE_ONCE, NULL);
}
}
else if (evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
break;
}
}
}
// nao esqueça de liberar os recursos da memoria!
al_destroy_audio_stream(musica);
al_destroy_sample(sample);
al_destroy_event_queue(interacao);
al_destroy_display(janela);
return 0;
}
Rafael Toledo:
http://www.rafaeltoledo.net/tutoriais-allegro-5/
WoW
Such Tutorials
Very Examples
Much Education
http://dogecoin.com/
Projeto Interativo II:
https://github.com/tgl-dogg/BCC-2s13-PI2-Codigo-de-Honra
Projeto Interativo III:
https://github.com/talespadua/BCC-1S14-PI3-CVMiniGames
https://github.com/gabrielgfa/BCC-1s14-PI3-AirNinja
Manual de Referência:
http://alleg.strangesoft.net/docs/refman.pdf
http://elpodcastdelabsaa.blogspot.com.br/2013/12/review-machinarium.html
By Vinicius de Carvalho | [TGL] Dogg
Workshop de introdução à ferramenta gráfica Allegro 5 para linguagem C, ministrado no curso de Bacharelado em Ciência da Computação no Centro Universitário SENAC São Paulo