terça-feira, 28 de outubro de 2008

Tutorial - Nosso Primeiro Jogo 2D - Parte 3

Neste tutorial veremos, passo a passo, como criar um jogo 2D simples. Este tutorial foi baseado nos videos Begginers Guide 2D encontrados no site creators.xna.com.

Esta é a terceira parte do nosso tutorial de como criar um jogo 2D com o XNA Game Studio. Aqui veremos como criar e desenhar os mísseis que o canhão do nosso navio irá disparar para acertar as aeronaves inimigas. Veremos também o conceito de array, como declarar uma constante e alguns tipos de loop que a linguagem C# nos oferece.

Adicionando e Inicializando Mais Algumas Variáveis

Para a criação dos mísseis que o nosso canhão irá disparar contra as aeronaves inimigas teremos que adicionar novas variáveis a nossa classe GameObject, no arquivo GameObject.cs. Se esse arquivo não estiver aberto, dê um duplo clique nele no Solution Explorer. Uma das variáveis que iremos adicionar é do tipo Vector2 e a chamaremos de velocity, ela tem o objetivo de armazenar a velocidade do deslocamento do míssil disparado. A segunda variável que iremos adicionar será do tipo bool e a chamaremos de alive, sua função é identificar se o missil ainda está "vivo", ou seja, se ele ainda pode ser vusualizado em nossa tela.


Como fizemos com nossas outras variáveis, vamos inicializa-las no construtor da nossa classe GameObject. Logo abaixo da inicialização da nossa variável center, vamos inicializar nossas variáveis velocity e depois a nossa variável alive. Como tanto o missil como o canhão são objetos do tipo GameObject devemos ter o cuidado de inicializar as variáveis com valores "neutros" que não causem nenhum efeito indesejável no jogo e podemos muda-las mais adiante, fora da classe GameObject, pelo objeto a que pertence. Iremos inicializar a nossa variável velocity como um vetor Zero e nossa variável alive com o valor false.


Instanciando e Carregando Nossos Mísseis

Agora poderemos voltar ao nosso arquivo Game1.cs e declarar na classe Game1, uma constante do tipo int e de nome maxCannonMissiles, que indicará o número máximo de mísseis que poderão aparecer na tela ao mesmo tempo, e um array GameObject[] de nome cannonMissiles, que conterá nossos mísseis. Ao declararmos uma constante usamos antes de seu tipo a palavra reservada const que caso por engano tentemos mudar o valor dessa constante durante a codificação do nosso jogo nos proporcionará erros. O tipo GameObject[] indica um array que nada mais é do que um conjunto de elementos do tipo GameObject organizados de forma sequencial e que podem ser acessados por um indice.


Depois disso vamos até o método protected override void LoadContent() e abaixo de onde inicializamos a posição do nosso canhão vamos instanciar nosso array de mísseis. Esse array terá tamanho maxCannonMissiles. Logo abaixo inicializaremos cada missil utilizando um loop para percorrer o array do início ao fim. Para aqueles que não conhecem, o loop for(,,) funciona da seguinte forma. Fornecemos a ele um inteiro que usaremos como contador que geralmente é o i, depois ele compara o contador com uma condição, que no nosso caso o loop vai acontecer enquanto i for menor que o tamanho do nosso array, e em seguida realizamos um incremento ou decremento do contador, no nosso caso o incrementamos fazendo i++. Quando a condição se torna falsa, no nosso caso quando i for maior ou igual ao tamanho do array o loop é quebrado. Dentro do nosso for vamos inicializando cada elemento do array pelo seu indice cannonMissiles[i] sabendo que o i vai variando de 0 até o tamanho do nosso array.


Atualizando Misseis, Tratando Entradas e Disparos

Tendo instanciado e inicializado nosso array e nossos misseis podemos ir ao método protected override void Update(GameTime gameTime) e dentro dele chamaremos o método UpdateCannonMissiles() logo abaixo do trecho de código onde limitamos a rotação do nosso canhão e acima do base.Update(gameTime).


