Mostrando postagens com marcador xna. Mostrar todas as postagens
Mostrando postagens com marcador xna. Mostrar todas as postagens

terça-feira, 22 de abril de 2008

O padrão Visitor

Enquanto vou brincando com o código, tentando organizar as classes de uma forma legal e intuitiva, me deparo sempre com dois problemas: aumento da complexidade e reescrita de código.
Da parte do aumento de complexidade, é mais o caso de experiencia mesmo.
A reescrita de código, tenho me deparado com um problema em particular: Eu crio objetos que representem sólidos. Alguns deles ficarão parados na tela, como paredes ou caixas. Outros sofrerão a ação da gravidade, do vento ou qualquer outra situação que altere o comportamento desses objetos.
Como coloquei a dois posts atrás, implementar essa gravida é bem simples, 1 linha no método Update() e está pronto. Para testar,criei uma classe de sólidos que caem e todas as que tivessem esse comportamento, herdariam dela, algo bem simples para começar. Dai começaram os "e se...?". Se para cada tipo de solido que eu quisesse criar, teria que criar uma nova classe e herdar dessa "objeto que cai". Quantas classes eu teria ao criar cada classe para um comportamento? Se eu quisesse que uma caixa caia?
Seria muito interessante se eu pudesse acoplar esse comportamento ao objeto quando eu quisesse. Se eu tenho uma caixa e quero que ela passe a cair, bastaria dar a ela esse comportamento e tudo funcionaria bem. Como não da para fazer herança múltipla, comecei a pesquisar nos padrões do gof por algum que me ajudasse a implementar isso. Por sorte, ele existe!
O padrão Visitor é uma solução para separar o algoritmo da estrutura. Uma das vantagens desse padrão é a habilidade de adicionar novas operações a uma estrutura já existente. Com ele, podemos ter a classe ObjetoSolido e o comportamento de queda em uma classe Gravidade, separada da estrutura do ObjetoSolido. Isso é feito através de uma interface, onde o objeto que vai executar esse método da classe do comportamento, passa uma referencia dela mesmo juto dos parâmetros normais da classe.
No caso desse exemplo, teríamos:

Visitor gravidade = new Gravidade(); //esse é o nosso visitor, responsável pelo comportamento de queda.
Solido solido = new Solido("caixa"); //solido que recebera o comportamento
solido.accept(gravidade); //recebe o comportamento Gravidade


Internamente, o método accept(Visitor visitor) de Solido faz o seguinte:

public void accept(Visitor visitor) {
visitor.visitSolido(this);
}

Ao passar para o Visitor uma referencia de si mesmo, o visitor pode acessar os métodos e atributos públicos dessa classe, que no nosso caso, vai adicionar a aceleração da gravidade ao Solido. Assim como o comportamento de queda foi adicionado, outros também poderiam ser feitos da mesma maneira, como movimentação através do teclado, sons... as possibilidades são infinitas.

Para quem quiser saber mais sobre o Visitor, segue o link (inglês): http://en.wikipedia.org/wiki/Visitor_pattern

segunda-feira, 21 de abril de 2008

Colisão

Queria fazer um post sobre como organizar os objetos dentro do código mas eu ainda estou bem perdido nisso :)
Assim sendo, vou falar um pouco de colisão.
Falando bem por alto, algoritmos de colisão tratam de detectar quando objetos colidem (dããã), ou seja, quando um objeto encosta ou penetra outro objeto.
Para a nossa alegria, o XNA facilita a nossa vida enormemente pois na versão 2.0 passou a disponibilizar métodos para tal. Ele ja faz colisão entre sólidos (cubo, esfera...) e não-sólidos(planos, retas...), entre tipos diferentes como esferas e planos... tudo isso com um só método. Com a chamada objeto.Intersect(objetoAlvo) e pronto.
Até ai ótimo mas tudo isso não serve de nada sem o principal. O mais importante da colisão não é a detecção em si, mas a reação dos objetos que colidem.
Um exemplo para ilustrar e para facilitar, vamos trabalhar em 2D:
Um objeto Bola cai perpendicularmente em direção a um objeto Caixa. Em cada um desses objetos, eu crio um atributo _boudingBox do tipo Rectangle que irá guardar a representação geometria desse objeto. Note que o Rectangle não da para usar no teste de colisão com uma das classes que o XNA disponibiliza para tal mas vai ser suficiente para o exemplo já que seu uso é quase idêntico.
Dai, já assumimos que essa bola está acelerando sob ação da gravidade. Logo, pode-se dizer que o Update() dessa bola é:
public void Update() {
...
this.aceleracao.Y = 10f; //aceleração da gravidade
this.velocidade.Y += this.aceleração.Y; //incrementa a velocidade com a aceleração

this.Y += this.velocidade.Y; //muda a posição da bola de acordo com a velocidade
...
}

Pronto, nossa bola está caindo. Agora vamos testar, no Update de quem controla os objetos, se a bola colide com a caixa:
public void Update() {
...
if (obejtoBola._boudingBox.
Intersect(objetoCaixa._boudingBox))
{
//a bola colide com a caixa
}
...
}

