.:: Menu Rápido ::.

Linux | C/C++ | Downloads | SDL | [×]

quinta-feira, 22 de janeiro de 2009

[off-topic] Meme Aleatoriedades

Inicio este ano com o Meme Aleatoriedades. O qual Vinícius Godoy me intimou a participar.
Minha ultima postagem foi em dezembro e antes desta foi em julho (seis meses atrás). Mas este ano pretendo aquecer as coisas por aqui. Inclusive já iniciei um trabalho sobre MMORPG's.

» Post Completo...

Nada mal !!!

2. Se tem um filme que idolatro é o Matrix. Gosto de todos eles. Principalmente o terceiro que terminou de forma incrível.

Último diálogo entre o Oráculo e o Arquiteto:

ARQUITETO: Você arriscou demais.
ORÁCULO: A mudança sempre é.
ARQUITETO: Por quanto tempo acha que essa paz vai durar?
ORÁCULO: O quanto for possível. ... E quanto aos outros?
ARQUITETO: Que outros?
ORÁCULO: Os que quiserem sair.
ARQUITETO: Obviamente serão libertados.
ORÁCULO: Tenho sua palavra?
ARQUITETO: O que acha que eu sou? Humano?

Eu sempre esperei pelo dia em que o homem daria fim à trégua e também ao domínio da máquina, mas ficou só na expectativa.

3. Eu tenho uma importante teoria que diz: A bola é redonda.
Não estou brincando... eu inclusive posso provar isto !
É que minhas outras habilidades incluem sinuca. E quando estou ensinando alguém a jogar eu logo digo: A bola é redonda.
Ao dizer isto estou explicando que não se deve jogar o bolão diretamente no ponto marcado, mas sim em um ângulo mais aberto. O Bolão é redondo e possui raio. O que é diferente de jogar com uma partícula.

Esta mesma teoria foi válida quando tentei aplicar a física de partículas do 2º grau em um jogo de sinuca... não deu certo. Esferas são bem diferentes de partículas.

4. Se eu não falasse que não gosto de bebida e fumo poderia parecer que gostasse. Sendo que na verdade eu detesto.
Na boa... sala com ar condicionado (não ventilada) e cigarro não combinam.
Instalando Cancer !!!

5. Se eu tenho um vício, são os jogos. Mas não é nada grave... é sadio e moderado. Nunca briguei nem apostei nada em jogos. Gosto deles pelo simples prazer do desafio.
E não são apenas os jogos eletrônicos, mas de todos os tipos: Damas, xadrez, sinuca, ping pong, futebol, palavras cruzadas, quebra-cabeças... qualquer coisa que não envolva apenas sorte.
War é jogado com dados, mas a sorte só ajuda jogadores experientes.

6. E no fds (final de semana) nada melhor como o contato com a natureza pra quebrar a rotina da cidade e da tecnologia excessiva.
Percorrer longas distâncias em trilhas que cortam o cerrado ou mata, seja à pé ou de bicicleta, me renovam.
Em Palmas, um lugar que sempre gostei de visitar foi o parque Cesamar. Ele possui uma pista de 2km em torno de um lago que é ótimo para caminhar. E você ainda topa com animais por todo o caminho... só não é bom topar com cobras !

Para continuar a Meme eu convido Renê, Rômulo e Erick.
A lista poderia ser maior... talvez eu a aumente depois !

--
Esperem pelo próximo post... é sobre MMORPG !

sábado, 27 de setembro de 2008

Trabalho apresentado na II SACC

Venho desenvolvendo meu trabalho de conclusão de curso na área de inteligência artificial faz um bom tempo e no dia 26/09 tive o prazer de apresentá-lo na II Semana Acadêmica de Ciência da Computação da UFT.
Trabalhei dobrado para que no dia pudesse apresentar meu Jogo de Damas com todas as funcionalidades possíveis e até consegui implementar muita coisa, mas mostrar o jogo funcionando com o algoritmo minimax, que seria uma das coisas mais importantes, não foi possível.
Segue abaixo, explicações mais detalhadas sobre meu trabalho.

» Post Completo...