O método UpdateCannonMissiles() ainda não existe e nós iremos implementá-lo. Nele faremos a atualização da posição de nossos mísseis. Então, no final do método protected override void Update(GameTime gameTime), abaixo da chave que indica seu fim, iremos implementar nosso método. Utilizaremos o loop foreach() que percorre todos os elementos do nosso array sem necessitarmos de um contador. A diferença entre ele e o loop for(,,) é que o foreach() incondicionalmente percorre o array do início ao fim e no for(,,) podemos estabelecer uma condição de parada.


Temos que criar também o método que irá disparar nossos mísseis. Para isso necessitamos de mais duas variáveis na classe Game1 e iremos declara-las logo abaixo de onde declaramos nosso array cannonMissiles. Essas variáveis que iremos declarar são do tipo GamePadState e KeyboardState e usaremos elas para guardar o ultimo estado em que o controle do xbox360 ou o teclado se encontravam a cada quadro.


Podemos voltar ao método protected override void Update(GameTime gameTime) e logo abaixo de onde limitamos a rotação do canhão e acima do método UpdateCannonMissiles() vamos checar se o jogador pressionou o botão A do controle do xbox360 ou a barra de espaço do teclado. Para que fique mais interessante, vamos impedir que hajam disparos continuos caso o jogador mantenha pressionado qualquer um desses botões checando se o estado anterior do botão A do controle do xbox360 ou a barra de espaço era "não pressionado". Caso ele pressione qualquer um desses botões de disparo chamaremos a função FireCannonMissile() que realizará o disparo do missil. Devemos também ao final de tudo atualizar o valor das nossas variáveis de estado do controle e do teclado para que funcionem corretamente a cada quadro.


Vamos agora implementar nosso método FireCannonMissile() logo abaixo do fim do método protected override void Update(GameTime gameTime) e acima do método UpdateCannonMissiles(). Ele verifica se os misseis do nosso array ainda estão na tela, caso algum não esteja podemos disparar outo missil. Assim ele define a posição inicial do missil como sendo a posição do canhão, a rotação da imagem do míssil como sendo a mesma rotação da imagem do canhão (por isso fizemos as duas imagens no mesmo sentido), e a velocidade junto a direção que o missil será atirado.


Temos que fazer uma atualização no método UpdateCannonMissiles() para que possamos "matar" os mísseis que estiverem fora da nossa tela. Logo abaixo de onde atualizamos a posição do nosso missil no método UpdateCannonMissiles() vamos checar se o missil ainda está na tela, o que é uma tarefa bem simples por termos o nosso viewportRect.


Desenhando os Mísseis na Tela

Para finalizarmos temos que desenhar os nossos misseis na tela. Assim no método protected override void Draw(GameTime gameTime), para termos os misseis desenhados antes do canhão e dar a impressão que eles estão saindo de dentro do canhão temos também que colocar o código para desenha-los antes do código para desenhar o canhão. Então usaremos um loop para desenhar cada missil do nosso array na tela.


Se não nos esquecemos de nenhum detalhe e não cometemos nenhum erro podemos rodar nosso jogo e já ver nosso canhão atirando os misseis ao pressionarmos a barra de espaço do teclado ou o botão A do controle do xbox360.


Resumo

Nesta terceira parte do nosso tutorial de como criar um jogo 2D com o XNA Game Studio vimos como criar e desenhar os mísseis que o canhão do nosso navio irá disparar para acertar as aeronaves inimigas. Vimos o conceito de array, como declarar uma constante e alguns tipos de loop que a linguagem C# nos oferece.

Na quarta parte do nosso tutorial de como criar um jogo 2D com o XNA Game Studio veremos como criar as aeronaves inimigas para que apareçam de posições randomicas do canto direito da tela.

2 comentários:

'Jr. PachekOo' disse...

Cara...seu blog eh da ora!
Vou começar a estudar o XNA agora, depois que li seu blog fiquei mais animado pra fazer os joguinhos!

podemos linkar nossos blogs?
da uma olhada no meu: www.quediafoi.blogspot.com

Abraço!

Anônimo disse...

Fala brother.

Muito bom seu blog cara... to me inspirando muito nele agora no começo do xna.

Me diga uma coisa, tem como vc fornecer o código fonte? ou mesmo um arquivo txt. Eu to seguindo passo a passo mas tá dando erro aqui no meu aplicativo.

Abraços.

Eduardo