Simples, não? Agora você ja sabe que eles colidem, mas e dai?
Daqui em diante temos que implementar a reação que a bola terá ao colidir com a caixa. Para isso, vamos adicionar algumas linhas no Update() da bola.
public void Update() {
...
this.aceleracao.Y = 10f; //aceleração da gravidade
this.velocidade.Y += this.aceleração.Y; //incrementa a velocidade com a aceleração

if (this.estaColidindo)
{
this.velocidade.Y = -
this.velocidade.Y; //inverte a velocidade vertial, ou seja, joga a bola de volta para cima
}

this.Y += this.velocidade.Y; //muda a posição da bola de acordo com a velocidade
...
}

Pronto. Agora toda vez que a bola bater na caixar ela vai para cima de volta. Assim, reproduzimos o "quique" da bola.

Depois dou uma explicada melhor em colisão. Seguem alguns links para quem quiser saber mais:
http://www.harveycartel.org/metanet/tutorials/tutorialA.html Muito bom, tem vários exemplos e alguns applets mostrando a reação de alguns objetos a colisão
http://www.cs.unc.edu/~geom/collide/ Alguns textos, vídeos e exemplos bem interessantes

terça-feira, 18 de março de 2008

Primeiras experiências

Esse final de semana, uma chuva absurda e eu a pé! Foi a deixa pra começar a estudar o XNA.
Abrindo Visual Studio, criar novo projeto, Xna Windows Game... Abre um dos n textos que peguei na internet e vamos lá!
A primeira parte é entender os métodos da classe principal do jogo, a Game1.
Simplificaram bastante as coisas, uma para carregar conteúdo, outra para carregar grafico, uma para descarregar, um loop de lógica e um loop de impressão. Tudo bem organizado mesmo.
O próprio xna já vem configurado de tal forma que ele mesmo cuida de gerar uma janela, o tipo de coisa que você passa horas fazendo em outras linguagens. Lá basta definir a altura, largura e se é fullscreen, e só! Mais que isso é detalhe. Até ai, ok.
Legal, vamos começar agora... mas por onde?
Provavelmente essa é a parte mais difícil de todas. Por fim, escolhi importar e exibir uma imagem na tela. Depois de algumas horas lendo e pesquisando, consegui e cheguei a conclusão de que é mais idiota que imaginava.
O mais dificil ali é o pontapé inicial, já que não é o tipo de estrutura que está acostumado a ver, principalmente eu que venho de web, onde os programas: começa, executam e terminam em ate 1 ou 2 segundos!
Depois, comecei a me meter a besta lendo as teclas: apertar esc e fechar o jogo, molezinha.
Sendo assim, por que não movimentar o meu desenho com as setinhas do teclado pela tela?
Incrementa o x e o y... Movimento feito!
E se eu aplicasse aceleração no movimento?
Ah, tranqüilo, pega o incremento, multiplica pela aceleração... Aceleração feita!
E nesse ritmo foi: aumento de aceleração, rotação do sprite.
Pronto, ele ja andava, acelerava e parava, e rodava mas ele não fazia uma curva, simplesmente rodava e andava de lado.
Como fazia pra ele andar na diagonal? Já que eu conseguia andar pra cima e pra baixo alterando o Y, esquerda e direita alterando o X, mas diagonal... ai bateu o estalo, momento flashback a aula da tia maricota lá no segundo grau, trigonometria!
Rezando pra São Google por mais uns minutos, tudo clareou: X*cos(angulo) e Y*sin(angulo)!
Perfeito! Num é que funcionava mesmo?!
Fui me empolgando, a chuva não dava trégua e quando vi, já entrava pela madrugada até que a cama começou a exercer uma gravidade e, o que a principio era uma barata (sim, o sprite que eu usava pro teste era uma barata), tornou-se um borrão marrom andando sobre um borrão azul. Bom, era hora de dormir.
Resultado final:

  • Básico de XNA
  • Importação de imagem
  • Leitura de Teclas
  • Movimentação
  • Aceleração
  • Rotação
  • Movimento em diagonal
  • Inércia
  • Desaceleração por atrito
A proxima será debulhar um exemplo que baixei com colisão, plataformas, pulo, gravidade. Ou seja, a base do nosso projeto final.

terça-feira, 19 de fevereiro de 2008

Um pouco do projeto

Pouca coisa está certa ainda. O que foi definido até agora, é:

  • O projeto será um jogo.
  • O framework escolhido é o XNA da Microsoft. Como é um framework feito justamente para o desenvolvimento de jogos, nada mais natural.
  • Seguindo a linha de pensamento, a linguagem para esse caso será o C#. Poderia ser o VB, mas eu ainda não estou usando crack pra isso! :)
  • Ferramenta de desenvolvimento: Visual Studio 2005.
  • O jogo será semelhante ao Grand Chase. Para quem não conhece, esse é um mmog de luta, onde até 4 jogadores se enfrentam em um cenário 2D, com muitas plataformas.
Ainda a decidir:
  • A temática do jogo: desenho, sons, musicas, personagens, história... Essa parte não é tão relevante no momento, já que isso fica na etapa de implementação, ou seja, em Projeto Final II (junho 2008 em diante).
  • Vamos colocar multiplayer em rede? Isso o deadline dirá. Afina, será mais um caso de um caso de uso, mais algumas classes, diagramas de seqüencia, implantação... já viu o tamanho da brincadeira, não?
  • Rodar o projeto no Xbox 360? Se estiver tudo certinho, porque não? Na verdade, a meta é essa. Não sei ao certo se existe alguma dificuldade de passar o jogo de Windows para Xbox360.
Mais para frente, eu explico um pouco mais sobre cada ponto. Principalmente, assim que eu aprender um pouco mais sobre cada um.