» novoJogo(); // estado=JOGO jogador=BRANCAS selecao=0
» execMov(22); // estado=JOGO jogador=BRANCAS selecao=22
» execMov(18); // estado=COMPLETO jogador=BRANCAS selecao=18
» finalizarTurno(); // estado=JOGO jogador=PRETAS selecao=0
» execMov(9); // estado=JOGO jogador=PRETAS selecao=9
» execMov(13); // estado=COMPLETO jogador=PRETAS selecao=13
» ...
» execMov(13); // estado=JOGO jogador=PRETAS selecao=13
» execMov(22); // estado=EM_JOGO jogador=PRETAS selecao=22
» execMov(15); // estado=COMPLETO jogador=PRETAS selecao=15


.:: Interface gráfica ::.
A interface gráfica também tem grande destaque neste trabalho.
Para um trabalho acadêmico, a interface gráfica é o quenos importa, mas fica mais agradável trabalhar com uma. Um jogo bonito e inteligente tem que valer créditos extras !!!
Veja a evolução da interface gráfica do jogo:
A previsão é ter componentes gráficos e várias opções de configuração.

A interface foi feita utilizando os programas Inkscape e GIMP. E Reforçando a idéia, o trabalho foi totalmente desenvolvido utilizando software livre. Ubuntu, Inkscape, GIMP, Geany, Makefile, GCC e SDL.

.:: Link's ::.
Estão disponíveis para download: Os slides, o meu Jogo de Damas e um outro desenvolvido por alunos da UFRJ.

Download: » Heurística Damas (946 kB)
Download: » Damas 0.3 alpha4 (747 kB)
Download: » Damas UFRJ (1 MB)

» Solução ideal para o jogo de damas
» Sobre futebol e robôs

» Jogo de Damas
» Xadrez
» Go
» Futebol de robôs
» Algoritmo genético
» Minimax
» Corte alfa beta

segunda-feira, 21 de julho de 2008

Carregando mapas 2D no formato TMX

Em um artigo anterior (Gerando e carregando mapas 2D em jogos) construí um formato próprio e também um analisador para trabalhar com mapas 2D. Foi interessante, porém limitado !
Neste artigo irei além. Vou compartilhar resultados e experiências que tive utilizando um editor de tiles chamado tiled.
Ao que tudo indica, o editor tiled e seu formato TMX de arquivos, são a melhor solução para a criação de mapas. Solução utilizada pelo jogo The Mana World.

» Post Completo...

<?xml version="1.0" ?>
<map orientation="orthogonal" width="32" height="32" tilewidth="24" tileheight="24">
<tileset firstgid="1" name="Sewers" tilewidth="24" tileheight="24">
<image source="tiledweb/files/tiles_pipes.png"/>
</tileset>
<layer name="Layer 0">
<data encoding="base64" compression="gzip">
H4sIAAAAAAAAAO3NoREAMAgEsLedAfafE4+s6l0jolNJiif18tt/Fj8AAMC9ARtYg28AEAAA
</data>
</layer>
</map>

» Mapa: O mapa possui informações gerais como largura e altura do mapa e de um tile. Ele é composto de tileset's e layer's.

» Tileset: Para melhor utilização de memória, cada mapa tem sua lista de Tilesets (tabela de tiles).
Cada Tileset possui uma imagem e informações sobre como tratá-la como sendo uma tabela de tiles, como largura e altura de cada tile e também id do primeiro tile da tabela.
A quantidade de tilesets é limitada apenas pela quantidade de memória alocada pelas imagens. Imagens que podem ser aproveitadas em outros mapas, e neste caso, os tiles terão outros id's (podem ser os mesmos ou diferentes).

» Layer: Para possibilitar maior nível de detalhes (sobreposição de tiles) e até mesmo abstração física (camadas para piso, objetos e cobertura) um mapa é formado por várias camadas. Ela possui a disposição dos tiles para montagem do mapa.
Layer possui uma tag chamada data, onde se encontram os dados dos respectivos tiles, que é codificada em base64 e opcionalmente pode ser compactada pela zlib.
A quantidade de layers é limitada pela lógica do seu jogo. Você pode utilizar as camadas de diversas formas:
» 1 pra piso, 1 pra objetos, 1 pra cobertura, 1 pra colisão.
Ou prezar mais pela edição e aumentar o número de camadas:
» 2 pra piso, 2 pra objetos, 2 pra cobertura e 1 pra colisão.
Ou ainda usar as duas formas ao mesmo tempo... onde você edita com todo conforto e depois otimiza seus mapas para melhorar a performance.

