DISPOSITIVOS MÓVEIS II Etep Desenvolvendo Jogos 2D-Android Prof. Rogério B. de Andrade Coordenador do Curso de Programação em Jogos Digitais
Desenvolvimento de Jogos Utilizando Android Inicialmente o primeiro item é saber adicionar imagens ao jogo. Para isto para arrastar as imagens para uma pasta específica do projeto Android: No exemplo acima foram arrastadas as imagens png para a pasta drawabel-hdpi. Esta pasta esta destinada as imagens de alta resolução (high). Também podem ser adicionadas imagens com resoluções menores (Drawable-ldpi (low)), média resolução (Drawable-mdpi) e assim por diante. O segundo passo é definir variáveis que sejam compatíveis com as imagens que foram adicionadas. Na pasta src selecione o arquivo MainActivity.java (arquivo principal do projeto). E neste arquivo que devemos inserir os códigos do jogo. Observe que temos a classe MainActivity sendo complementada (extends) pela classe Interna Activity do Android. Toda classe de projeto deve ter esta classe como referência é esta classe que permite dar vida a aplicação, todas as definições básicas de uma aplicação são herdadas desta classe. No código foram criados objetos (personagem, cenário, vilão e objeto, todos com herança na Classe Bitmap). A classe Bitmap é responsável por permitir o uso de imagens em jogos desenvolvidas em Java para a plataforma Android.
Apenas isto não basta, é preciso relacionar as imagens que adicionamos as variáveis (objetos) que criamos: O código acima associa o objeto personagem ao arquivo físico aranha.png. O arquivo físico é representado no Android através da Classe R. Esta classe tem uma subclasse drawable que contém os atributos (no caso aranha ) que referenciam o arquivo físico aranha.png. Lembrem-se todo e qualquer recurso visual no Android é armazenado e gerenciado pela classe R (Resources=recursos). Este processo deve ser repetido para toda a imagem que será gerenciada pelo jogo (projeto), como descrito a seguir: Os códigos acima devem ser inseridos no método oncreate, pois, este é o primeiro método que é executado quando uma aplicação Android é iniciada:
Vamos agora começar a programar códigos que irão permitir desenhar as imagens do jogo. Para isto vai ser necessário criar variáveis que servirão para posicionar cada uma das imagens do jogo. As variáveis posx e posy são necessárias para iniciar a posição do personagem no jogo. O personagem deverá iniciar na posição central do cenário, pois, posx é igual ao comprimento do cenário (cenário.getwidth()) dividido por 2. O mesmo ocorre para Y, porém em relação à altura do cenário (cenário.getheight()) divido por 2. Também foram criadas outras variáveis a fim de gerenciar a imagens restantes do jogo: A variável posxvilão e posyvilão servem para gerenciar a posição do vilão. O vilão no caso do jogo é o duende verde. O vilão vai de um lado para outro da tela, descendo até o final do cenário, quando deve subir novamente. A variável direção indica em qual sentido o vilão está atualmente. Quando o vilão atinge o limite em um dos sentidos (esquerda ou direita) volta para o sentido contrário que estava fazendo. Tudo isto que foi descrito deve ocorrer no método Run(), método responsável por executar o jogo. Mas antes vamos ver como desenhar as imagens do jogo:
... O método Run contém um laço de repetição. Este laço é o loop que mantém o jogo em execução. Note que os Comandos iniciados com a palavra canvas são responsáveis por desenhar as imagens do jogo. O canvas possui um método chamado drawbitmap que permite desenhar imagens em determinada posição da tela (x,y). O último parâmetro diz respeito ao contexto (memória) onde será desenhada a imagem. Vamos entender melhor a origem de paint : Paint é um objeto (atributo) declarado e iniciado logo no começo da classe MySurfaceView. Esta classe é complementada pela classe SurfaceView do Android. A classe SurfaceView é responsável por gerenciar os desenhos em um contexto gráfico. Este contexto gráfico é o Paint. Se quisermos desenhar algo, devemos utilizar esta referência. O código abaixo permite deslocar o vilão para direita ou esquerda:
Também é necessário saber se o vilão chegou ao limite de deslocamento, de acordo cm a direção que é tomada ou ainda mudar de direção: Nos jogos em geral, um objeto deve ser mover automaticamente. No caso do jogo desenvolvido temos a abóbora que cai. O objetivo é que o personagem aranha consiga pegar as abóboras antes de tocarem o chão. A variável posxobjeto e posyobjeto fazem o gerenciamento da posição da abóbora. A variável posyobjeto tem seu valor atualizado em dez pixel para baixo. Como este comando está dentro de um laço (While) a abóbora irá cair automaticamente. Também é necessário verificar se a abóbora chegou ao seu limite para então fazê-la voltar em uma nova posição aleatória (Random):
O Limite em Y que a abóbora pode cair é a altura do cenário (cenario.getheight()) menos a altura da própria abóbora (objeto.getheight()). A abóbora é controlada através da variável denominada objeto. O código faz esta verificação e poir meio do método nextint sorteia um novo número que irá servir de posição (x) para abóbora não cair sempre a partir do mesmo lugar. Quando a abóbora ultrapassa o limite em Y, o jogador perde 10 pontos (pontos-=10). Para o usuário ver a quantidade de pontos do jogo é necessário enviar a mensagem, para isto temos o código abaixo: O objeto canvas tem um método denominado drawtext que escreve uma mensagem pontos na posição x,y (10,10) no contexto de memória paint. Foi implementada também a função de colisão que verifica se personagem aranha colidiu com o objeto abóbora. Isto é feito pelo código abaixo: Nesta função passamos como parâmetros: o centro do objeto abóbora, dado pelos dois parâmetros iniciais: Lembre-se a variável posxobejto e posyobjeto são responsáveis por gerenciar a posição da imagem abóbora. No caso acima são passados o centro x e y da abóbora, resultado dos calculos descritos (posxojbeto+comprimento do objeto dividido por 2 e posyobjeto + altura do objeto dividido por 2)
E mais a área do personagem aranha, representado pelos quatro parâmetros restantes: Lembre-se a variável posx e posy são responsáveis por gerenciar a imagem (aranha) que é simbolizado pelo objeto personagem. Os parâmetros descritos são: x inicial, x final e y inicial e y final. Para obter x e y iniciais basta utilizar as variáveis posx e posy respectivamente. Para obter o x final e y final, basta somar a posição x o comprimento do personagem e a posição y a altura do personagem. A função responsável por esta análise esta descrita logo abaixo:
Trata-se da implementação clássica do algortimo que verifica se um ponto (x,y) está dentro de um retângulo (x1,y1,x2,y2). Chamada da função: Por comparação percebe-se que x recebe o parâmetro posxobjeto+objeto.getwidth()/2). Y recebe posyobjeto+ objeto.getheight()/2, x1 recebe posx, x2 recebe posx+personagem.getwidth(), y1 recebe posy, y2 recebe posy+personagem.getheight() respectivamente. Quando a colisão ocorre é necessário sortear uma nova posição para a abóbora, pois a mesma deve aparecer novamente no iníco do cenário, em uma posição x aleatória. Não esquecer de atualizar a variável pontos (pontos+=10) e atualizar o placar do jogo, mostrando o valor da variável pontos (canvas.drawtext( pontos +pontos,10,10,paint); Entendendo o objeto inicio: Este objeto é uma cópia da instância da classe Random. Esta classe é responsável por gerar números aleatórios: Além disto vamos determinar os valores máximos e mínimos que o número a ser sorteado vai poder ter: A variável mim é resultado da obtenção do comprimento do objeto, que no caso é abóbora. A variável max é resultado do comprimento do cenário menos o comprimento do próprio objeto. Este valores servirão de base para gerar uma nova posição para a abóbora. O método nextint retorna um inteiro a partir do valor dado entre (), ou seja,( max min +1)+ min.
Não podemos esquecer que feitas todas as atualizações no surface através do objeto paint é necessário halitarmos o Surface: O movimento do persoangem é realizado através de toques na tela, nos cantos esquerdo ou direito, conforme a direção desejada: O evento de touch é gerenciado pelo código abaixo: A partir deste código podemos obter informações à respeito do evento touch. No código acima, o objeto event passado como parâmetro pelo próprio evento nos permite obter a posição x e y, na qual ocorreu o toque pelo usuário. Antes a variável action armazena a ação realizada pelo evento, que será utilizada mais tarde para identificar se o usuário realizou o toque na tela. O código anterior verifica se o conteúdo da variáel action é igual a constante MotionEvent.ACTION_DOWN que identifica um toque na tela. Caso seja verdadeiro é verificada qual área da tela foi tocada:
A primeira condição analisa se foi a área esquerda e a segunda a direita. Quando selecionada a esquerda, a variável posx é decrementada menos 20 pixels, do contrário (direita) é incrementada 20 pixels. Lembre-se a variável posx e posy definem o posionamento do persoangem (aranha) no jogo. A seguir o código completo que gerencia o evento de touch: Há também os métodos padrões que gerenciam a questão de pausa no jogo, continuação, interrupção etc. Este códigos devem estar declarados e implementados como descrito abaixo:
Para facilitar o desenvolvimento de jogos utilize o exemplo dado como template. Altere-o conforme seu desejo para um novo projeto. Lembre-se ao utilizar um template o erro causado por digitação ou esquecimento de um método padrão diminuem, dando ganho de produtividade. Crie um novo jogo com a utilização do template, mas antes pratique a partir do exemplo adiconando novas imagens, movimentos diversificados, colocando a possibilidade do jogador ganhar bônus etc.