terça-feira, 29 de maio de 2012

paOpenGLDraw finalizada!

Olá a todos!

Consegui finalizar por hora a parte de desenhos de primitivas da engine. Alguns desenhos suportam texturas com GL_REPEAT. Outros, somente texturas com GL_CLAMP_TO_EDGE. Algumas primitivas também suportam smooth de cor para cada vértice.

Algumas coisas ainda estão por ser feitas, como o desenho de qualquer poliedro desejado de modo fácil, desenho usando smooth para todas as formas, e suporte para GL_REPEAT para qualquer tipo de forma geométrica também, o que deixarei para mais tarde devido ao tempo para a entrega do projeto estar se esgotando.

É importante ressaltar que o comando  "setPolygonDrawMode" define o modo como a forma será desenhada (de modo normal, por linhas - wireframe - , ou somente os vértices da mesma).

A seguir, todas as forma geométricas 2D e 3D suportadas e suas respectivas características:
  • Pontos;
  • Linhas (2D e 3D);
  • Linhas tracejadas (2D e 3D);
  • Grid;
  • Triângulo (suporta texturas com GL_REPEAT);
  • Quadrado/Retângulo (suporta texturas com GL_REPEAT);
  • Círculo (suporta texturas);
  • Elipse;
  • Poligonos com textura;
  • Polígonos com smooth de cores para cada vértice;
  • Polígonos com dimensões internas dinâmicas e ângulo inicial e final variados (Ex: podemos desenhar um polígono com um buraco no centro e indo de 0 a 90 graus, formando assim um leque);
  • Skybox;
  • Cubo/Paralelepípedo (suporta texturas com GL_REPEAT);
  • Pirâmide (suporta texturas com GL_REPEAT);
  • Esfera (suporta texturas);
  • Poliedros esféricos (que nada mais são que esferas com número de linhas de definição dinâmicas). Suporta texturas;
  • Cilindros parciais (somente o envolto) e completos (o envolto e os círculos laterais). Suporta texturas;
  • Cones parciais (somente o envolto) e completos (o envolto e o círculo da base). Suporta texturas;
  • Polígono/Poliedro com posicionamento dos pontos a ser definido pelo usuário (suporta smooth de cores).
As implementações futuras envolverão:

 * Suporte de textura para todas as fomas

 * Suporte de GL_REPEAT para todas as texturas

 * Desenho com smooth para todas as formas

 * Desenho de qualquer tipo de poliedro de modo fácil

 * Desenho de mais formas cilindricas

 * Melhora das texturas esféricas

 * Suporte a curvas

 * Suporte a texturas 1D (para linhas) e 3D (para volumes)

domingo, 27 de maio de 2012

Arte + Game Design - Elementos gráficos "in Game"

Oie!!!!

Como prometido já estão prontos os novos elementos gráficos, desde umas duas semanas na verdade, mas como estou com várias correções e  atualizações na documentação acabei não fazendo este post antes.
Então, vamos lá!

A criação destes novos elementos é produto das sprints Produção dos elementos da arte – HUD PadrãoProdução dos elementos da arte – HUD (Personagens) inclusas como tarefas na estória Desenvolvimento Intermediário nas Estimativas de Desenvolvimento no Documento de Arquitetura  e como estórias individuais na ferramenta Pivotal Tracker.

Esses Elementos são os utilizados "in Game"  na tela em que o jogo estará em andamento, ou seja, a partida em si e os turnos de cada jogador.
Como já comentei optamos em utilizar como base o conceito do jogo original em sua versão digital, para mais detalhes confira nos posts anteriores: Arte Inicial e Game Design.

Agora vamos ver a personalização dos elementos gráficos para a nossa própria versão do jogo "Ticket to Ride"!!!

Produção dos elementos da arte – HUD Padrão


As dimensões de tela foram definidas como 1024 x 768, além do modo Full Screen e a área do mapa 842 x 512, assim desenvolvi o background  com estas dimensões.
Já no conceito resolvi criar um fundo com textura de madeira para proporcionar um ar rústico, também coloquei um trilho na parte inferior da imagem onde ficam as cartas que o jogador atual possui na "mão", levando em consideração que serão estas que ele utilizará para construir suas rotas no mapa, criando assim uma imagem de referencia entre cartas e trilhos. Por fim, fiz uma moldura com tons amarelos e alaranjados.

Primeiro estudo do Background
(Figura 1 - Primeiro estudo do Background)

