Tutorial de trigonometria fora do ar
Devido a alguns erros encontrados no tutorial de trigonometria estou retirando-o do ar para passar por correções.
Agradeço a compreensão.
1 comentário September 25th, 2008
Devido a alguns erros encontrados no tutorial de trigonometria estou retirando-o do ar para passar por correções.
Agradeço a compreensão.
1 comentário September 25th, 2008
Hoje iremos aprender a fazer um menu simples em Allegro, utilizando alguns bitmaps e um pouco de lógica podemos ter um menu perfeitamente funcional, flexível e fácil de fazer.
Ao término do tutorial teremos o seguinte menu:

O menu com todas as suas opções
Ao passar o mouse sobre o item do menu teremos um pequeno efeito:

Opção do menu com o mouse em cima
O nosso menu terá os seguintes “recursos”:
Agora que vimos a teoria vamos à implementação:
#include <string> #include <vector> using namespace std;
Estas três linhas incluem as bibliotecas que utilizaremos (string e vector) e declara que utilizaremos o espaço de nomes std (maiores explicações depois).
Após a declaração da variável *bmp (BITMAP *bmp) vamos inserir o código das classes:
/*
=======
MenuItem
Representa o item de um menu
=======
*/
class MenuItem {
private:
int x, y; // localizacao deste item de menu na tela
// esta funcao verifica se o cursor do mouse esta em cima (dentro) deste item de menu
// se estiver, retorna true, caso contrario retorna false
bool mouseDentro() {
int x1 = x;
int y1 = y;
int x2 = x1 + pic->w;
int y2 = y1 + pic->h;
if (mouse_x > x1 && mouse_x < x2 && mouse_y > y1 && mouse_y < y2)
return true;
else
return false;
}
public:
BITMAP *pic; // imagem do item do menu
BITMAP *picMouseDentro; // imagem do item do menu (quando o mouse estiver em cima)
bool isMouseDentro; // flag que indica se o mouse esta ou nao dentro do menu
void (*funcao)(); // ponteiro para a funcao que sera executada quando o usuario clicar neste menu
MenuItem(int posX, int posY, string imagem, string imagemDentro, void (*pFuncao)()) {
isMouseDentro = false;
// define a posicao
x = posX;
y = posY;
// carrega as figuras do menu
pic = load_bitmap(imagem.c_str(), NULL);
picMouseDentro = load_bitmap(imagemDentro.c_str(), NULL);
// se especificou uma funcao, passa ela
if (pFuncao)
funcao = pFuncao;
}
// acao que este item de menu ira realizar
void realizaAcao() {
if (funcao != NULL)
(funcao)(); // chama a funcao
}
// atualiza este item de menu
void atualiza() {
// se o mouse passar em cima, executa a acao deste menu
if (mouseDentro()) {
isMouseDentro = true;
// se clicar realiza a acao
if (mouse_b & 1) realizaAcao();
} else {
isMouseDentro = false;
}
}
// desenha este item de menu na tela
void desenha(BITMAP *bmp) {
if (isMouseDentro)
draw_sprite(bmp, picMouseDentro, x, y);
else
draw_sprite(bmp, pic, x, y);
}
~MenuItem() {
}
};
/*
=======
Menu
Classe que gerencia os menus
=======
*/
class Menu {
private:
vector<MenuItem> items; // representa os itens do menu
public:
Menu() {}
// verifica a logica para todos os itens do menu
void atualiza() {
int totalItems = items.size();
for (int i = 0; i < totalItems; i++) {
items[i].atualiza();
}
}
// desenha os itens de menu
void desenha(BITMAP *bmp) {
int totalItems = items.size();
for (int i = 0; i < totalItems; i++) {
items[i].desenha(bmp);
}
}
// adiciona um item ao menu
void adicionaItem(MenuItem menuItem) {
items.push_back(menuItem);
}
~Menu() {
int totalItems = items.size();
for (int i = 0; i < totalItems; i++) {
// desaloca a memoria alocada para este item
destroy_bitmap(items[i].pic);
destroy_bitmap(items[i].picMouseDentro);
}
}
};
// ===================
// funcoes dos menus
// ===================
void mnuNewGame() {
}
void mnuOptions() {
}
void mnuHighScores() {
}
void mnuExit() {
fimJogo = true;
}
// ===================
// fim das funcoes dos menus
// ===================
Agora que temos as classes definidas e explicadas é hora da inicialização.
Após a chamada da função Inicializa na função main, insira o código abaixo:
// inicializa o gerenciador do menu
Menu *menu = new Menu();
// agora adiciona os itens do menu
// new game
MenuItem itemNewGame(187, 51, "mnuNewGame.bmp", "mnuNewGameM.bmp", mnuNewGame);
menu->adicionaItem(itemNewGame);
// options
MenuItem itemOptions(187, 122, "mnuOptions.bmp", "mnuOptionsM.bmp", mnuOptions);
menu->adicionaItem(itemOptions);
// highscores
MenuItem itemHighScores(187, 199, "mnuHighscores.bmp", "mnuHighscoresM.bmp", mnuHighScores);
menu->adicionaItem(itemHighScores);
// exit
MenuItem itemExit(187, 274, "mnuExit.bmp", "mnuExitM.bmp", mnuExit);
menu->adicionaItem(itemExit);
Já temos o menu inicializado, o que precisamos agora é fazer o gameloop atualizar a lógica do menu e desenhá-lo na tela.
Dentro do loop iniciado por:
while (ticks && !fimJogo) {
e após a linha:
if (key[KEY_ESC]) fimJogo = true;
insira o código:
menu->atualiza();
e para desenhar o menu, antes da linha:
textprintf(bmp, font, 0, 0, -1, "FPS: %i", fps);
insira o código:
// limpa a tela com a cor branca
clear_to_color(bmp, makecol(255, 255, 255));
Agora já temos a tela branca, só falta exibir o menu e o cursor do mouse, para isso após a linha:
textprintf(bmp, font, 0, 0, -1, "FPS: %i", fps);
insira:
// desenha o menu
menu->desenha(bmp);
// exibe o cursor do mouse na tela
show_mouse(bmp);
e para finalizar, antes da chamada à função Finaliza, insira o código abaixo para destruir corretamente o menu e liberar a memória alocada por ele:
delete menu;
Basicamente o menu possui duas classes: Menu que cuida para gerenciar todos os itens do menu, e MenuItem que representa um item de menu.
A classe Menu possui os itens de menu em um vector, permitindo assim inserirmos dinamicante quantos itens forem necessários. Esta classe simples apenas possui métodos para adicionar um item de menu, atualizar a lógica dos mesmos e desenhá-los na tela.
A classe MenuItem é o núcleo do menu. Cada item do menu possui algumas propriedades chave tais como posição (int x, y), uma imagem para ser exibida normalmente e outra para ser exibida quando o mouse passa em cima, uma flag para indicar se o mouse está passando em cima e o mais importante: um ponteiro para uma função que será chamada assim que o menu for clicado.
Esta classe também implementa métodos para desenhar o item de menu e atualizar a sua imagem caso o mouse esteja em cima.
Algumas observações: eu deixei o código todo no mesmo arquivo (não aconselhável exceto para exemplos mais triviais) para ajudar as pessoas que tem dificuldades em compilar arquivos separados e evitar complicações com variáveis não definidas, variáveis externas, etc…
Se quiser o projeto pronto baixe este arquivo (arquivo de projeto para o Dev-C++).
Agora que você já viu uma implementação básica, tente os exercícios abaixo:
Na segunda parte veremos em detalhes como controlar os “estados” do jogo para poder trocar mais facilmente as telas (podendo inclusive implementar um menu em cada uma ou iniciar o jogo).
Espero que tenham gostado.
PS: estou pensando em distribuir os códigos fontes com arquivo de projeto do Microsoft Visual C++ Express Edition 2008 ao invés de utilizar o Dev-C++, se alguém tiver alguma observação agora é a hora.
1 comentário September 23rd, 2008
Olá,
Hoje vamos ver um tema bem simples: como utilizar arquivos de configuração no Allegro.
Os arquivos de configuração do Allegro podem ser utilizados para diversos fins (com suas devidas vantagens e desvantagens).
Vantagens
Desvantagens
Os arquivos de configuração no Allegro nada mais são do que arquivos texto comuns formatados com uma estrutura parecido com arquivos .INI onde temos a seguinte estrutura:
// comeco do arquivo [nomesecao] rotulo=valor # comentario // fim do arquivo
Aqui vemos os seguintes elementos:
nomesecao = nome da seção que contém as configurações (serve como uma maneira de organizar as configurações por partes)
rotulo = nome do rótulo que conterá um valor (e será referenciado em código)
valor = valor para o rótulo
Exemplo de um arquivo:
// comeco do arquivo [graficos] largura=640 altura=480 profundidade=16 telacheia=0 // fim do arquivo
No arquivo acima temos uma seção chamada “graficos” onde definimos algumas variáveis específicas para a resolução de tela.
Algumas observações adicionais retiradas do manual:
- toda variável que não estiver definida em uma seção automaticamente estará disponível em todas as seções
- o mecanismo de seções serve para implementar uma espécie de escopo onde é possível definir rótulos iguais para seções diferentes
Exemplo:
[video] largura=640 altura=480 [monstro] largura=10 altura=50
Acima podemos ver que a largura e altura do monstro diferem da altura e largura da seção “video”.
Para utilizar arquivos de configuração no Allegro, precisamos seguir os passos abaixo:
- especificar o arquivo que contém os valores
- pegar o valor da seção e rótulo que queremos
- utilizar o valor
Para especificar o arquivo de configuração, utilizaremos a função “set_config_file” onde passamos um ponteiro de chars para o arquivo que queremos:
Exemplo:
char *nomeArquivo = "config.cfg"; set_config_file(nomeArquivo);
Para pegar o valor de um determinado rótulo precisamos primeiro saber o tipo do valor que queremos. Atualmente o Allegro suporta os seguintes tipos:
- string: equivalente ao tipo “char *” no C. (const char *get_config_string(const char *section, const char *name, const char *def);)
- inteiro: equivalente ao tipo “int” no C. (int get_config_int(const char *section, const char *name, int def);)
- hexadecimal: equivalente ao tipo “int” no C. (int get_config_hex(const char *section, const char *name, int def);)
- float: equivalente ao tipo “float” no C. (float get_config_float(const char *section, const char *name, float def);)
Como vemos no protótipo das funções acima, elas compartilham alguns parâmetros em comum:
const char *section = nome da seção onde iremos especificar o rótulo
const char *name = rótulo que contém o valor
(int|float|const char *def) = valor padrão para o rótulo se nenhum valor for encontrado
Exemplo:
int largura = get_config_int("graficos", "largura", 320);
A linha de código acima procura no arquivo de configuração na seção “graficos” pelo “rótulo” “largura” e atribui o valor à variável inteira “largura”, se o valor não for encontrado, a variável inteira “largura” terá então o valor 320.
Um exemplo mais completo:
Faça o download deste exemplo aqui.
Como você percebeu, a utilização dos arquivos de configuração depende da criatividade. Arquivos de configuração podem ser utilizados para guardar a lógica de gameplay de um jogo podendo ser alterado sem necessidade de recompilação do executável.
Existe muito mais flexibilidade disponível, recomendo uma leitura no manual pois existem funções para escrever nos arquivos e diversas outras não apontadas neste tutorial.
Agora que você já sabe o básico sobre arquivos de configuração, tente os exercícios abaixo:
Não deixe de dar a sua sugestão para artigos futuros.
Até a próxima.
Adicionar comentário May 26th, 2008