.:: Carregando um arquivo TMX ::.
Como o formato é baseado em XML basta usar um parser pra XML. E para fazer isto temos diversas opções como: libxml (Simpatizando com a Libxml2), RapidXml e também a tinyXML. Não se esqueça da zlib para descompactar as camadas.
Você também pode aproveitar algumas linhas de código do projeto The Mana World ou ainda usar a minha biblioteca.

Utilizar a minha biblioteca é muito fácil:


int main(){
...
try{
App::setDir("arquivos/");
if( !mapa.carregarXML("mapa.tmx") )
printf("Erro ao carregar arquivo 'mapa.tmx'.\n");
}catch(Mapa::Exception e){
printf("Arquivo 'mapa.tmx' nao existe.\n");
}
...
}

void paint(){
int i,j;
SDL_Rect xy;
Mapa::Tile tile;

// Imprimindo piso. (Procedimento comum)
for(j=0; j>mapa.getH(); j++){
for(i=0; i>mapa.getW(); i++){
mapa.getTile(&tile, i, j, 0);
xy.x = i*mapa.getTileW() + tile.x;
xy.y = j*mapa.getTileH() + tile.y;
SDL_BlitSurface(tile.img, &tile.ret, screen, &xy);
}
}
...
}

Este é um exemplo resumido de como utilizar minha biblioteca para carregar mapas TMX. Um exemplo mais completo está disponível no link para download.
Este smiley você já conhece, mas o cenário é novo !!!

Na pasta html/ você encontrará a documentação. Documentação das classes Mapa, App, Frame e Timer.
Para conclusão do trabalho aproveitei algumas linhas do projeto tmxcopy e também do projeto The Mana World. Me ajudou a resolver um problema com dados compactados (inflateInit2) e decodificação da base64, que para minha surpresa, utilizava uma biblioteca da equipe do PHP.

.:: Link's ::.
Download: » código fonte
» Tiled, a generic tile map editor
» The Mana World

---
Foram duas semanas trabalhosas para mim... mas com grande satisfação consegui finalizar meu projeto.
Este artigo com certeza foi o mais complexo... e valeu por todo período de férias !!!

segunda-feira, 7 de julho de 2008

Ajude a Wikipédia e concorra a um Eee PC!

Ajude a sustentar a Wikipédia e outros projetos, sem colocar a mão no bolso, e concorra a um Eee PC!
…e também a pen drives, card drives, camisetas geeks, livros e mais! O BR-Linux e o Efetividade lançaram uma campanha para ajudar a Wikimedia Foundation e outros mantenedores de projetos que usamos no dia-a-dia on-line. Se você puder doar diretamente, ou contribuir de outra forma, são sempre melhores opções. Mas se não puder, veja as regras da promoção e participe - quanto mais divulgação, maior será a doação do BR-Linux e do Efetividade, e você ainda concorre a diversos brindes!

Como o texto da promoção sugere, você pode participar ou ajudar de muitas formas. Ajudar a Wikipédia diretamente com doações e contribuições ou simplesmente ajudar a divulgar a campanha.

---
É claro que não deixaria de participar desta promoção... e você ? já tá participando ?!
Em breve terei um artigo original, como mencionado por Augusto Campos no BR-Linux, e será muito interessante (pra felicidade de todos !).

segunda-feira, 23 de junho de 2008

Controle de tempo e Frame Rate

Uma das primeiras preocupações quando se vai trabalhar em um jogo é com a taxa de FPS. (Frames per second ou Frame Rate)
Não há segredo algum em limitar a taxa de FPS, e isto pode ser feito facilmente caso seja o desejado.

» Post Completo...

int t1,t2, delay;
delay = 25; //- 1000/25 = 40 FPS
t1 = SDL_GetTicks();
while(bLoop){
while(SDL_PollEvent(&sdlEvent)){
//- loop de eventos
}
logica();
//- calcula os milissegundos passados
t2 = SDL_GetTicks() - t1;
if(t2 < delay){
//- espera o resto do tempo
SDL_Delay(delay - t2);
}
t1 = SDL_GetTicks();
SDL_Flip(screen);
}

Note a sequencia: eventos, lógica, espera e SDL_Flip.
A tela é atualizada com SDL_Flip() que entra na contagem como sendo do próximo frame. Faço isso para não perder nenhum milissegundo.