Para finalizar utilizei efeitos para deixar o conjunto com uma perspectiva melhor com sombra na moldura e 3D no trilho dando uma melhorada na posição deste.

(Figura 2 -  Background com Textura Simples)
(Figura 2 -  Background com Textura Simples)

Ai surgiu a ideia de estilizar mais a textura de madeira do fundo, confira o resultado:

(Figura 3 -  Background com Textura Estilizada)
(Figura 3 -  Background com Textura Estilizada)

Ainda não decidimos qual das texturas de fundo utilizaremos...

Também fazem parte desta as cartas anteriormente estilizadas com base nas originais, porém agora elas estão com as dimensões definitivas, aoalterar as dimensões consequentemente precisei otimizar as imagens.

(Figura 4 - Cartas de Construção(Trens Coloridos))
(Figura 4 - Cartas de Construção (Trens Coloridos))

Quanto as cartas de destino faltam algumas definições, assim que acerta-las disponibilizo as cartas, de qualquer forma seguirão o padrão das originais.

Também entra na hud padrão as peças, que na verdade é uma peça branca que terá a cor modificada de acordo com o jogador que a utilizar.

(Figura 5 - Peça vagão)
(Figura 5 - Peça vagão)


O ultimo detalhe da hud padrão é o botão "?" que conterá um help sobre os comandos e esta localizado no canto superior esquerdo da tela.

(Figura 6 - Botão de help "?")
(Figura 6 - Botão de help "?")

(Figura 7 - Botão de help "?" ativo)
(Figura 7 - Botão de help "?" ativo)




- Produção dos elementos da arte – HUD (Personagens) 

Os personagens são baseados nas 5 cores disponíveis para escolha dos jogadores: Preto, Vermelho, Azul, Verde e Amarelo. Cada um tem uma personalidade distinta como pode ser observado no próprio desenho deles, tentei abranger o máximo de estilos de pessoas que jogam Ticket to Ride apesar da limitação de cinco possibilidades.
A hud é formada pela 'foto' do personagem caracterizado com acessórios da sua cor, a moldura envolve esta e também os locais onde aparecerão a quantidade de trens (abaixo da imagem de locomotiva) e pontos atuais, estendendo-se em uma linha personalizada até a outra extremidade da tela servindo como apoio das cartas do jogador.

Abaixo as huds dos personagens no modo jogador atual, esta fica na parte inferior da tela:

(Figura 8 - Lady)
(Figura 8 - Lady a Charmosa)

(Figura 9 - Shadow)
(Figura 9 - Shadow Mistério...)

(Figura 10 - Scot)
(Figura 10 - Scot o Aventureiro)

(Figura 11 - Sarah)
(Figura 11 - Sarah a Estrategista)

(Figura 12 - John)
 (Figura 12 - John o Divertido)


E na parte superior da tela ao lado do botão de help ficam as huds dos outros personagens que fazem parte da partida e aguardam seu turno. Se trata de uma hud diminuída da hud de personagem atual sem a linha inferior desta, confira:

                               (Figuras 13 - Personagens aguardando seu turno) Shadow(Figuras 13 - Personagens aguardando seu turno) Lad(Figuras 13 - Personagens aguardando seu turno) Scot

                                            (Figuras 13 - Personagens aguardando seu turno) Sarah(Figuras 13 - Personagens aguardando seu turno) John
(Figuras 13 - Personagens aguardando seu turno)

Enfim, nas próximas imagens pode-se visualizar o resultado final com a textura normal e a estilizada. Se alguém quiser opinar sobre qual prefere ou fazer sugestões sinta-se a vontade, espero que gostem!

(Figura 14 - Resultado Final)
(Figura 14 - Resultado Final)

(Figura 15 - Resultado Final 2)
(Figura 15 - Resultado Final 2)

Novas Implementações na paOpenGLDraw

Olá!

Devido a alguns problemas, não acabei implementando muitas coisas nesses ultimos dias. Também perdi muito tempo corrigindo um bug no desenho (as texturas não estavam mais funcionando) e na câmera (as transformações passaram a acontecer invertidas).

Pra compensar, diversas alterações se fizeram necessárias na classe draw para chegar à formula perfeita, e desconfio que esta formula ainda não chegou ao seu ápice.

A maior decisão de projeto envolveu remover o modo de posicionamento do desenho. Agora para movimentar os objetos no cenário só é possível utilizando-se a classe de transformações.

