» novoJogo(); // estado=JOGO jogador=BRANCAS selecao=0
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....:: Trabalho de conclusão de curso ::.
Estou concluindo o curso de Ciência da Computação da UFT e como monografia resolvi desenvolver algo de meu total interesse e que trouxesse um grau de dificuldade. Não posso reclamar do grau de dificuldade de desenvolver um Jogo de Damas e nem da possibilidade de aplicar os conhecimentos adquiridos em outros problemas similares como o xadrez, go e num futuro não tão distante o futebol de robôs.
O trabalho, com o título SOLUÇÕES HEURÍSTICAS PARA O JOGO DE DAMAS, está sendo desenvolvido juntamente com meu professor orientador Alexandre Tadeu Rossini da Silva. E de uma maneira geral, conta com duas soluções desenvolvidas para o problema do Jogo de Damas, sendo elas, algoritmo genético e minimax com corte alfa beta.
O trabalho encontra-se em desenvolvimento e apesar dos estudos nas duas soluções, ainda não foi implementado a solução por minimax e corte alfa beta.
.:: Implementação por algoritmo genético ::.
Como alternativa para solucionar o problema do Jogo de Damas, foi proposto utilizar algoritmo genético.
O resultado foi um tanto frustrado, pois desenvolver esta solução custou muito tempo no desenvolvimento e implementação, e não teve o retorno esperado.
Esperava-se mais pelo esforço aplicado, mesmo assim, estrou satisfeito de ter obtido resultados ciente das falhas no desenvolvimento.
.:: Implementação por minimax e corte alfa beta ::.
Esta sim é uma solução de eficácia comprovada para o problema do Jogo de Damas. Onde pode-se fazer a melhor jogada, num dado nível de busca, sem temer as conseqüências.
Esta teria sido a primeira opção, caso o objetivo do trabalho não fosse buscar novos horizontes.
Eu tinha esperanças de implementar o minimax ainda este mês, mas andei trabalhando em outras coisas como a nova interface gráfica e os slides para a apresentação na Semana Acadêmica.
.:: Implementação da Lógica ::.
Quando digo lógica estou me referindo às regras do jogo.
Para trabalhar os estados do tabuleiro eu numerei as 32 casas ocupáveis do tabuleiro, assim como atribuí id's para cada tipo de peça:
- ⇒ Espaço não ocupado
p ⇒ Peça do jogador branco
d ⇒ Dama do jogador branco
P ⇒ Peça do jogador preto
D ⇒ Dama do jogador preto
# ⇒ Peça capturada (função de impedir a recaptura da mesma peça)
Vetor de casas ocupáveis: PPPPPPPPPPPP--------pppppppppppp
Para referenciar um movimento basta indicar as casas numeradas:
» 22-18 Para abrir o jogo com as brancas.
» 9-13 Poderia ser a próxima jogada das pretas.
» 13-22-15 Poderia uma tomada em seqüência das pretas caso o movimento 21-17 fosse feito.
O jogo ficaria: 1.22-18 9-13 2.21-17 13-22-15
Através da função execMov(Peca peca) é possível validar e executar um movimento de cada vez:
» execMov(22) Seleção da peça na casa 22 válida.
» execMov(18) Movimento da peça da casa 22 para a casa 18 válida.
Outra coisa seria trabalhar o tabuleiro como uma máquina de estados:
» JOGO - Ativo para jogar.
» EM_JOGO - Deve continuar jogando.
» COMPLETO - O movimento foi válido e é a vez do oponente.
» VITORIA - O Jogador atual venceu a partida.
» EMPATE - Os jogadores empataram.
» DERROTA - O Jogador atual perdeu a partida.
Com controle de jogador, estados e tudo mais:
» 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
.:: Menu Rápido ::.
Linux | C/C++ | Downloads | SDL | [×]A melhor maneira de se descobrir uma lib gratuita é nos repositórios do Ubuntu: $apt-cache search lib <palavra_chave> dev
Ou pelo devpaks.org, mas o repositório tem me ajudado mais !!!
- Script's GIMP - Python-Fu !!!
- Dicas Web
- Vídeo Compiz Fusion (Desktop 3D)
- Compilando com gcc e Makefile
- Que tal mudar para Ubuntu ?!
- SDL - A Biblioteca dos Jogos 2D
- Analisador léxico de arquivos script
- Simpatizando com a Libxml2
- AsciiGen - Tabela ASCII em C
- Conexão com API C do MySQL
- Compilando com gcc e Makefile
- DR Tetris 0.3 - Tetris no estilo tradicional !
- DR Quebra-Cabeça disponível para download !!!
- Freeggs - Liberdade aos ovos \o/
Se você quer aprender a programar jogos... SDL !!!
- Carregando mapas 2D no formato TMX
- Controle de tempo e Frame Rate
- SDL em Processamento de Imagens
- SDL_Surface - Introdução detalhada
- Imprimindo texto com SDL_Ttf
- SDL_Collide - Colisão 2D para jogos
- Tocando música e sons com SDL_mixer
- Gerando e carregando mapas 2D em jogos
- SDL - A Biblioteca dos Jogos 2D
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...
Postado por
Diogo_RBG
1 comentários
Tópicos: eventos
segunda-feira, 21 de julho de 2008
Carregando mapas 2D no formato TMX
<?xml version="1.0" ?>
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....:: The Mana World ::.
Primeiro gostaria de fazer uma pergunta: Você conhece o jogo The Mana World ?
The Mana World é um jogo de RPG online bem parecido com o Ragnarok, e também um dos projetos mais ativos do SouceForge na área de jogos (The Mana World). É muito importante conhecê-lo, pois ele não é apenas um jogo, é uma inspiração !
Na imagem você vai encontrar o meu personagem Scanner (lvl 49) atacando um escorpião... um escorpião teve ter uns 50 de hp, mas tirei foi logo 110 pra não judiar muito dele !
Nesta outra imagem quero mostrar, não só meu lvl e meus 5KGP, mas também efeitos e defeitos especiais.
» 1. Efeito especial de grama alta. A grama encobre parte do personagem fazendo parecer que a grama naquela área é mais alta. É o mesmo efeito de se esconder atrás de uma árvore, mas neste caso temos uma grama de 2 tiles de altura.
» 2. Defeito especial de objeto editado como piso. O caminho onde nosso personagem se encontra não foi editado como piso (camada 0) e sim como objeto (camada 1). Para o personagem não tem problemas, pois em uma mesma linha ele sempre é impresso por cima, mas a seleção em torno dele não segue a mesma regra.
Conclusão: O caminho parece ter volume... o que não é muito lógico.
Solução: Mesclar os tiles grama+caminhos e definí-los como piso (camada 0). Em run time ficaria legal !
Tudo no jogo é muito bonito e detalhado... mas está vendo algo de estranho na disposição das árvores ?!
» 1. Efeito especial de se esconder atrás de um relevo. Impressão visual e física de uma elevação.
» 2. Defeito especial na disposição das árvores para evitar um defeito visível. A copa de nenhuma das árvores invade o lado mais baixo do relevo. Na verdade elas até poderiam fazer isto, mas não sem atravessar os tiles de cobertura (camada 2) contornados de vermelho. Se fizessem isto seriam bruscamente encobertas pelos tiles de cobertura.
Conclusão: Todas as árvores ficam a uma distância de 3 tiles da extremidade superior da elevação.
Solução: Mais mesclagens... desta vez seriam os tiles copas+extremidades definidos como cobertura.
The Mana World ainda pode melhorar, mas ele já é bem legal !!!
Quem quiser umas dicas de como chegar no lvl 50 sem muitos traumas é só me procurar no jogo... tarefa nada fácil !
:: Tiled e o formato TMX ::.
Tiled é um editor genérico de mapas de tiles que roda em java. Ele é muito interessante pois edita várias camadas de tiles e salva tudo em um xml (base64 e compactado). Ele segue um padrão que pode ser facilmente adotado por outros jogos... padrão que foi utilizado no jogo The Mana World !
Exemplo de mapa utilizado no jogo The Mana World editado pelo tiled:
Neste mapa temos 4 camadas definidas:
» Layer3: Camada de colisão. (A exibição foi desabilitada)
» Layer2: Camada de cobertura. Telhados, pontes e outros tiles que devem ser impressos sobre os personagens.
» Layer1: Camada de objetos. Árvores, pedras e qualquer coisa sobre o piso.
» Layer0: Camada de piso. Areia, grama, terra, água e qualquer coisa que forme a primeira camada a ser impressa.
Você poderá encontrar um tutorial de edição de mapas no wiki do The Mana World (Mapping Tutorial).
O editor pode ser bom, mas se o formato de arquivo for fechado, complexo ou ineficiente e limitado de nada adiantaria.
TMX é um formato baseado em XML. Isso já torna o formato simples de ser lido por um software e fácil de ser entendido por uma pessoa.
Também pelo fato de ser XML podemos adicionar novas funcionalidades... até mesmo manualmente.
Veja a simplicidade de um arquivo TMX:
<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>
» 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 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 !!!
Postado por
Diogo_RBG
3
comentários
Tópicos: sdl
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 !).
Postado por
Diogo_RBG
0
comentários
Tópicos: dicas
segunda-feira, 23 de junho de 2008
Controle de tempo e Frame Rate
int t1,t2, delay; void logica(int t1){ class Timer {
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....:: Limitar ou não ::.
Limitar a taxa de frames pode servir apenas para não desgastar o processador.
É claro que pode servir para sincronizar o tempo no jogo, mas isso não pode influenciar na jogabilidade. Digo que você pode querer usar os frames para controlar a animação e os estados do jogo e que pode até funcionar se seu jogo for bem simples.
Uma implementação por frames trás resultados negativos em algumas ocasiões:
» Quando o PC é muito lento e não consegue processar a quantidade de frames que você previa. O jogador não perde nenhum detalhe da animação, mas o jogo fica lento.
» Tudo no seu jogo será medido em frames e você terá dificuldades em aumentar ou diminuir o frame rate.
» Em algumas ocasiões um só frame não será suficiente e você terá que contá-los. Acredite, nesta ocasião o controle por tempo ganha em disparado de incrementos por interação.
.:: Frame Rate em SDL ::.
Em SDL usamos a função SDL_GetTicks() para saber quantos milissegundos se passaram. SDL_GetTicks() começa a contar assim que a SDL é inicializada. Você só não pode esquecer de inicializar a SDL passando SDL_INIT_TIMER para SDL_Init().
Para limitar a taxa de frames eu só preciso saber o tempo antes (t1) e depois (t2) da execução da lógica do jogo e logo depois esperar o restante do tempo com SDL_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);
}
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:
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);
}
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:
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 !
Postado por
Diogo_RBG
0
comentários
Tópicos: sdl
quinta-feira, 10 de abril de 2008
[Mini-curso] Programação de jogos 2D com SDL
Por incentivo do CACComp e do interesse de expansão do GrupoJ, estarei apresentando o mini-curso: Programação de jogos 2D com SDL.
Trata-se de aulas práticas e teóricas sobre como programar jogos 2D utilizando a biblioteca SDL e a linguagem C/C++.
Datas: 19/04, 26/04 e 03/05
Horário: 14:00 às 17:40
Local: Labin 09, Bloco III - UFT
Inscrição: R$ 3,00
Para fazer as inscrições procure o CACComp no Bloco III e corra porque as inscrições são limitadas.
» Post Completo....:: Ementa ::.
1 Introdução (19/04)
1.1 O que é e como surgiu
* Simple DirectMedia Layer
1.2 O que pode fazer
* Vídeo
* Eventos
* Áudio
* CD-ROM áudio
* instancias
* Timers
* Independência na ordenação da memória
1.3 Como e onde funciona.
* Linux
* Win32
* BeOS
1.4 Bibliotecas estensivas
* Imagem
* Textos
* Processamento Gráfico e Geometria
* Som
2 Trabalhando com SDL
2.1 Instalando e configurando o ambiente de programação
* Instalação pelo devpaks
* Instalação por código fonte no linux
* Configuração do projeto e compilação no Dev-Cpp (Windows)
* Configuração do projeto e compilação make e gcc (Linux)
2.2 Escrevendo o primeiro código
* Exemplo básico proposto pelo Dev-Cpp
2.3 Explicações mais detalhada da API da SDL (26/04)
* inicialização
* Modo de vídeo
* Manipulação de imagens
* Manipulação de eventos
* Atualização da tela e controle de FPS
2.4 API's extensivas
* SDL_Image (imagem)
* SDL_Ttf (texto)
* SDL_Gfx (Processamento Gráfico e Geometria)
* SDL_Mix (Som)
2.5 Exemplos e soluções para jogos
* A problemática dos jogos e algumas soluções
2.6 Apresentação da Implementação (03/05)
* Apresentação dos trabalhos desenvolvidos pelos alunos
.:: Downloads ::.
» Slides
» Slides 2
» Slides 3
» Código Fonte do primeiro dia
» Código da classe Sprite
» Código do jogo da velha
Postado por
Diogo_RBG
8
comentários
quinta-feira, 27 de março de 2008
SDL em Processamento de Imagens
Depois de muito tempo sem postar, estou de volta.
Desta vez não vou falar de teoria ou documentação, mas apenas de um exemplo prático de como utilizar SDL em Processamento de Imagens.
SDL não tem componentes gráficas, caixa de diálogo ou funções de acesso ao pixel, mas a gente pode improvisar.
Em SDL trabalhar com pixels é muito fácil e rápido.
Imagem 2D é com a SDL mesmo !
Download: » código fonte
Postado por
Diogo_RBG
4
comentários
quinta-feira, 7 de fevereiro de 2008
SDL_Surface - Introdução detalhada
typedef struct SDL_Surface { #include <SDL/SDL.h> SDL_Surface *img = NULL; SDL_Surface *aux, *img; int SDL_BlitSurface( SDL_BlitSurface(img, NULL, screen, NULL); SDL_Rect xy = {x,y,0,0}; SDL_Rect ret = {retx, rety, retw, reth};
Este post deveria ter vindo logo depois do primeiro sobre SDL (SDL - A Biblioteca dos Jogos 2D). Se você estava meio perdido esta leitura é recomendada.
A abordagem começa com os pixels e se estende até o blit completo ou parcial.
» Post Completo...*** SDL_Surface ***
É uma superfície gráfica (área de memória) que armazena uma imagem do tipo raster (ou bitmap, que significa mapa de bits).
A cada pixel (menor unidade de uma imagem) é atribuído uma cor. Para representar uma cor no padrão RGB pode-se utilizar um número variável de bits: 8bpp (8 bits por pixel), 16bpp, 24bpp ou 32bpp. Isto interfere diretamente na quantidade de cores que serão apresentadas e no tamanho do arquivo.
Esta é a estrutura da SDL_Surface:
Uint32 flags;
SDL_PixelFormat *format;
int w, h;
Uint16 pitch;
void *pixels;
SDL_Rect clip_rect;
int refcount;
} SDL_Surface;
Todos estes valores são apenas para leitura, exceto pixels. Nem sempre pixels está disponível para escrita, neste caso você deve usar SDL_LockSurface() e SDL_UnlockSurface() para ter acesso direto aos dados.
Uma curiosidade é saber como os pixels estão dispostos exatamente em *pixels. Uma imagem 3x3 de 24bpp possui pitch=12 e pixels[36]. w*h*bpp = 3*3*3 = 27, mas não é dessa forma que as coisas funcionam.
Observe a imagem:
Pode existir lixo no final de cada linha quando ela não for multipla de 32 bits (4 bytes), mas isto não é um bug, é apenas uma otimização. Logo o cálculo fica: pitch*h = 36
*** Screen ***
É através da SDL_Surface que tudo será apresentado ao usuário, e usualmente eu nomeio a superfície da tela como screen:
SDL_Surface *screen = NULL; //- Tela
int main(int argc, char *argv[]){
//- Inicializa a SDL -//
SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER);
//- Inicializa a tela -//
screen = SDL_SetVideoMode(640,480,32,SDL_SWSURFACE);
//- título da janela -//
SDL_WM_SetCaption("Aplicação SDL em 3 segundos !!!", NULL);
//- Atualiza a tela -//
SDL_Flip(screen);
//- Pausa de 3 segundos -//
SDL_Delay(3000);
//- Finaliza a SDL -//
SDL_Quit();
return 0;
}
» Incluí a biblioteca SDL. (Ela deve estar instalada)
» Criei um ponteiro para armazenar a superfície da tela (screen).
» Minha função main da maneira correta, exatamente como a SDL a espera.
» Inicializo a SDL
» Inicializo a tela. 640x480 e 32bpp é criada na memória.
» Define "Aplicação SDL em 3 segundos !!!" como título da janela.
» Mostra a superfície no vídeo. Se você estiver utilizando SDL_DOUBLEBUF esta função terá o papel crucial.
» Como ainda não estamos tratando eventos do teclado fiz uma pausa de 3 segundos para que a janela possa ser visualizada.
» Devemos inicializar e também finalizar a SDL.
» Retornar 0 indica que tudo ocorreu bem.
*** Imagens ***
Com SDL é fácil carregar (SDL_LoadBMP) e salvar (SDL_SaveBMP) imagens no formato BMP. Pena que o formato BMP não suporta mais que 24bpp, e isto nos limita a usar cor de transparência, já que não podemos carregar imagens com alpha. O formato PNG suporta alpha, mas não se pode carregar PNG com a função SDL_LoadBMP(), para isto devemos utilizar a lib SDL_Image (veremos mais à frente).
Trecho de código:
...
int main(int argc, char *argv[]){
//- Inicializa a SDL -//
...
//- carrega imagem -//
img = SDL_LoadBMP("img/imagem.bmp");
//- pinta imagem na em outra screen -//
SDL_BlitSurface(img,0,screen,0);
//- salvando a tela -//
SDL_SaveBMP(screen,"img/screen.bmp");
//- Atualiza a tela -//
SDL_Flip(screen);
//- Pausa de 3 segundos -//
SDL_Delay(3000);
//- limpando memória -//
SDL_FreeSurface( img );
//- Finaliza a SDL -//
SDL_Quit();
return 0;
}
» Em main inicializamos a SDL.
» Carregamos "img/imagem.bmp" com a função SDL_LoadBMP e guardamos seu ponteiro em img. Usar / é o mesmo que usar \\ e funciona no Windows e Linux. Caso a imagem não seja carregada verifique se seu nome está correto ou se o programa está sendo executado do local correto. system("pwd") ou system("dir") podem esclarecer o que digo.
» SDL_BlitSurface é capaz de pintar uma superfície sobre outra. Desta maneira a imagem será pintada completamente nas coordenadas 0x0 da imagem de destino.
» Com SDL_SaveBMP é fácil gravar uma screenshot do seu jogo !
» SDL_Flip e SDL_Delay para visualizarmos a janela.
» SDL_FreeSurface é utilizada para limpar a memória da imagem carregada.
» Por fim SDL_Quit e return 0;
Se você quiser ganhar performance em seu jogo não trabalhe com diferentes formatos de superfície (não estou falando dos formatos de arquivo). Toda vez que blita uma superfície de 24bpp em outra de 32bpp há uma conversão em tempo de blitagem, e para ganhar performance temos que deixar todas as superfícies convertidas em um único formato, o formato do display (nossa tela).
aux = SDL_LoadBMP("smiley.bmp");
SDL_SetColorKey(aux, SDL_SRCCOLORKEY, SDL_MapRGB(aux->format,0xff,0,0xff) );
img = SDL_DisplayFormatAlpha(aux);
SDL_FreeSurface(aux);
» O rosa 0xff00ff é setado como cor de transparência. (faça antes de converter pro display)
» SDL_DisplayFormatAlpha é chamado e converte a imagem para 32bpp e transforma a cor de transparência em uma camada de transparência.
» aux deve ser limpada, pois SDL_DisplayFormat cria uma nova superfície.
*** SDL_BlitSurface ***
Até agora só trabalhamos com SDL_BlitSurface em sua forma mais simples (imagem, NULL, imagem, NULL). Esta função tem diversas utilidades, tais como imprimir apenas parte de uma imagem em outra.
Analisando cuidadosamente temos:
SDL_Surface *src, //- Imagem de origem (imagem a pintar)
SDL_Rect *srcrect, //- Retângulo de corte. permite pintar
// parte dela.
SDL_Surface *dst, //- Imagem de destino (imagem modificada)
SDL_Rect *dstrect //- Coordenadas da imagem de origem.
);
A forma mais simples de uso é onde uma imagem é toda impressa em outra nas coordenadas de origem:
SDL_BlitSurface(img, NULL, screen, &xy);
SDL_Rect xy = {x,y,0,0};
SDL_BlitSurface(img, &ret, screen, &xy);
» Uma imagem não precisa estar realmente cortada para que se possa imprimir parte dela.
» A imagem de destino nunca irá mudar de tamanho para acomodar a imagem de origem.
» Só serão aproveitados o x e y do retângulo de destino, logo ele só servirá para posicionar onde a imagem será impressa.
» Você não poderá redimensionar ou rotacionar imagens com SDL_BlitSurface. Para isto use SDL_Gfx.
*** Link's ***
Download: » código fonte
» Surface Loading and Blitting
» Documentação da SDL (online)
Postado por
Diogo_RBG
5
comentários
sábado, 26 de janeiro de 2008
Script's GIMP - Python-Fu !!!
Calma... Python-Fu não é um novo estilo ninja !!!
Não é atoa que o GIMP é a melhor ferramenta gráfica 2D e open source da atualidade. Ela é perfeita para ser manipulada por artistas e programadores.
Saiba como automatizar aquele efeito especial que você geralmente usa ou criar algum que só é possível através de programação !
» Post Completo...*** GIMP ***
Wikipédia: "O GNU Image Manipulation Program ou GIMP é um editor de imagens raster (ou bitmap, que significa mapa de bits)."
"O GIMP é muito utilizado para processamento de imagens e fotografias. Seus usos incluem criar gráficos e logotipos, redimensionar fotos, alterar cores, combinar imagens utilizando o paradigma de camadas, remover partes indesejadas das imagens e converter arquivos entre diferentes formados de imagem digital."
"Assim como o uso interativo, o GIMP pode ser inserido em scripts e chamadas de sistemas em programas compilados. Para isso pode-se usar, Scheme (ou ScriptFu), Perl, Python, Tcl, Ruby, e programas capazes de executar comandos UNIX."
Não sou profissional, mas digo que o GIMP é completo (ou quase !). Com ele é fácil corrigir fotos, manipular diversos tipos de imagens e criar efeitos especiais.
Esta imagem foi produzida com a ajuda do meu plug-in borda cubismo (disponível nos exemplos), mas com poucos cliques é possível reproduzí-lo manualmente utilizando o plug_in_cubism em filtros/Artísticos/Cubismo....
*** Script Scheme ***
Wikipédia: "Scheme é uma linguagem de programação multi-paradigma que suporta programação funcional e procedural. Foi criada por Guy L. Steele e Gerald Jay Sussman nos anos 1970 a partir da linguagem Lisp com o intuito de estudar a teoria dos atores de Carl Hewitt."
"Devido à sua sintaxe completamete aninhada, não existem regras de precedência de operadores e sua notação parentizada é usada para todas as chamadas de função, desta forma não há ambigüidades como as que são encontradas nas linguagens de notação infixa."
Na prática, Scheme não é pra qualquer um !
» Scheme Tutorial
» Script-Fu aula 1
» Script-Fu aula 2
Exemplos no download abaixo.
*** Plug-in Python-Fu ***
Wikipédia: "Python é uma linguagem de programação de alto nível interpretada, interativa, orientada a objetos e de tipagem dinâmica e forte, lançada por Guido van Rossum em 1991."
"A linguagem foi projetada com a filosofia de enfatizar a importância do esforço do programador sobre o esforço computacional. Prioriza a legibilidade do código sobre a velocidade ou expressividade. Combina uma sintaxe concisa e clara com os recursos poderosos de sua biblioteca padrão e por módulos e frameworks desenvolvidos por terceiros."
Em outras palavras, adeus dores de cabeça !
Só não se esqueça que o pacote gimp-python deve estar instalado e que os arquivos devem ser copiados para "/home/usuario/.gimp-x.x/plug-ins" nomeados como "meu_plugin.py" com permição de execução.
» Gimp-Python
» Python-fu para no programadores
Exemplos no download abaixo.
*** Plug-in em C ***
O GIMP é feito em C, logo, penso que escrever plug-ins em C pode ser vantajoso.
A parte inicial é mais complicada de entender, mas depois de superada você estará programando em C como em qualquer outro programa que já tenha feito.
A interface gráfica é feita em GTK, e isto é outra coisa que deve ser estudada. Mas com o básico já se pode criar diálogos para capturar os dados de entrada.
» Compilando (e instalando) plug-in do Gimp para Linux e Windows
» COMO ESCRIBIR UN PLUG-IN PARA GIMP (parte I)
» COMO ESCRIBIR UN PLUG-IN PARA GIMP (parte II)
*** Conclusões ***
Esta foi uma abordagem geral, e por enquanto é tudo que disponho.
Não se trata de escolher a melhor linguagem, há outras variáveis em jogo. Metade dos plug-ins e script's do GIMP são escitos em C e Scheme e existem fortes razões para isto.
Não existe nada que se case melhor ao GIMP do que um plug-in em C, mas podem ocorrer casos em que isto é irrelevante.
Python-Fu é 1000 vezes mais fácil de entender e programar que Scheme, mas isto tem um custo (dependências). Para que um plug-in Python-Fu funcione você precisa ter o pacote gimp-python instalado e funcionando.
O que faz a diferença é saber utilizar instruções complexas e deixar que o próprio GIMP faça o trabalho. Para consultar as instruções disponíveis do GIMP use o Navegador de Plug-ins e o Navegador de Procedimentos que estão localizados no menu Extras.
Criar um plug-in para o GIMP é mais simples que escrever um programa para edição de imagens e ainda é mais prático de usar, considerando todas as ferramentas do GIMP que estarão disponíveis.
Era exatamente isto que eu buscava para apresentar em processamento de imagens !!!
*** Link's ***
Download: » Exemplos
» GIMP Plug-In Registry (Repositório oficial)
» Scheme Tutorial
» Processamento Digital de Imagens (Site com muitas referências)
» Gimp-Python
» Python-fu para no programadores
» Compilando (e instalando) plug-in do Gimp para Linux e Windows
» COMO ESCRIBIR UN PLUG-IN PARA GIMP (parte I)
» COMO ESCRIBIR UN PLUG-IN PARA GIMP (parte II)
---
Ainda não tenho experiência com os plug-ins do GIMP, e espero que com este post eu possa ajudar e receber ajuda. Não encontrei muito material na Internet, se alguém tiver algum material sobre o assunto terei o prazer de incluir aos outros.
Postado por
Diogo_RBG
4
comentários
Tópicos: gimp
quarta-feira, 9 de janeiro de 2008
Imprimindo texto com SDL_Ttf
int TTF_Init(); TTF_Font *font_16 = NULL; void print(int x,int y,const char *format, ...){ std::string str;
Você já deve ter reparado que a função printf não faz milagres quando se está utilizando SDL. Isso é normal, pois a superfície da SDL não é uma saída padrão. A saída padrão é o console (Linux) ou o arquivo stdout.txt (Windows).
A única maneira de se imprimir texto na superfície da SDL é desenhando letra por letra, mas isso não significa que você tenha que fazer isso na unha !
A forma mais simples de resolver este problema é utilizando a lib SDL_Ttf (SDL True Type Fonts).
Além de mostrar minhas soluções para entrada e saída de texto também abordo um pouco sobre manipulação de argumentos variáveis.
» Post Completo...*** SDL_Ttf ***
Tradução do LazyFoo: "SDL não suporta arquivos *.ttf nativamente e por isso a biblioteca de extensão SDL_Ttf é necessária. SDL_Ttf é uma biblioteca de extensão que lhe permite gerar superfícies a partir de certo tipo de fontes."
Isso significa que a lib SDL_Ttf não carrega a font, mas a converte para uma superfície (SDL_Surface) e após carregada não se pode alterar o tamanho da fonte, por exemplo.
Como sempre você pode baixar do Site do projeto, do Devpaks ou instalar direto do repositório (distribuições derivadas do Debian):
$ sudo apt-get install libsdl-ttf2.0-dev
E para linkar ao seu projeto use -lSDL_ttf
Algumas de suas funções são:
void TTF_Quit();
char *TTF_GetError();
TTF_Font *TTF_OpenFont(const char *file, int ptsize);
void TTF_CloseFont(TTF_Font *font);
int TTF_SizeText(TTF_Font *font, const char *text, int *w, int *h)
SDL_Surface *TTF_RenderText_Solid(TTF_Font *font, const char *text, SDL_Color fg);
...
É importante saber que é preciso inicializar (TTF_Init) e encerrar (TTF_Quit) a biblioteca e também carregar (TTF_OpenFont) e descarregar (TTF_CloseFont) o recurso TTF_Font.
A parte de renderização (impressão de texto) possui alguns conceitos a serem estudados:
» Solid: Rápido e direto. Cria uma nova camada de 8bpp (usa paleta) com o texto impresso em baixa qualidade (2 cores). 0 é o colorkey e 1 é a cor da font. O resultado é rápido, o texto tem cor de transparência mas é serrilhado.
» Shaded: Lento com caixa de cor sólida. Cria uma nova camada de 8bpp (usa paleta) com o texto impresso em alta qualidade (com anti-aliasing). O resultado não é muito rápido, o texto não é serrilhado mas também não tem cor de transparência.
» Blended: Muito lento e com camada de transparência. Cria uma nova camada de 32bpp (usa camada alpha) com o texto impresso em alta qualidade (com anti-aliasing). É o resultado mais lento, o texto não é serrilhado e tem transparência.
A lib SDL_Ttf permite vários tipos de codificação de texto: LATIN1, UTF8, UNICODE text/glyph.
Isto significa que você não terá problemas com acentuação, como é comum acontecer quando você escreve seu código em ISO-8859-1 e o programa imprime num terminal IBM-850.
UTF-8 é a codificação de tamanho variável que pode representar qualquer caracter universal padrão do Unicode, mas para nós do ocidente o LATIN1 é mais do que suficiente.
Um exemplo rápido de como utilizar a lib SDL_Ttf: (Não compile isto !)
SDL_Surface *screen=NULL, *aux=NULL;
...
int TTF_Init();
...
font_16 = TTF_OpenFont("free_serif.ttf", 16);
...
SDL_Color cor = {255,255,255,0};
aux = TTF_RenderText_Solid(font_16, "Texto !!!", cor );
SDL_BlitSurface(aux, NULL, screen, NULL);
SDL_FreeSurface(aux);
...
TTF_CloseFont(font_16);
...
void TTF_Quit();
*** O Exemplo ***
No exemplo você vai encontrar os 3 tipos de renderização, um exemplo de texto formatado e um exemplo de leitura de texto.
Download: » código fonte
*** Impressão de texto formatado ***
A função printf sempre foi uma mão na roda, pois ela formata, converte e imprime (Tudo ao mesmo tempo). E o que dizer da quantidade variável de argumentos ?! Ela sempre foi um verdadeiro canivete suíço !!!
Não podemos imprimir direto na tela, mas podemos imprimir para um vetor com sprintf. E melhor ainda, criar nossa função print(x,y,texto,...) com argumentos variáveis com a ajuda da função vsprintf:
SDL_Surface *aux;
SDL_Color cor = {255,255,255,0};
SDL_Rect ret={x,y,0,0};
//- Imprimindo para vetor -//
char buf[256];
va_list args;
va_start (args, format);
vsprintf (buf,format, args);
va_end(args);
aux = TTF_RenderText_Blended(font_16, buf, cor);
SDL_BlitSurface(aux,0,screen,&ret);
SDL_FreeSurface(aux);
}
*** Manipulação de argumentos variáveis ***
Já se perguntou como como é possível declarar: int printf( const char *format, ... ) ?
Samuel Dias Neto: "Uma função pode ser chamada com um número variável de argumentos sendo estes argumentos de diversos tipos. O arquivo de cabeçalho stdarg.h declara um tipo va_list e define três macros (va_start, va_arg e va_end) para manipular uma lista de argumentos cuja quantidade e tipos são desconhecidos pela função."
» va_list: tipo para a listas de argumentos variável.
» va_start: inicializa a listas de argumentos variável.
» va_arg: retira o próximo argumento.
» va_end: finaliza a listas de argumentos variável.
*** Leitura de texto ***
Já sabemos como escrever, agora só falta saber como ler ! Aqui é a parte em que eu tive que improvisar, pois não existe a função SDL_Scanf !!!
Minha função de leitura foi feita para teclados ABNT2 e não aceita acentuação, mas pode quebrar um galho:
bool shift;
void scan(SDLKey key, bool shift){
...
if(key==SDLK_BACKSPACE && !str.empty())
str.erase(str.length()-1);
else if(key==' ')
str += key;
else if(key>=SDLK_KP0 && key<=SDLK_KP9)
str += key - SDLK_KP0 + '0';
else if(key>='a' && key<='z'){
if(shift)
str += key-'a'+'A';
else
str += key;
}else{
...
}
}
*** Link's ***
Download: » código fonte
» Site SDL_Ttf
» LazyFoo (True Type Fonts)
» SDL - A Biblioteca dos Jogos 2D
Postado por
Diogo_RBG
4
comentários
terça-feira, 8 de janeiro de 2008
DR Tetris 0.3 - Tetris no estilo tradicional !
2007 foi um ótimo ano, mas 2008 promete ! E para começar o ano com o pé direito estou lançando a terceira edição do meu jogo de tetris.
DR Tetris 0.3 é um jogo de tetris estilo tradicional que promete matar saudade dos velhos tempo em que se perdiam horas em mini games (Eu sou um exemplo !)
Algumas das características são:
* Roda em Windows e Linux.
* Sons do jogo original (Ou quase !).
* Sombra projetando onde a peça irá cair.
* Placar de recordes com 13 posições (Editável).
* Acumulador de pontos em sequência.
* Níveis diferentes de velocidade.
Você pode baixar no site do jogo: DR Tetris
...que ainda se encontra em construção !
---
DR Teris ==> Diogo Rigo Tetris :)
Este é o motivo do meu sumisso !
Em breve voltarei a postar meus tutorias de SDL.
Postado por
Diogo_RBG
8
comentários
Tópicos: downloads