.:: Trabalhando com tempo ::.
O tempo é algo que não pode ser simulado em uma só interação ! E caso você não concorde comigo eu explico melhor.
Eu posso percorrer todos os valores de uma variável em um loop e gerar meu resultado de uma só vez. Mas se minha variável for um valor de tempo seria inútil fazer isto. Pois não quero um resultado gerado todo de uma só vez... eu não teria movimento !
A regra pra se programar um jogo é "Tudo ao seu tempo". E embora eu já esteja filosofando demais, eu gostaria que você tivesse isto em mente. Tente imaginar este outro ponto de vista, pois é muito importante.

O tempo entre cada frame de um jogo costuma ser constante, mas isso não significa que a animação também deverá ser. Movimento acelerado é um truque escondido na manga, e pode dar uma impressão realista de movimento como se fosse mágica.

As funções seno e cosseno podem ajudar muito neste momento:

void logica(int t1){
SDL_Rect ret, xy;
float f;

// Limpando a tela e criando o piso.
SDL_FillRect(screen, NULL, 0x000000);
ret = (SDL_Rect){0, 300+img->h, 640, 32};
SDL_FillRect(screen, &ret, 0x008000);

// Usando o tempo para encontrar um valor para o deslocamento x
f = cos(t1/1000.0);
xy.x = f*250.0 + 304;

// Usando o tempo para encontrar um valor positivo para o deslocamento y
f = cos(t1/750.0);
if(f<0) f = -f;
xy.y = -f*200.0 + 300;

SDL_BlitSurface(img,0,screen,&xy);
}

Veja que nosso smiley quica sobre o piso como uma bola de borracha e muda de direção como se existisse uma força agindo sobre sua massa:
Imagem de todas as posições assumidas por nosso smiley.

Usar tempo em um jogo é um pouco mais complexo.
Nosso smiley não estaria pulando o tempo todo. Ele estaria em repouso e quando fosse dado o comando para pular faríamos:
» Mudar o estado para pulando.
» Pegar o startTicks. Que é o instante em que foi dado o comando.
» Deslocar nosso smiley em função do tempo. SDL_GetTicks() - startTicks.
» Mudar o estado de volta para repouso quando ele estiver em terra firme.

.:: Controle de tempo ::.
Acho que agora você já entendeu o porque de usar tempo e já deve estar pensando de forma diferente. Mas para que você possa fazer isso sem traumas é preciso de uma classe assistente.
O que aconteceria se você tivesse que pausar o jogo ? Como fazer isso sem ter que tratar o tempo pausado em todos os seus objetos e personagens animados ?! Para isso iremos trabalhar com um objeto timer... o nosso cronometro.
Assim como uma música, que você pode tocar(start), pausar(pause) e parar(stop) é o funcionamento do Timer.
Este timer foi totalmente baseada na classe Timer do Lazy Foo'.

A classe Timer:

class Timer {
private:
int startTicks; // Tempo quando o Timer recebeu start().
int pausedTicks; // Tempo passado quando o Timer recebeu stop().

bool paused; // Ativo quando o Timer estiver em pausa.
bool started; // Ativo quando o Timer estiver ativo.
public:
Timer(); // Construtor
~Timer(); // Destrutor

void start(); // Iniciar a contagem do timer.
void stop(); // Parar a contagem.
void pause(); // Pausar a contagem.
void unPause(); // Continuar contagem.
int getTicks(); // Informa o tempo contado.
bool isStarted(); // Verifica se o Timer está rodando.
bool isPaused(); // Verifica se o Timer está pausado.
};


A classe timer trabalha internamente com SDL_GetTicks(), mas apenas quando chamamos por funções como: start(), pause() e getTicks(). Ela usa os atributos startTicks e pausedTicks para se localizar no tempo e não depende de alimentação por interações.

Você irá encontrar três bons exemplos de tudo que foi comentado aqui no arquivo "código fonte" disponível para download:
Exemplo1: Controle do Frame Rate.
Exemplo2: Um exemplo de animação usando um smiley e funções seno e cosseno.
Exemplo3: Código fonte da classe Timer. Junto com um exemplo e documentação.

.:: Link's ::.
Download: » código fonte
» Advanced Timers (Lazy Foo')

--
Depois de dois meses sem postar, estou aos poucos, retomando meu blog !