Também inseri desenho de textura com e sem glRepeat, de forma que o usuário deve informar apenas o tamanho da primitiva gráfica, quais serão as texturas utilizadas, qual será a ordem para cada face, e qual será o fator de repetição para cada face.

Para contextualizar, segue o cabeçalho do método drawParallelepiped:

//Desenha um paralelepípedo ou cubo dependendo das dimensões desejadas
//Recebe o tamanho em largura, altura e profundidade no vetor size
//Recebe um ponteiro para um array contendo todas as texturas usadas na rederização de cada face
//Recebe a sequencia de aplicação de textura (ex: se houver apenas uma textura em textures,
//  podemos setar o valor de textureSequence como: {0,0,0,0,0,0}, ou seja, a mesma textura para todas as faces)
//Em caso de uso de TEXTURE_REPEAT, passar o fator de repetição para cada face em X e Y (factor)
//(usar DEFAULT_FACTOR para GL_CLAMP)
//A ordem das faces desenhadas é: TOP, BOTTOM, FRONT, BACK, LEFT, RIGHT
void drawParallelepiped(const math::Vector3D size,const GLuint *textures,
                                        const GLuint textureSequence[6],const GLuint factor[6][2]);


Também implementei Culling para todo tipo de forma desenhada para otimizar a engine. Apesar de quase, a parte de desenho ainda não está finalizada, pois estou dando uma melhor estudada em texturas a fim de criar formas geométricas arredondadas com textura aplicada.

quinta-feira, 24 de maio de 2012

Melhorando o desenho

Olá a todos!

De acordo com o cronograma de desenvolvimento, a próxima etapa é implementar a colisão.
Pensando nisso, fui analisar como estava a classe paOpenGLDraw para poder criar maneiras de integrar o desenho à colisão em uma classe de sprites.

Quando observei os aspéctos da classe, reencontrei o caos!

Para contextualizar, é importante lembrar da época da refatoração do código e das implementações a nível de prototipagem. Nesse contexto, todas as demais classes foram modificadas e melhoras, exceto a pobre paOpenGLDraw.

Então, antes de iniciar a implementação das colisões, decidi por buscar finalizar os métodos restantes de desenho. Acabei também corrigindo um bug da câmera e da paOpenGLWindow.

Dessa forma, as seguintes funcionalidades foram implementadas:

  • Melhora do método já existente "setSimulationStuff" para setar, de acordo com a qualidade desejada, qual será a qualidade do mipmap das texturas.
  • Método setColor.
  • Método para deletar texturas carregadas.
  • Método drawLine.
  • Método drawGrid.
  • Método drawSkybox.
  • Método para desenho de cubos e paralelepípedos.
  • Método drawPyramid.
  • Método drawSphere (EM CONSTRUÇÃO).

É importante ressaltar que todos as implementações envolvem aplicação de textura e culling.
Ainda faltam implementar os métodos:
  • drawTriangle
  • drawRect
  • drawCircle
Finalizadas essas implementações, planejarei como será a integração da colisão às classes de desenho, porém já dando inicio ao mesmo tempo ao gerador de mapas que precisa ser implementado o quanto antes!

domingo, 20 de maio de 2012

Ultimos Ajustes

Olá...

Depois de uma semana trabalhando com a parte de som, finalmente cheguei ao resultado desejado.

A ultima funcionalidade adicionada foi a de limitar os tipos de arquivos de sons carregáveis, disparando uma exceção em caso de formato não suportado.

Se fosse continuar a programação dessa parte da engine, ainda teria que inserir controladores de paning e de distância do som de acordo com a posição do jogador. Infelizmente não tenho o tempo necessário para isso e por hora a parte de som fica por aqui.

Restando somente a parte de colisão, agora vou buscar inserir na engine o método de colisão por picking para poder iniciar a construção do gerador de mapas.

paSDLChannelPlayer

Olá!

Levando em consideração os moldes criados para paSDLMusicPlayer, criei paSDLChannelPlayer para gerenciar os sfx.

Apesar da maior complexidade, foi muito mais fácil criar essa classe, já que a maioria da programação de dependência com um gerenciador já estava feita entre paSDLSoundEffect e paSDLAudio, bastando apenas colocar as coisas no lugar certo.

Diferente das músicas como todo mundo sabe, sfx podem tocar ao mesmo tempo. Então não foi necessário remover do escopo da paSDLSoundEffect métodos de reprodução da música. Em geral deu tudo rapidamente certo.

As maiores dificuldades foram a alocação de canais, uma vez que tive que fazer uns testes para estabelecer o melhor padrão para o usuário inserir o número de canais desejados para a aplicação; e um método que pausasse todas as músicas e voltasse a reproduzir apenas as que estavam tocando no momento do pause. Além da própria implementação, ainda tive que considerar problemas com relação ao estado do pauseAll. Por exemplo, se todos os sfx estiverem parado, nao faz sentido aplicar pauseAll. E se todas as músicas estiverem reproduzindo novamente, não faz sentido aplicar o resumo para cada uma delas, sendo necessario novamente pausar as musicas ao inves de voltar a reproduzí-las.

Outra grande dificuldade foi estabelecer um padrão entre pauseAll e pauses de escopo. Testando as melhores maneiras, cheguei ao seguinte algoritmo:

1- Musicas pausadas com pauseAll e reiniciadas ou despausadas com os métodos de escopo para tais funcionalidades não são mais gerenciadas pelo pauseAll

2- Se o usuário chamar o método pauseAll e depois mandar tocar mais sfx sem reaplicar o pauseAll para retomar os sfx com pauseAll, somente os sfx pausados com esse metodo voltarão a tocar, sendo os demais sons não atingidos por ele.


É aquela velha história. Uma engine deve ser flexível, mas cobrir todas as burradas do usuário é impossível. Se eu fosse levar em conta novas músicas reproduzidas ou músicas despausadas independente do pauseAll, acabaria desvirtuando o motivo real da criação desse método.


Juro que o próximo post será o último sobre audio! Ainda preciso verificar algumas coisas nas classes antes de fechar uma nova versão.

Até la!

paSDLMusicPlayer

Olá!


Lembrando dos assuntos referentes ao último post, a parte de som da engine estava praticamente concluída, exceto por alguns problemas de encapsulamento envolvendo funções friend e variáveis estáticas.


Este problema se agravou quando fui implementar as ultimas funcionalidades, as quais envolviam dar stop em todos os sons, pausar todos os sons ou retomá-lo a partir do ponto de onde pararam. O grande problema envolvido nessas funcionalidades estava na ausência de um mecanismo ágil de conversação entre as classes. além da perigosa declaração das mesmas como friend. Analisando a situação, percebi que era inviável continuar e resolvi aumentar a complexidade das classes em virtude da iminente necessidade de um gerenciador decente!


Como diria Carlo Ginzburg em "O Queijo e os Vermes": VOLTAMOS À ESTACA ZERO!


Buscando maneiras de melhorar a conversa entre uma possível classe gerenciadora dos atributos de todas as músicas, me decidi pela velha companheira herança que nunca cessa em ajudar os desesperados por uma relação de hierarquia melhor que a dos velhos e tediosos ponteiros usados em C, através de uma dica da Keli para o meu problema.


O grande diferencial seria que, mesmo possuindo uma alta gama de variáveis estáticas controladoras, eu ainda conseguisse manter um encapsulamento decente e funcionalidades relacionadas à manipulação de músicas dentro do seu devido escopo. Dessa forma a classe pai foi nomeada para paSDLMusicPlayer.

Tendo um gerenciador encapsulado para os atributos das musicas do game, a maioria dos meus problemas com variáveis estáticas e complexidade excessiva se resolveu, exceto pela perda de tempo ocasionada pelo esquecimento da declaração do destrutor da classe pai como virtual (hehehehe...).

Com um escopo mais protegido, fiquei livre para aumentar as funcionalidades. Agora é possível receber da paSDLMusic retornos contendo o ID da música, qual é a música atual que está tocando, se a música X está ou não reproduzindo e aumentar o volume de todas as músicas ou de uma específica.

Em resumo, com paSDLMusicPlayer, a reprodução de músicas ficou extremamente poderosa na engine, possibilitando diversas abordagens facilitadas para tratamento dos queridos sons que acompanham o fundo dos nossos jogos.

Essa nova classe me possibitou também tornar toda a paSDLMusic independente da paSDLAudio, sendo esta responsável apenas por inicializar a biblioteca SDL_Mixer e reservar as constantes de audio como o volume máximo permitido.

Ainda tenho que adaptar o desenvolvimento para a paSDLSoundEffect. Se eu conseguir tal façanha, sem novamente encontrar outro grande erro que me faça reiniciar a construção das classes, a parte de som estará concluída!