Tutorial Android 02J Criando Jogo Deep Duck Trouble
-
Upload
vagner-carvalho -
Category
Documents
-
view
67 -
download
14
description
Transcript of Tutorial Android 02J Criando Jogo Deep Duck Trouble
-
2
Aviso sobre este Tutorial
Antes de iniciar a leitura deste material, veja esses avisos importantes:
Esse material NO PODER SER DISTRIBUDO, em hiptese alguma, em
outros sites da Internet ou atravs outros processos/meios .
Essa material , em hiptese alguma, NO PODE SER COMERCIALIZADO tanto
pela Internet ou de forma impressa.
Se por acaso voc ver este material sendo distribudo em outro site ou sendo
comercializado (sem ser pelo site oficial da apostila), por favor, entre em contato
com o autor (ver e-mail na primeira pgina).
-
3
Sobre o Autor do Tutorial
Luciano Alves da Silva Bacharelado em Cincia da Computao pela UNISUAM
(Rio de Janeiro RJ) e Ps-Graduado em Docncia do Ensino Superior pelo
Instituto A Vez do Mestre (Universidade Cndido Mendes UCAM, no Rio de
Janeiro). Possui conhecimento e domnio das linguagens de programao Pascal,
Java, C/C++, C#, Visual Basic, Delphi, PHP e HTML. J criou Ambientes de
Desenvolvimento Integrado (conhecidos como IDE) como o MakeWare (que
trabalha com as linguagens Pascal, C++ e Java) e o AlgoWare (interpretador de
algoritmos).
autor tambm dos seguintes livros, pela editora AGBOOK
Aprenda Passo a Passo a Programar em Android Guia Essencial para Desenvolvedores
Desenvolvendo Jogos com a Plataforma XNA Guia para Desenvolvedores.
Desenvolvendo Jogos com a Ferramenta RPG Maker VX Guia do Usurio.
-
4
Apresentao
Este material mostra passo a passo a construo de um jogo baseado no Deep
Duck Trouble Donald Duck (do console Master System) para a plataforma
Android.
Caso voc, que esteja lendo este tutorial, seja iniciante em programao com
jogos para Android, recomendo antes adquirir a Apostila de Android :
Desenvolvimento de Jogos 2 Edio (que pode ser encontrada em meu site
www.apostilaandroid.net), para melhor compreenso e entendimento dos
comandos e instrues utilizadas para o desenvolvimento do jogo.
-
5
Tutorial Criando um jogo baseado no Deep Duck Trouble
este tutorial iremos aprender passo a passo a construir um jogo baseado
no famoso Deep Duck Trouble Donald Duck. Se voc ainda no leu a
minha Apostila de Android : Desenvolvimento de Jogos (2 Edio),
recomendo adquirir o material citado para melhor compreenso do
desenvolvimento.
Sobre o jogo Deep Duck Trouble Donald Duck
O jogo do Deep Duck Trouble nada mais do que a continuao do jogo The
Luck Dime Capper (tambm estrelado por Pato Donald). A histria a seguinte:
Tio Patinhas em uma de suas viagens em uma ilha misteriosa, sofre uma
maldio, que o transforma em um balo gigante. Ele recorre ao Pato Donald
para que ele possa ajuda-lo a retirar esse feitio. Para isso, Pato Donald dever
passar por vrios desafios nessa ilha misteriosa, para retirar o feitio que est
sobre o tio Patinhas. Veja a imagem do jogo abaixo:
Jogo do Deep Duck Trouble
N
-
6
Construindo o jogo passo a passo
O nosso jogo que iremos construir, ter somente uma nica fase com desafio. O
jogo ir se passar na fase da floresta (Savana), e o desafio ser uma guia (que
o desafio da fase do vale (Valley)) que o Pato Donald ter que enfrentar.
Em nossa verso (diferente do jogo original, onde o Pato Donald tinha que
somente se desviar dos ataques dos desafios de cada fase), nosso personagem
ir enfrentar o desafio, chutando as pedras (que esto presentes na fase) sobre o
inimigo.
A partir de agora iremos construir passo a passo, o nosso prprio Deep Duck
Trouble.
A primeira coisa que precisamos fazer importar a nossa framework GameUtil2D
(neste caso, o arquivo GameUtil2DV1_1.zip, que voc poder baixar pelo
seguinte link : http://bit.ly/1pgpwzz) para dentro do Android Developer Tools
(qualquer dvida, consulte a Apostila de Android : Desenvolvimento de Jogos 2
Edio).
Depois de importar o framework para o ADT, vamos realizar algumas tarefas
dentro dele.
Primeiramente, vamos renomear o nosso projeto (simplesmente selecionando-o
dentro do ADT, na seo Package Explorer, e em seguida pressionando a tecla
F2). Iremos chamar nosso projeto de Deep Duck Trouble, conforme podemos
conferir abaixo:
Renomeando o projeto
-
7
Clique em OK para confirmarmos a operao acima.
Aps renomearmos o projeto, vamos abrir o arquivo strings.xml (presente dentro
do diretrio values, situado dentro da pasta res do nosso projeto). Feito isso,
vamos atribuir um novo valor a constante app_name, que ser o nome do nosso
jogo : Deep Duck Trouble (Android). Veja o resultado na figura seguinte:
Renomeando a constante app_name
Depois de atribuir o valor a constante, salve o arquivo para que as alteraes
tenham efeito.
Agora vamos clicar com o boto direito sobre o nosso projeto criado e em seguida
vamos selecionar a opo Android Tools / Rename Application Package. Feito
isso ser aberta a seguinte caixa de dilogo :
Caixa de dilogo Rename Application Package
-
8
Vamos atribuir um novo nome para o pacote , que vai se chamar
gameutil2d.deepducktrouble. Feito isso clique em OK, que surgir a seguinte
caixa de dilogo:
Caixa de dilogo Refactoring
Clique em Finish para concluirmos o processo de renomeao do pacote.
Possivelmente em seguida dever ser mostrada a seguite mensagem :
-
9
Mensagem de confirmao
Basta clicar em Yes para confirmar.
Agora vamos obter as imagens e arquivos de sons de efeito que utilizaremos
dentro do nosso jogo, que voc pode baixar pelo seguinte link : bit.ly/1nZD2lz
Copiando as imagens e os arquivos de sons de efeito
Agora vamos copiar todas as imagens png que baixamos do link acima para
dentro da pasta drawable-mdpi.
Em seguida, vamos criar uma pasta dentro do diretrio res do nosso projeto
chamada raw , que ir guardar todos os sons de efeito e msicas do nosso jogo.
Aps criar a pasta copie todos os arquivos wav e mp3 para dentro desse
diretrio que acabamos de criar.
Definindo o cone da nossa aplicao
Agora vamos abrir o arquivo AndroidManifest.xml (que se encontra dentro da
pasta principal do projeto) para alterarmos o cone do nosso jogo.
Aps abrir o arquivo AndroidManifest.xml, selecione a guia Application para
definirmos cone do nosso jogo (no campo Icon). Vamos escolher a imagem
icone_jogo_deep_duck_trouble. Vejamos o resultado abaixo:
-
10
cone da aplicao alterado
Feito isso, salve as alteraes para que elas tenham efeito.
Desenvolvendo as classes e o cdigo do jogo
O projeto do nosso jogo ter as seguintes classes:
TelaMenu: Essa a tela principal, onde mostrada a tela de abertura do
jogo.
TelaChamadaFase1: Essa a tela de chamada da fase 1, onde ser
mostrado o nome da fase que o nosso personagem ir percorrer (a fase da
floresta : Savana)
TelaFase1 : Essa a tela onde praticamente todo o jogo ir acontecer. Nela
nosso personagem Pato Donald ir enfrentar os inimigos e passar pela fase.
TelaDesafio : Nessa tela o Pato Donald ir enfrentar o nosso desafio (a
guia), desviando dos seus ataques e chutando os blocos de pedra sobre
ele .
TelaGameOver : Tela de Game Over, que mostrada quando nosso
personagem perde todas as suas vidas.
TelasDoJogo: Classe que contm todas as telas que sero exibidas no
nosso jogo.
-
11
Inimigo : Essa uma classe genrica, que ser utilizada para a construo
dos nossos inimigos do jogo.
Canguru : Classe derivada de Inimigo que ir representar um dos inimigos
do Pato, que um canguru que fica andando (pulando) de um lado para o
outro:
Canguru - Inimigo do Pato Donald
EsquiloVoador : Classe derivada de Inimigo que ir representar um dos
inimigos do Pato, que um esquilo voador, que fica em uma rvore e s voa
quando o nosso personagem se aproxima dele:
Esquilo voador - Inimigo do Pato Donald
Aguia : Esse o chefe que nosso personagem Pato Donald ir enfrentar na
tela do desafio. A guia realiza as seguintes aes : Voa de um lado para o
outro, realiza ataques sobre o personagem e joga uma pedra para o Pato
Donald (para que personagem possa chutar sobre ele, durante o seu voo) :
-
12
guia Desafio do Pato Donald
BlocoPedra : Essa classe representa um bloco de pedra onde nosso
personagem pode pisar (como se fosse uma plataforma) ou chutar sobre o
inimigo (ou desafio). Quando o bloco de pedra chutado ele simplesmente
voa e cai (sobe e desce), quebrando quando o mesmo atinge o cho ou
algum inimigo (ou desafio).
Bloco de pedra
BlocoFerro : Essa classe representa um bloco de ferro onde nosso
personagem pode pisar (como se fosse uma plataforma) ou chutar sobre o
inimigo (ou desafio). Quando o bloco de ferro chutado ele simplesmente
desliza , eliminando os inimigos que esto a sua frente.
Bloco de ferro
-
13
Exploso: Classe que representa as exploses que acontecem quando os
blocos de pedras atingem os inimigos, o desafio e o cho. Veja sua sprites
abaixo:
Sprite das exploses
HUDInfo: Classe que possui uma nica finalidade: Guardar o status de vida
do personagem.
Direcao: Esse enumerador ser utilizado para armazenar a direo que o
personagem se encontra (direita ou esquerda).
MusicasSonsEfeito: Classe responsvel por gerenciar todas as msicas e
sons de efeito que ocorrem dentro do jogo.
Bom, vamos iniciar agora a construo das classes do nosso jogo.
Dentro da estrutura de pastas do nosso projeto, vamos localizar o pacote
gameutil2d.project (situado dentro do diretrio src), para em seguida criarmos
uma classe dentro dele, a classe MusicaSonsEfeito.
Depois de criarmos a classe, vamos digitar o seguinte cdigo abaixo dentro dela:
package gameutil2d.project; import gameutil2d.framework.deepducktrouble.R; import android.content.Context; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.SoundPool;
-
14
public class MusicasSonsEfeito { //Array que ir armazenar todas as msicas que sero reproduzidas no jogo //No total, o jogo ter 7 msicas MediaPlayer mp[]; //Objeto que ir gerenciar e executar todos os sons de efeito do nosso //jogo SoundPool sp; //Constantes que iro representar o nome de cada msica, assim como seu //ndice dentro do array MediaPlayer public static final int MUSICA_TELA_INICIAL = 0; public static final int MUSICA_TELA_CHAMADA_FASE_1 = 1; public static final int MUSICA_TELA_FASE_1 = 2; public static final int MUSICA_TELA_DESAFIO_SURGINDO = 3; public static final int MUSICA_TELA_DESAFIO = 4; public static final int MUSICA_TELA_GAME_OVER = 5; public static final int MUSICA_TELA_FASE_1_CONCLUIDA = 6; //Variveis que iro representar o nome de cada som de efeito, assim como //sua ID dentro do objeto SoundPool public static int SOM_DONALD_CHUTANDO; public static int SOM_INIMIGO_MORRENDO; public static int SOM_DONALD_SOFRENDO_DANO; public static int SOM_DONALD_PULANDO; //Construtor da classe, que ir carregaar todas as msicas e sons de //efeito public MusicasSonsEfeito(Context context) { //Carrega todas as msicas mp = new MediaPlayer[7]; mp[MUSICA_TELA_INICIAL] = MediaPlayer.create(context,R.raw.musica_tela_inicial); mp[MUSICA_TELA_CHAMADA_FASE_1] = MediaPlayer.create(context, R.raw.musica_tela_chamada_fase_1); mp[MUSICA_TELA_FASE_1] = MediaPlayer.create(context, R.raw.musica_fase_1); mp[MUSICA_TELA_DESAFIO_SURGINDO] = MediaPlayer.create(context, R.raw.musica_desafio_surgindo); mp[MUSICA_TELA_DESAFIO] = MediaPlayer.create(context, R.raw.musica_desafio); mp[MUSICA_TELA_GAME_OVER] = MediaPlayer.create(context, R.raw.musica_game_over); mp[MUSICA_TELA_FASE_1_CONCLUIDA] = MediaPlayer.create(context, R.raw.musica_fase_concluida); //Carrega todos os sons de efeito
-
15
sp = new SoundPool(4, AudioManager.STREAM_MUSIC, 0); SOM_DONALD_CHUTANDO = sp.load(context, R.raw.som_donald_chutando , 0); SOM_INIMIGO_MORRENDO = sp.load(context, R.raw.som_inimigo_morrendo, 0); SOM_DONALD_SOFRENDO_DANO = sp.load(context, R.raw.som_donald_sofrendo_dano, 0); SOM_DONALD_PULANDO = sp.load(context, R.raw.som_donald_pulando, 0); } //Mtodo que pra todas as msicas em execuo public void PararTodasMusicas() { try { for(MediaPlayer m : mp) { if(m != null) m.stop(); } }catch(Exception e) { } } //Mtodo que pra a execuo uma msica, atravs do seu nome representado //por uma constante) passado como argumento public void PararMusica(int nome_musica) { mp[nome_musica].pause(); } //Mtodo que reproduz uma msica no jogo, atravs do seu nome //(representado por uma constante) passado como argumento public void TocarMusica(int nome_musica) { mp[nome_musica].seekTo(0); mp[nome_musica].start(); } //Mtodo que retorna verdadeiro se uma msica do jogo est em reproduo public boolean EstaTocando(int nome_musica) { return mp[nome_musica].isPlaying(); } //Mtodo que reproduz um som de efeito, atravs do seu nome (representado //por uma varivel) //passado como argumento public void TocarSom(int nome_som) { sp.play(nome_som, 1, 1, 1, 0, 1f); }
-
16
//Esse mtodo ser responsvel por definir se uma msica ir ficar em //loop ou no no jogo atravs do seu nome (que ser representada por uma //constante) public void RepetirMusica(int nome_musica, boolean repetir) { mp[nome_musica].setLooping(repetir); } }
Agora dentro do pacote gameutil2d.project vamos criar uma classe chamada
Explosao , com o seguinte cdigo abaixo:
package gameutil2d.project; import android.content.Context; import gameutil2d.classes.basic.AnimationSprites; import gameutil2d.classes.basic.GameElement; import gameutil2d.framework.deepducktrouble.R; public class Explosao extends AnimationSprites { public Explosao(Context c, GameElement e) { super(c, (e.GetX() + (e.GetWidth() / 2) - (70 / 4)), (e.GetY() + (e.GetHeight() / 2) - (74 / 4)), 70, 74); Add(R.drawable.explosao_1); Add(R.drawable.explosao_2); Add(R.drawable.explosao_3); Add(R.drawable.explosao_4); Add(R.drawable.explosao_5); Start(3, false); SetTag("explosao"); } public Explosao(Context c, int x, int y) { super(c, x,y, 70, 74); Add(R.drawable.explosao_1); Add(R.drawable.explosao_2); Add(R.drawable.explosao_3); Add(R.drawable.explosao_4); Add(R.drawable.explosao_5); Start(3, false); SetTag("explosao"); } }
-
17
Agora vamos criar um enumerador (no uma classe) chamado Direcao dentro do
pacote gameutil2d.project. Para criarmos um enumerador bem simples, basta
clicar com o boto direito sobre o pacote gameutil2d.project e em seguida
selecione New/Enum. Veja na figura abaixo:
Criando um enumerador
Feito isso ser aberta a seguinte caixa de dilogo em seguida:
-
18
Caixa de dilogo New Enum Type
Dentro do campo Name vamos digitar o nome do nosso enumerador, que vai se
chamar Direcao. Depois que digitar o nome do enumerador no campo
informado, clique em Finish para podermos gera-lo.
Depois de gerar o enumerador, digite o seu cdigo conforme mostrado abaixo:
package gameutil2d.project; public enum Direcao { DIREITA , ESQUERDA }
Agora dentro do pacote gameutil2d.project vamos criar uma classe chamada
HUDInfo , com o seguinte cdigo:
package gameutil2d.project; public class HUDInfo { public static int life; }
-
19
Agora dentro do pacote gameutil2d.project vamos criar uma classe chamada
Inimigo , com o seguinte cdigo abaixo:
package gameutil2d.project; import android.content.Context; import android.graphics.Canvas; import gameutil2d.classes.basic.GameElement; import gameutil2d.classes.scene.Scene; public abstract class Inimigo extends GameElement{ public Inimigo(Context context, int x, int y, int w, int h) { SetBounds(x, y, w, h); SetTag("inimigo"); } @Override public void Draw(Canvas canvas) { } public abstract void Update(Scene scene); public abstract void SofrerDano(); public abstract boolean EstaSofrendoDano(); }
Agora dentro do pacote gameutil2d.project vamos criar uma classe chamada
Canguru , com o seguinte cdigo abaixo:
package gameutil2d.project; import gameutil2d.classes.basic.FlipEffect; import gameutil2d.classes.basic.Image; import gameutil2d.classes.scene.Scene; import gameutil2d.framework.deepducktrouble.R; import android.content.Context; import android.graphics.Canvas;
-
20
public class Canguru extends Inimigo { final int IMAGEM_CANGURU_PARADO = 0; final int IMAGEM_CANGURU_PULANDO = 1; final int IMAGEM_CANGURU_SOFRENDO_DANO = 2; Image aCanguru[]; enum Acao { PARADO, PULANDO, SOFRENDO_DANO } Acao acaoInimigo; Direcao direcaoInimigo; int contaFrameAcao; int contaFrameDano; int deslocamento; int contaPulos; boolean podeProcessar; public Canguru(Context context, int x, int y) { super(context, x, y, 75, 85); aCanguru = new Image[3]; aCanguru[IMAGEM_CANGURU_PARADO] = new Image(context, R.drawable.canguru_parado, x, y, 75, 85); aCanguru[IMAGEM_CANGURU_PULANDO] = new Image(context, R.drawable.canguru_pulando, x, y, 75, 85); aCanguru[IMAGEM_CANGURU_SOFRENDO_DANO] = new Image(context, R.drawable.canguru_sofrendo_dano, x, y, 75, 85); acaoInimigo = Acao.PARADO; direcaoInimigo = Direcao.ESQUERDA; contaPulos = 0; podeProcessar = false; } @Override public void Draw(Canvas canvas) { if(acaoInimigo == Acao.PARADO) { if(direcaoInimigo == Direcao.ESQUERDA) aCanguru[IMAGEM_CANGURU_PARADO].Draw(canvas); else aCanguru[IMAGEM_CANGURU_PARADO]. Draw(canvas,FlipEffect.HORIZONTAL); } else if(acaoInimigo == Acao.PULANDO) { if(direcaoInimigo == Direcao.ESQUERDA)
-
21
aCanguru[IMAGEM_CANGURU_PULANDO].Draw(canvas); else aCanguru[IMAGEM_CANGURU_PULANDO]. Draw(canvas,FlipEffect.HORIZONTAL); } else if(acaoInimigo == Acao.SOFRENDO_DANO) { if((contaFrameDano % 2) == 0){ if(direcaoInimigo == Direcao.ESQUERDA) aCanguru[IMAGEM_CANGURU_SOFRENDO_DANO].Draw(canvas); else aCanguru[IMAGEM_CANGURU_SOFRENDO_DANO]. Draw(canvas,FlipEffect.HORIZONTAL); } } } @Override public void Update(Scene scene) { if (podeProcessar) { if (acaoInimigo == Acao.PARADO) { contaFrameAcao++; if (contaFrameAcao == 70) { acaoInimigo = Acao.PULANDO; contaFrameAcao = 0; deslocamento = -10; contaPulos++; } } else if (acaoInimigo == Acao.PULANDO) { MoveByY(deslocamento); deslocamento++; if (direcaoInimigo == Direcao.ESQUERDA) MoveByX(-5); else MoveByX(5); if (deslocamento > 10) { acaoInimigo = Acao.PARADO; if (contaPulos == 4) { contaPulos = 0; if (direcaoInimigo == Direcao.DIREITA) direcaoInimigo = Direcao.ESQUERDA; else direcaoInimigo = Direcao.DIREITA; } } } else {
-
22
deslocamento++; contaFrameDano++; MoveByY(deslocamento); } } else { if(this.GetX()
-
23
package gameutil2d.project; import android.content.Context; import android.graphics.Canvas; import gameutil2d.classes.basic.*; import gameutil2d.classes.character.Character; import gameutil2d.classes.scene.Scene; import gameutil2d.framework.deepducktrouble.R; public class EsquiloVoador extends Inimigo { Image aEsquiloVoador[]; final int IMAGEM_ESQUILO_PARADO = 0; final int IMAGEM_ESQUILO_VOANDO = 1; enum Acao { PARADO, VOANDO, SOFRENDO_DANO } Acao acaoInimigo; boolean esta_voando; int deslocamento; int contaFrameDano; public EsquiloVoador(Context context, int x, int y) { super(context, x, y, 78, 55); aEsquiloVoador = new Image[2]; aEsquiloVoador[IMAGEM_ESQUILO_PARADO] = new Image(context, R.drawable.esquilo_voador_parado, x, y, 78, 55); aEsquiloVoador[IMAGEM_ESQUILO_VOANDO] = new Image(context, R.drawable.esquilo_voador_voando, x, y, 78, 55); acaoInimigo = Acao.PARADO; } @Override public void Update(Scene scene) { if(acaoInimigo == Acao.PARADO) { for(GameElement e : scene.Elements()) { if(e instanceof Character) { if((e.GetX() + 280) >= this.GetX())
-
24
{ esta_voando = true; deslocamento = 15; acaoInimigo = Acao.VOANDO; } } } } else if(acaoInimigo == Acao.VOANDO) { MoveByX(-5); if(deslocamento > -6) deslocamento--; MoveByY(deslocamento); } else if(acaoInimigo == Acao.SOFRENDO_DANO) { deslocamento++; MoveByY(deslocamento); } } @Override public void Draw(Canvas canvas) { if(acaoInimigo == Acao.PARADO) aEsquiloVoador[IMAGEM_ESQUILO_PARADO].Draw(canvas); else if(acaoInimigo == Acao.VOANDO) { aEsquiloVoador[IMAGEM_ESQUILO_VOANDO].Draw(canvas); } else if(acaoInimigo == Acao.SOFRENDO_DANO) { contaFrameDano++; if((contaFrameDano % 2) == 0) aEsquiloVoador[IMAGEM_ESQUILO_VOANDO].Draw(canvas); } } public void Voar() { }
-
25
@Override public void SofrerDano() { acaoInimigo = Acao.SOFRENDO_DANO; deslocamento = -15; } @Override public boolean EstaSofrendoDano() { return acaoInimigo == Acao.SOFRENDO_DANO; } @Override public void MoveByX(int value) { super.MoveByX(value); aEsquiloVoador[0].MoveByX(value); aEsquiloVoador[1].MoveByX(value); } @Override public void MoveByY(int value) { super.MoveByY(value); aEsquiloVoador[0].MoveByY(value); aEsquiloVoador[1].MoveByY(value); } }
Agora dentro do pacote gameutil2d.project vamos criar uma classe chamada
Aguia , com o seguinte cdigo abaixo:
package gameutil2d.project; import android.content.Context; import android.graphics.Canvas; import gameutil2d.classes.basic.*; import gameutil2d.classes.scene.Scene; import gameutil2d.framework.deepducktrouble.R; public class Aguia extends Inimigo{ AnimationSprites aguiaVoando; Image aguia[]; final int IMAGEM_PASSARO_VOANDO_CIMA_DIREITA = 0; final int IMAGEM_PASSARO_VOANDO_CIMA_ESQUERDA = 1;
-
26
final int IMAGEM_PASSARO_VOANDO_BAIXO_DIREITA = 2; final int IMAGEM_PASSARO_VOANDO_BAIXO_ESQUERDA = 3; final int IMAGEM_PASSARO_SOFRENDO_DANO = 4; Direcao direcaoInimigo; enum Acao { VOANDO, ATACANDO, JOGAR_PEDRA } Acao acaoInimigo; enum SentidoAtaque { DIAGONAL_PRA_CIMA, DIAGONAL_PRA_BAIXO } SentidoAtaque sentidoAtaqueInimigo; enum StatusDano { SEM_DANO, SOFREU_DANO } StatusDano statusDanoInimigo; final int TOTAL_DE_VOOS = 3; final int TOTAL_ATAQUES = 3; int conta_voos; int conta_ataques; int contaTempoDano; boolean reiniciaAtaque; int posicao_centro_x; enum MovimentoVoo { DESCER, SUBIR } MovimentoVoo movimentoVooInimigo; MusicasSonsEfeito mse; Context context; Scene scene; boolean esta_morrendo; public Aguia(Context context, MusicasSonsEfeito mse, int x, int y) { super(context, x, y, 182, 229); this.mse = mse; this.context = context; aguia = new Image[5]; aguia[IMAGEM_PASSARO_VOANDO_CIMA_DIREITA] = new Image(context, R.drawable.aguia_voando_cima_direita, x, y, 182, 229); aguia[IMAGEM_PASSARO_VOANDO_CIMA_ESQUERDA] = new Image(context,
-
27
R.drawable.aguia_voando_cima_esquerda, x, y, 182, 229); aguia[IMAGEM_PASSARO_VOANDO_BAIXO_DIREITA] = new Image(context, R.drawable.aguia_voando_baixo_direita, x, y, 182, 229); aguia[IMAGEM_PASSARO_VOANDO_BAIXO_ESQUERDA] = new Image(context, R.drawable.aguia_voando_baixo_esquerda, x, y, 182, 229); aguia[IMAGEM_PASSARO_SOFRENDO_DANO] = new Image(context, R.drawable.aguia_sofrendo_dano, x, y, 182, 229); aguiaVoando = new AnimationSprites(context, x, y, 182, 229); aguiaVoando.Add(R.drawable.aguia_voando_1); aguiaVoando.Add(R.drawable.aguia_voando_2); aguiaVoando.Add(R.drawable.aguia_voando_3); aguiaVoando.Add(R.drawable.aguia_voando_2); aguiaVoando.Start(8, true); acaoInimigo = Acao.VOANDO; direcaoInimigo = Direcao.DIREITA; statusDanoInimigo = StatusDano.SEM_DANO; SetBounds(x, y, 182, 229); SetTag("inimigo"); posicao_centro_x = (400 - 91); conta_voos = 0; reiniciaAtaque = false; esta_morrendo = false; } public void Update(Scene scene) { if(this.scene == null) this.scene = scene; if (statusDanoInimigo == StatusDano.SEM_DANO) { if (acaoInimigo == Acao.VOANDO) { if (direcaoInimigo == Direcao.DIREITA) { MoveByX(5); if (GetX() > 900) { conta_voos++; direcaoInimigo = Direcao.ESQUERDA; SetY(-40); if (conta_voos == TOTAL_DE_VOOS) { conta_voos = 0; reiniciaAtaque = true; acaoInimigo = Acao.ATACANDO; } } } else {
-
28
MoveByX(-5); if (GetX() < (-GetWidth()) - 100) { conta_voos++; direcaoInimigo = Direcao.DIREITA; SetY(-40); if (conta_voos == TOTAL_DE_VOOS) { conta_voos = 0; reiniciaAtaque = true; acaoInimigo = Acao.ATACANDO; } } } } else if (acaoInimigo == Acao.ATACANDO) { if (reiniciaAtaque) { // Define movimento do ataque reiniciaAtaque = false; if (((int) Math.round(Math.random() * 100)) % 2 == 0) direcaoInimigo = Direcao.DIREITA; else direcaoInimigo = Direcao.ESQUERDA; if (((int) Math.round(Math.random() * 100)) % 2 == 0) sentidoAtaqueInimigo = SentidoAtaque.DIAGONAL_PRA_CIMA; else sentidoAtaqueInimigo = SentidoAtaque.DIAGONAL_PRA_BAIXO; if (direcaoInimigo == Direcao.DIREITA) SetX(-182); else SetX(800); if (sentidoAtaqueInimigo == SentidoAtaque.DIAGONAL_PRA_CIMA) SetY(480); else SetY(-229); } else { if (sentidoAtaqueInimigo == SentidoAtaque.DIAGONAL_PRA_CIMA) { MoveByY(-8); if (direcaoInimigo == Direcao.DIREITA) MoveByX(8); else MoveByX(-8); if (GetY() < -GetWidth()) { conta_ataques++;
-
29
if (conta_ataques == TOTAL_ATAQUES) { if (ContaPedras() > 0) { acaoInimigo = Acao.VOANDO; conta_ataques = 0; direcaoInimigo = Direcao.DIREITA; SetY(-40); SetX(-182); } else { acaoInimigo = Acao.JOGAR_PEDRA; SetX(posicao_centro_x); SetY(-229); movimentoVooInimigo = MovimentoVoo.DESCER; } } else reiniciaAtaque = true; } } else { MoveByY(8); if (direcaoInimigo == Direcao.DIREITA) MoveByX(8); else MoveByX(-8); if (GetY() > 480) { conta_ataques++; if (conta_ataques == TOTAL_ATAQUES) { if (ContaPedras() > 0) { acaoInimigo = Acao.VOANDO; conta_ataques = 0; direcaoInimigo = Direcao.DIREITA; SetY(-40); SetX(-182); } else { acaoInimigo = Acao.JOGAR_PEDRA; SetX(posicao_centro_x); SetY(-229);
-
30
movimentoVooInimigo = MovimentoVoo.DESCER; } } else reiniciaAtaque = true; } } } } else if(acaoInimigo == Acao.JOGAR_PEDRA) { if(movimentoVooInimigo == MovimentoVoo.DESCER) { MoveByY(5); if(this.GetY() > 10) { BlocoPedra b = new BlocoPedra(context, mse, 400 - 24, 190, 48, 48); scene.Add(b); b.CairNoChao(); movimentoVooInimigo = MovimentoVoo.SUBIR; } } else { MoveByY(-5); if(this.GetY() < -240) { acaoInimigo = Acao.VOANDO; conta_ataques = 0; direcaoInimigo = Direcao.DIREITA; SetY(-40); SetX(-182); } } } } else { contaTempoDano++; if (!esta_morrendo) { if (contaTempoDano == 100) { contaTempoDano = 0; statusDanoInimigo = StatusDano.SEM_DANO; } } else {
-
31
MoveByY(6); } } } @Override public void Draw(Canvas canvas) { if (statusDanoInimigo == StatusDano.SEM_DANO) { if ((acaoInimigo == Acao.VOANDO) || (acaoInimigo == Acao.JOGAR_PEDRA)) { if (direcaoInimigo == Direcao.DIREITA) aguiaVoando.Draw(canvas); else aguiaVoando.Draw(canvas, FlipEffect.HORIZONTAL); } else if (acaoInimigo == Acao.ATACANDO) { if (direcaoInimigo == Direcao.DIREITA) { if (sentidoAtaqueInimigo == entidoAtaque.DIAGONAL_PRA_CIMA) aguia[IMAGEM_PASSARO_VOANDO_CIMA_DIREITA].Draw(canvas); else aguia[IMAGEM_PASSARO_VOANDO_BAIXO_DIREITA].Draw(canvas); } else { if (sentidoAtaqueInimigo == SentidoAtaque.DIAGONAL_PRA_CIMA) aguia[IMAGEM_PASSARO_VOANDO_CIMA_ESQUERDA].Draw(canvas); else aguia[IMAGEM_PASSARO_VOANDO_BAIXO_ESQUERDA].Draw(canvas); } } } else { if((contaTempoDano % 2) == 0) return; if(direcaoInimigo == Direcao.DIREITA) aguia[IMAGEM_PASSARO_SOFRENDO_DANO].Draw(canvas); else aguia[IMAGEM_PASSARO_SOFRENDO_DANO].Draw(canvas, FlipEffect.HORIZONTAL); } }
-
32
@Override public void MoveByX(int x) { super.MoveByX(x); for(Image a : aguia) a.MoveByX(x); aguiaVoando.MoveByX(x); } @Override public void MoveByY(int y) { super.MoveByY(y); for(Image a : aguia) a.MoveByY(y); aguiaVoando.MoveByY(y); } @Override public void SetY(int value) { super.SetY(value); for(Image a : aguia) a.SetY(value); aguiaVoando.SetY(value); } @Override public void SetX(int value) { super.SetX(value); for(Image a : aguia) a.SetX(value); aguiaVoando.SetX(value); } @Override public void SofrerDano() { statusDanoInimigo = StatusDano.SOFREU_DANO; } @Override public boolean EstaSofrendoDano() { return statusDanoInimigo == StatusDano.SOFREU_DANO; }
-
33
private int ContaPedras() { int c = 0; for(GameElement e : scene.Elements()) { if(e.GetTag() == "bloco_pedra") { c++; } } return c; } public boolean EstaJogandoPedra() { return acaoInimigo == Acao.JOGAR_PEDRA; } public void Morrer() { statusDanoInimigo = StatusDano.SOFREU_DANO; esta_morrendo = true; contaTempoDano = 0; } }
Agora dentro do pacote gameutil2d.project vamos criar uma classe chamada
BlocoPedra , com o seguinte cdigo abaixo:
package gameutil2d.project; import android.content.Context; import android.graphics.Canvas; import gameutil2d.classes.basic.*; import gameutil2d.classes.scene.Scene; import gameutil2d.framework.deepducktrouble.R; public class BlocoPedra extends GameElement { Image bloco_pedra; boolean foi_chutado; Direcao direcaoBloco; Scene scene; int deslocamento;
-
34
boolean foi_quebrado; Explosao explosao; Context context; MusicasSonsEfeito mse; boolean esta_caindo; GameElement elementoAtingido; boolean elemento_foi_atingido; boolean pode_remover_bloco_pedra; int contaFrameTempo; public BlocoPedra(Context context, MusicasSonsEfeito mse, int x, int y, int w, int h) { bloco_pedra = new Image(context, R.drawable.bloco_pedra, x, y, w, h); SetBounds(x, y, w, h); SetTag("bloco_pedra"); foi_chutado = false; foi_quebrado = false; esta_caindo = false; this.context = context; this.mse = mse; elementoAtingido = null; elemento_foi_atingido = false; pode_remover_bloco_pedra = false; contaFrameTempo = 0; } public void Update(Scene scene) { this.scene = scene; if(foi_chutado) { deslocamento++; if (!elemento_foi_atingido) { MoveByY(deslocamento); if (direcaoBloco == Direcao.DIREITA) MoveByX(8); else MoveByX(-8);
-
35
if(GetY() > 500) pode_remover_bloco_pedra = true; } else { contaFrameTempo++; if(contaFrameTempo >= 15) pode_remover_bloco_pedra = true; } GameElement inimigo = Collision.CheckAndReturn(bloco_pedra, scene, "inimigo"); if(inimigo != null) { elementoAtingido = inimigo; if (!elemento_foi_atingido) { explosao = new Explosao(context, bloco_pedra); foi_quebrado = true; elemento_foi_atingido = true; } } else { GameElement chao = Collision.CheckAndReturn(bloco_pedra, scene, "chao"); if(chao != null) { elementoAtingido = chao; if (!elemento_foi_atingido) { explosao = new Explosao(context, bloco_pedra); mse.TocarSom(MusicasSonsEfeito. SOM_INIMIGO_MORRENDO); foi_quebrado = true; elemento_foi_atingido = true; } }
-
36
} } else if(esta_caindo) { deslocamento++; MoveByY(deslocamento); GameElement chao = Collision.CheckAndReturn(bloco_pedra, scene, "chao"); if(chao != null) { SetY(chao.GetY() - this.GetHeight()); esta_caindo = false; } } } @Override public void Draw(Canvas canvas) { if(!foi_quebrado) bloco_pedra.Draw(canvas); else explosao.Draw(canvas); } public void VoarECair(Direcao direcao) { if(!foi_chutado){ direcaoBloco = direcao; foi_chutado = true; deslocamento = -20; } } public void CairNoChao() { deslocamento = 0; esta_caindo = true; } @Override public void MoveByX(int x) { super.MoveByX(x); bloco_pedra.MoveByX(x); } @Override public void MoveByY(int y) { super.MoveByY(y); bloco_pedra.MoveByY(y); }
-
37
@Override public void SetY(int y) { super.SetY(y); bloco_pedra.SetY(y); } public GameElement Acertou() { return elementoAtingido; } public boolean PodeRemoverBloco() { return pode_remover_bloco_pedra; } }
Agora dentro do pacote gameutil2d.project vamos criar uma classe chamada
BlocoFerro , com o seguinte cdigo abaixo:
package gameutil2d.project; import android.content.Context; import android.graphics.Canvas; import gameutil2d.classes.basic.Collision; import gameutil2d.classes.basic.GameElement; import gameutil2d.classes.basic.Image; import gameutil2d.classes.scene.Scene; import gameutil2d.framework.deepducktrouble.R; public class BlocoFerro extends GameElement{ Image bloco_ferro; boolean foi_chutado; Direcao direcaoBloco; Scene scene; Context context; MusicasSonsEfeito mse; GameElement elementoAtingido; public BlocoFerro(Context context, MusicasSonsEfeito mse, int x, int y, int w, int h) { bloco_ferro = new Image(context, R.drawable.bloco_ferro, x, y, w, h); SetBounds(x, y, w, h); SetTag("bloco_ferro"); foi_chutado = false; this.context = context; this.mse = mse; elementoAtingido = null; }
-
38
public void Update(Scene scene) { this.scene = scene; if(foi_chutado) { if(direcaoBloco == Direcao.DIREITA) MoveByX(8); else MoveByX(-8); GameElement inimigo = Collision.CheckAndReturn(bloco_ferro, scene, "inimigo"); if(inimigo != null) { elementoAtingido = inimigo; } } } public void DeslizarBloco(Direcao direcao) { foi_chutado = true; direcaoBloco = direcao; } @Override public void Draw(Canvas canvas) { // TODO Auto-generated method stub bloco_ferro.Draw(canvas); } public boolean FoiChutado() { return foi_chutado; } @Override public void MoveByX(int x) { super.MoveByX(x); bloco_ferro.MoveByX(x); }
-
39
public GameElement Acertou() { return elementoAtingido; } }
Agora dentro do pacote gameutil2d.project vamos criar uma classe chamada
TelasDoJogo, com o seguinte cdigo abaixo:
package gameutil2d.project; public class TelasDoJogo { public enum TelaJogo { TELA_INICIAL, TELA_CHAMADA_FASE_1, TELA_FASE_1, TELA_DESAFIO, TELA_GAME_OVER } public static TelaJogo tela; }
Agora dentro do pacote gameutil2d.project vamos criar uma classe chamada
TelaInicial, com o seguinte cdigo abaixo:
package gameutil2d.project; import gameutil2d.framework.OrientationMode; import gameutil2d.framework.deepducktrouble.R; import gameutil2d.project.TelasDoJogo.TelaJogo; import android.content.Context; import android.graphics.Canvas; import android.view.MotionEvent; import gameutil2d.classes.basic.*; public class TelaInicial { Image tela_inicial; Context context; MusicasSonsEfeito mse; boolean podeTocarMusica; Image titulo_toque_tela_para_iniciar; public TelaInicial(Context context, MusicasSonsEfeito mse) { this.context = context; this.mse = mse; podeTocarMusica = true; }
-
40
public void onScreenLoading(int w, int h, OrientationMode orientation) { tela_inicial = new Image(context, R.drawable.tela_inicial, 0, 0, w, h); titulo_toque_tela_para_iniciar = new Image(context, R.drawable.titulo_toque_tela_para_iniciar, ((w / 2) - (502/2)), 300, 502, 97); } public void Update() { if(podeTocarMusica) { mse.RepetirMusica(MusicasSonsEfeito.MUSICA_TELA_INICIAL, false); mse.TocarMusica(MusicasSonsEfeito.MUSICA_TELA_INICIAL); podeTocarMusica = false; } } public void Draw(Canvas canvas) { tela_inicial.Draw(canvas); titulo_toque_tela_para_iniciar.Draw(canvas); } public void onTouch(MotionEvent e) { if(e.getAction() == MotionEvent.ACTION_DOWN) { podeTocarMusica = true; mse.PararMusica(MusicasSonsEfeito.MUSICA_TELA_INICIAL); HUDInfo.life = 5; TelasDoJogo.tela = TelaJogo.TELA_CHAMADA_FASE_1; } } }
Na figura abaixo, temos uma prvia de como ser a nossa tela inicial:
-
41
Prvia da execuo da Tela Inicial
Agora dentro do pacote gameutil2d.project vamos criar uma classe chamada
TelaChamadaFase1, com o seguinte cdigo abaixo:
package gameutil2d.project; import gameutil2d.framework.OrientationMode; import gameutil2d.framework.deepducktrouble.R; import gameutil2d.project.TelasDoJogo.TelaJogo; import android.content.Context; import android.graphics.Canvas; import android.view.MotionEvent; import gameutil2d.classes.basic.*; public class TelaChamadaFase1 { Image titulo_scene_1; Image titulo_savana; Image titulo_toque_tela_para_iniciar; Context context; MusicasSonsEfeito mse; long startTime;
-
42
long endTime; boolean gravaStartTime; boolean podeTocarMusica; public TelaChamadaFase1(Context context,MusicasSonsEfeito mse) { this.context = context; this.mse = mse; gravaStartTime = true; podeTocarMusica = true; } public void onScreenLoading(int w, int h, OrientationMode orientation) { titulo_scene_1 = new Image(context, R.drawable.titulo_scene_1, (w / 2) - (189 / 2), 20, 189 , 65); titulo_savana = new Image(context, R.drawable.titulo_savana, (w / 2) - (194 / 2), 95, 194 , 61); titulo_toque_tela_para_iniciar = new Image(context, R.drawable.titulo_toque_tela_para_iniciar, ((w / 2) - (502/2)), 300, 502, 76); } public void Update() { if(podeTocarMusica) { mse.RepetirMusica(MusicasSonsEfeito. MUSICA_TELA_CHAMADA_FASE_1, false); mse.TocarMusica(MusicasSonsEfeito. MUSICA_TELA_CHAMADA_FASE_1); podeTocarMusica = false; } if(gravaStartTime) { startTime = System.currentTimeMillis(); gravaStartTime = false; } endTime = System.currentTimeMillis(); } public void Draw(Canvas canvas) { titulo_scene_1.Draw(canvas); titulo_savana.Draw(canvas);
-
43
if((endTime - startTime) > 4000) { titulo_toque_tela_para_iniciar.Draw(canvas); } } public void onTouch(MotionEvent e) { if(e.getAction() == MotionEvent.ACTION_DOWN) { if((endTime - startTime) > 4000) { mse.PararMusica(MusicasSonsEfeito. MUSICA_TELA_CHAMADA_FASE_1); podeTocarMusica = true; gravaStartTime = true; TelasDoJogo.tela = TelaJogo.TELA_FASE_1; } } } }
Na figura seguinte, temos uma prvia de como seria a tela de chamada da fase 1:
Prvia da execuo da Tela de Chamada da Fase 1
-
44
Agora dentro do pacote gameutil2d.project vamos criar uma classe chamada
TelaFase1, com o seguinte cdigo abaixo:
package gameutil2d.project; import gameutil2d.framework.OrientationMode; import gameutil2d.framework.deepducktrouble.R; import gameutil2d.project.TelasDoJogo.TelaJogo; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.view.MotionEvent; import gameutil2d.classes.scene.*; import gameutil2d.classes.basic.*; import gameutil2d.classes.character.Character; import gameutil2d.classes.text.*; public class TelaFase1 { Scene scene; Image fundo_tela_1; Image fundo_tela_2; Image grupo_nuvem_1; Image grupo_nuvem_2; Context context; Character pato_donald; Image seta_esquerda; Image seta_cima; Image seta_direita; Image botao_chutar; Image foto_pato_donald; enum Acao { PARADO, ANDANDO } Acao acaoPersonagem = Acao.PARADO; Direcao direcaoPersonagem = Direcao.DIREITA; final int MAX_PASSOS = 800; int contaPasso ; int posicao_centro_x; int largura_tela; int altura_tela;
-
45
MusicasSonsEfeito mse; boolean podeTocarMusica; boolean podeControlar; boolean surgirInimigo; AnimationSprites aguia; TextDrawable texto; long startTime, endTime; boolean gravaStartTime; public TelaFase1(Context context, MusicasSonsEfeito mse) { this.context = context; this.mse = mse; scene = new Scene(); podeTocarMusica = true; podeControlar = true; surgirInimigo = false; texto = new TextDrawable(context, FontName.PC_SENIOR); texto.SetColor(Color.BLACK); texto.SetSize(30); gravaStartTime = true; } public void onScreenLoading(int w, int h, OrientationMode orientation) { fundo_tela_1 = new Image(context, R.drawable.fundo_tela, 0, 0, w, h); fundo_tela_2 = new Image(context, R.drawable.fundo_tela, w, 0, w, h); grupo_nuvem_1 = new Image(context, R.drawable.grupo_nuvens_1, 0, 0, w, 55); grupo_nuvem_2 = new Image(context, R.drawable.grupo_nuvens_2, w, 0, w, 55); foto_pato_donald = new Image(context, R.drawable.foto_pato_donald, 30, 30, 49, 48); aguia = new AnimationSprites(context, -182, 70, 182, 229); aguia.Add(R.drawable.aguia_voando_1); aguia.Add(R.drawable.aguia_voando_2); aguia.Add(R.drawable.aguia_voando_3); aguia.Add(R.drawable.aguia_voando_2); aguia.Start(5, true); scene.Add(fundo_tela_1);
-
46
scene.Add(fundo_tela_2); scene.Add(grupo_nuvem_1); scene.Add(grupo_nuvem_2); posicao_centro_x = (w / 2) - (92 / 2); pato_donald = new Character(context, (w / 2) - (92 / 2), 0, 92, 135); for(int x = 0; x < 30; x++) pato_donald.AddNewSpriteIdle("parado", R.drawable.pato_donald_parado); for(int x = 0; x < 4; x++) { pato_donald.AddNewSpriteIdle("parado", R.drawable.pato_donald_esperando_1); pato_donald.AddNewSpriteIdle("parado", R.drawable.pato_donald_esperando_1 + 1); } for(int x = 0; x < 4; x++) { pato_donald.AddNewSpriteIdle("parado", R.drawable.pato_donald_esperando_3); pato_donald.AddNewSpriteIdle("parado", R.drawable.pato_donald_esperando_3 + 1); } for(int x = 0; x < 4; x++) { pato_donald.AddNewSpriteIdle("parado", R.drawable.pato_donald_esperando_1); pato_donald.AddNewSpriteIdle("parado", R.drawable.pato_donald_esperando_1 + 1); } for(int x = 0; x < 4; x++) { pato_donald.AddNewSpriteIdle("parado", R.drawable.pato_donald_esperando_5); pato_donald.AddNewSpriteIdle("parado", R.drawable.pato_donald_esperando_5 + 1); } for(int x = 0; x
-
47
pato_donald.AddNewSpriteJumping("pulando", R.drawable.pato_donald_pulando_1); pato_donald.AddNewSpriteJumping("pulando", R.drawable.pato_donald_pulando_2); pato_donald.AddNewSpriteJumping("pulando", R.drawable.pato_donald_pulando_3); for (int x = 1; x
-
48
if ((contaPasso >= 0) && (contaPasso = 0) && (contaPasso 750) { podeControlar = false; } } } else { contaPasso--; if ((contaPasso >= 0) && (contaPasso = 0) && (contaPasso
-
49
else { pato_donald.MoveByX(-7); if (pato_donald.CollisionBySide(scene)) { pato_donald.MoveByX(7); contaPasso++; } if (pato_donald.GetX() < 0) { pato_donald.MoveByX(7); contaPasso++; } } } } //Verifica se o pato donald sofreu algum dano for(GameElement e : scene.Elements()) { if((e.GetTag() == "espinhos") || (e.GetTag() == "inimigo")) { if (Collision.Check(e, pato_donald)) { if (!pato_donald.IsDamaged()) { pato_donald.SufferDamage("sofrendo_dano", 5); mse.TocarSom(MusicasSonsEfeito. SOM_DONALD_SOFRENDO_DANO); HUDInfo.life--; if(HUDInfo.life == 0) { mse.PararMusica(MusicasSonsEfeito. MUSICA_TELA_FASE_1); pato_donald.Idle("parado", 8, true); acaoPersonagem = Acao.PARADO; podeControlar = true; podeTocarMusica = true; TelasDoJogo.tela = TelaJogo.TELA_GAME_OVER; surgirInimigo = false; gravaStartTime = true; CriarTela(); } } } } } if(pato_donald.IsAttacking()) { for(GameElement e : scene.Elements())
-
50
{ if(e.GetTag() == "bloco_pedra") { if(PersonagemEstaAoLado(pato_donald, e)) { ((BlocoPedra) e).VoarECair(direcaoPersonagem); } } else if(e.GetTag() == "bloco_ferro") { if(PersonagemEstaAoLado(pato_donald, e)) { ((BlocoFerro) e).DeslizarBloco(direcaoPersonagem); } } } } if(!podeControlar) { if(pato_donald.GetX() > largura_tela) { if (!surgirInimigo) { mse.PararMusica(MusicasSonsEfeito. MUSICA_TELA_FASE_1); mse.RepetirMusica(MusicasSonsEfeito. MUSICA_TELA_DESAFIO_SURGINDO,false); mse.TocarMusica(MusicasSonsEfeito. MUSICA_TELA_DESAFIO_SURGINDO); surgirInimigo = true; } } } if(surgirInimigo) { if(gravaStartTime) { startTime = System.currentTimeMillis(); gravaStartTime = false; } endTime = System.currentTimeMillis(); aguia.MoveByX(8); if((aguia.GetX() > largura_tela + 200) && ((endTime - startTime) > 4000)) {
-
51
pato_donald.Idle("parado", 8, true); acaoPersonagem = Acao.PARADO; podeControlar = true; podeTocarMusica = true; TelasDoJogo.tela = TelaJogo.TELA_DESAFIO; surgirInimigo = false; gravaStartTime = true; CriarTela(); } } UpdateInimigos(); UpdatePedras(); pato_donald.Update(scene); } public void Draw(Canvas canvas) { scene.Draw(canvas); seta_cima.Draw(canvas); seta_direita.Draw(canvas); seta_esquerda.Draw(canvas); botao_chutar.Draw(canvas); foto_pato_donald.Draw(canvas); texto.SetXY(90,65); texto.DrawString(canvas, "=" + HUDInfo.life); } public void onTouch(MotionEvent e) { if(e.getAction() == MotionEvent.ACTION_DOWN) { if(seta_esquerda.IsTouch(e.getX(), e.getY())) { if (podeControlar) { acaoPersonagem = Acao.ANDANDO; direcaoPersonagem = Direcao.ESQUERDA; } } else if(seta_direita.IsTouch(e.getX(), e.getY())) { if (podeControlar) { acaoPersonagem = Acao.ANDANDO; direcaoPersonagem = Direcao.DIREITA; } } else if(seta_cima.IsTouch(e.getX(), e.getY())) { if (podeControlar) { mse.TocarSom(MusicasSonsEfeito. SOM_DONALD_PULANDO); pato_donald.Jump("pulando", 5, false);
-
52
} } else if(botao_chutar.IsTouch(e.getX(), e.getY())) { if (podeControlar) { mse.TocarSom(MusicasSonsEfeito.SOM_DONALD_CHUTANDO); pato_donald.Attack("chutar_pedra", 5); } } } else { if (podeControlar) { acaoPersonagem = Acao.PARADO; if (pato_donald.IsGround()) { if (!pato_donald.IsAttacking()) { pato_donald.Idle("parado", 8, true); } } } } } public void MoverCenario(int value) { fundo_tela_1.MoveByX(value); fundo_tela_2.MoveByX(value); grupo_nuvem_1.MoveByX(value); grupo_nuvem_2.MoveByX(value); if(value < 0) { if(fundo_tela_1.GetX() < - fundo_tela_1.GetWidth()) fundo_tela_1.SetX(fundo_tela_2.GetX() + fundo_tela_2.GetWidth()); if(fundo_tela_2.GetX() < - fundo_tela_2.GetWidth()) fundo_tela_2.SetX(fundo_tela_1.GetX() + fundo_tela_1.GetWidth()); if(grupo_nuvem_1.GetX() < - grupo_nuvem_1.GetWidth()) grupo_nuvem_1.SetX(grupo_nuvem_2.GetX() + grupo_nuvem_2.GetWidth()); if(grupo_nuvem_2.GetX() < - grupo_nuvem_2.GetWidth()) grupo_nuvem_2.SetX(grupo_nuvem_1.GetX() + grupo_nuvem_1.GetWidth()); }
-
53
if(value > 0) { if(fundo_tela_1.GetX() > fundo_tela_1.GetWidth()) fundo_tela_1.SetX(fundo_tela_2.GetX() fundo_tela_2.GetWidth()); if(fundo_tela_2.GetX() > fundo_tela_2.GetWidth()) fundo_tela_2.SetX(fundo_tela_1.GetX() fundo_tela_1.GetWidth()); if(grupo_nuvem_1.GetX() > grupo_nuvem_1.GetWidth()) grupo_nuvem_1.SetX(grupo_nuvem_2.GetX() grupo_nuvem_2.GetWidth()); if(grupo_nuvem_2.GetX() > grupo_nuvem_2.GetWidth()) grupo_nuvem_2.SetX(grupo_nuvem_1.GetX() grupo_nuvem_1.GetWidth()); } for(GameElement e : scene.Elements()) { if((e.GetTag() == "arvore") || (e.GetTag() == "ponto_colisao") || (e.GetTag() == "espinhos") || (e.GetTag() == "inimigo") || (e.GetTag() == "bloco_pedra") || (e.GetTag() == "bloco_ferro") || (e.GetTag() == "nuvem")) { e.MoveByX(value); } } } public void CriarTela() { scene = new Scene(); contaPasso = 0; fundo_tela_1.SetX(0); fundo_tela_2.SetX(largura_tela); scene.Add(fundo_tela_1); scene.Add(fundo_tela_2); grupo_nuvem_1.SetX(0); grupo_nuvem_2.SetX(largura_tela); scene.Add(grupo_nuvem_1); scene.Add(grupo_nuvem_2); scene.Add(new Box(0, altura_tela - 121, largura_tela, 121,"chao"));
-
54
scene.Add(new Image(context, R.drawable.nuvem, 600, 100, 333, 96, "nuvem")); scene.Add(new Image(context, R.drawable.nuvem, 1200, 100, 333, 96, "nuvem")); scene.Add(new Image(context, R.drawable.nuvem, 1800, 100, 333, 96, "nuvem")); scene.Add(new Image (context,R.drawable.arvore_com_folhas, 1500,altura_tela - 121 - 385,384,385,"arvore")); scene.Add(new Box(1500 + 226, altura_tela - 121 - 385 + 241,156,50,"ponto_colisao")); scene.Add(new EsquiloVoador(context, 1500 + 240 , altura_tela - 121 385 + 191)); scene.Add(new Canguru(context, 1100, altura_tela - 121 - 85)); scene.Add(new BlocoFerro(context, mse, 800, altura_tela - 121 - 48, 48, 48)); scene.Add(new BlocoPedra(context, mse, 1480, altura_tela - 121 - 48, 48, 48)); scene.Add(new Image (context,R.drawable.arvore_sem_folhas_inverso, 2300,altura_tela - 121 - 385,249,385,"arvore")); scene.Add(new Box(2305, altura_tela - 121 - 385 + 238,140,29,"ponto_colisao")); scene.Add(new Image (context,R.drawable.arvore_com_folhas, 3100,altura_tela - 121 - 385,384,385,"arvore")); scene.Add(new Box(3100 + 226, altura_tela - 121 - 385 + 241,156,50,"ponto_colisao")); scene.Add(new Image(context, R.drawable.espinho, 3100 + 400, altura_tela - 121 - 45, 144, 45, "espinhos")); scene.Add(new Image (context,R.drawable.arvore_sem_folhas_inverso, 3670,altura_tela - 121 - 385,249,385,"arvore")); scene.Add(new Box(3675, altura_tela - 121 - 385 + 238,140,29,"ponto_colisao")); scene.Add(new BlocoFerro(context, mse, 4000, altura_tela - 121 - 48, 48, 48)); scene.Add(new Canguru(context, 4300, altura_tela - 121 - 85)); pato_donald.SetX(posicao_centro_x); pato_donald.SetY(0); scene.Add(pato_donald); aguia.SetX(-182); aguia.SetY(0);
-
55
scene.Add(aguia); } public void UpdateInimigos() { for(GameElement e : scene.Elements()) { if(e instanceof Inimigo) ((Inimigo) e).Update(scene); } } public void UpdatePedras() { for(GameElement e : scene.Elements()) { if(e instanceof BlocoPedra) { ((BlocoPedra) e).Update(scene); GameElement elementoAtingido = ((BlocoPedra) e).Acertou(); if (elementoAtingido != null) { if (elementoAtingido instanceof Inimigo) { if (!((Inimigo) elementoAtingido).EstaSofrendoDano()) { ((Inimigo) elementoAtingido).SofrerDano(); mse.TocarSom(MusicasSonsEfeito. SOM_INIMIGO_MORRENDO); } } } if(((BlocoPedra) e).PodeRemoverBloco()) { scene.Remove(e); break; } } else if(e instanceof BlocoFerro) { ((BlocoFerro) e).Update(scene); if (((BlocoFerro) e).FoiChutado()) {
-
56
if (((e.GetX() > largura_tela)) || (e.GetX() < - 48)) { scene.Remove(e); break; } GameElement elementoAtingido = ((BlocoFerro) e).Acertou(); if (elementoAtingido != null) { if (elementoAtingido instanceof Inimigo) { if (!((Inimigo) elementoAtingido).EstaSofrendoDano()) { ((Inimigo) elementoAtingido).SofrerDano(); mse.TocarSom(MusicasSonsEfeito. SOM_INIMIGO_MORRENDO); } } } } } } } private boolean PersonagemEstaAoLado(Character p, GameElement pedra) { if ((p.GetX() = (pedra.GetX() - p.GetWidth() - 20))) { return true; } else if ((p.GetX() >= (pedra.GetX() + pedra.GetWidth())) && (p.GetX()
-
57
Prvia da execuo da Tela da Fase 1
Agora dentro do pacote gameutil2d.project vamos criar uma classe chamada
TelaDesafio, com o seguinte cdigo abaixo:
package gameutil2d.project; import gameutil2d.classes.basic.Box; import gameutil2d.classes.basic.Collision; import gameutil2d.classes.basic.GameElement; import gameutil2d.classes.basic.Image; import gameutil2d.classes.character.Character; import gameutil2d.classes.scene.Scene; import gameutil2d.classes.text.FontName; import gameutil2d.classes.text.TextDrawable; import gameutil2d.framework.OrientationMode; import gameutil2d.framework.deepducktrouble.R; import gameutil2d.project.TelasDoJogo.TelaJogo; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.view.MotionEvent;
-
58
public class TelaDesafio { Character pato_donald; Image seta_esquerda; Image seta_cima; Image seta_direita; Image botao_chutar; Image foto_pato_donald; Context context; Scene scene; enum Acao { PARADO, ANDANDO } Acao acaoPersonagem = Acao.PARADO; Direcao direcaoPersonagem = Direcao.DIREITA; MusicasSonsEfeito mse; Image fundo_tela; Image titulo_fase_concluida; Aguia aguia; int largura_tela; int altura_tela; boolean podeTocarMusica; boolean podeControlar; TextDrawable texto; int hp_desafio; int posicao_centro_x; boolean desafio_morreu; boolean aparecer_frase_fase_concluida; boolean gravaStartTime; long startTime; long endTime; public TelaDesafio(Context context, MusicasSonsEfeito mse) { this.context = context; this.mse = mse; scene = new Scene();
-
59
podeTocarMusica = true; podeControlar = true; texto = new TextDrawable(context, FontName.PC_SENIOR); texto.SetColor(Color.BLACK); texto.SetSize(30); } public void onScreenLoading(int w, int h, OrientationMode orientation) { largura_tela = w; altura_tela = h; posicao_centro_x = (w / 2) - (92 / 2); pato_donald = new Character(context, posicao_centro_x, 0, 92, 135); for(int x = 0; x < 30; x++) pato_donald.AddNewSpriteIdle("parado", R.drawable.pato_donald_parado); for(int x = 0; x < 4; x++) { pato_donald.AddNewSpriteIdle("parado", R.drawable.pato_donald_esperando_1); pato_donald.AddNewSpriteIdle("parado", R.drawable.pato_donald_esperando_1 + 1); } for(int x = 0; x < 4; x++) { pato_donald.AddNewSpriteIdle("parado", R.drawable.pato_donald_esperando_3); pato_donald.AddNewSpriteIdle("parado", R.drawable.pato_donald_esperando_3 + 1); } for(int x = 0; x < 4; x++) { pato_donald.AddNewSpriteIdle("parado", R.drawable.pato_donald_esperando_1); pato_donald.AddNewSpriteIdle("parado", R.drawable.pato_donald_esperando_1 + 1); } for(int x = 0; x < 4; x++) { pato_donald.AddNewSpriteIdle("parado", R.drawable.pato_donald_esperando_5); pato_donald.AddNewSpriteIdle("parado", R.drawable.pato_donald_esperando_5 + 1); }
-
60
pato_donald.AddNewSpriteIdle("somente_parado", R.drawable.pato_donald_parado); for(int x = 0; x
-
61
public void Update() { if(podeTocarMusica) { mse.RepetirMusica(MusicasSonsEfeito.MUSICA_TELA_DESAFIO, true); mse.TocarMusica(MusicasSonsEfeito.MUSICA_TELA_DESAFIO); podeTocarMusica = false; } if(acaoPersonagem == Acao.ANDANDO) { if(direcaoPersonagem == Direcao.DIREITA) { if(pato_donald.IsGround()) pato_donald.MoveToRight("andando", 5, true); else pato_donald.TurnToRight(); pato_donald.MoveByX(7); if (pato_donald.CollisionBySide(scene)) { pato_donald.MoveByX(-7); } else if((pato_donald.GetX() + pato_donald.GetWidth()) > largura_tela) { pato_donald.MoveByX(-7); } } else { if(pato_donald.IsGround()) pato_donald.MoveToLeft("andando", 5, true); else pato_donald.TurnToLeft(); pato_donald.MoveByX(-7); if (pato_donald.CollisionBySide(scene)) { pato_donald.MoveByX(7); } if (pato_donald.GetX() < 0) { pato_donald.MoveByX(7); }
-
62
} } else if(acaoPersonagem == Acao.PARADO) { if(desafio_morreu) { if(pato_donald.IsGround()) pato_donald.Idle("somente_parado", 3, false); } } if (Collision.Check(aguia, pato_donald)) { if (!pato_donald.IsDamaged()) { if ((!aguia.EstaSofrendoDano()) && (!aguia.EstaJogandoPedra())) { pato_donald.SufferDamage("sofrendo_dano", 5); mse.TocarSom(MusicasSonsEfeito. SOM_DONALD_SOFRENDO_DANO); HUDInfo.life--; if (HUDInfo.life == 0) { pato_donald.Idle("parado", 8, true); mse.PararMusica(MusicasSonsEfeito. MUSICA_TELA_DESAFIO); TelasDoJogo.tela = TelaJogo.TELA_GAME_OVER; CriarTela(); } } } } if(pato_donald.IsAttacking()) { for(GameElement e : scene.Elements()) { if(e.GetTag() == "bloco_pedra") { if(PersonagemEstaAoLado(pato_donald, e)) { ((BlocoPedra) e).VoarECair(direcaoPersonagem); } } else if(e.GetTag() == "bloco_ferro") { if(PersonagemEstaAoLado(pato_donald, e)) { ((BlocoFerro) e).DeslizarBloco(direcaoPersonagem);
-
63
} } } } if(desafio_morreu) { if(!aparecer_frase_fase_concluida) { if (aguia.GetY() > 700) { titulo_fase_concluida.SetY(-79); aparecer_frase_fase_concluida = true; gravaStartTime = true; mse.PararMusica(MusicasSonsEfeito. MUSICA_TELA_DESAFIO); mse.RepetirMusica(MusicasSonsEfeito. MUSICA_TELA_FASE_1_CONCLUIDA, false); mse.TocarMusica(MusicasSonsEfeito. MUSICA_TELA_FASE_1_CONCLUIDA); } } else { if(gravaStartTime) { startTime = System.currentTimeMillis(); gravaStartTime = false; } endTime = System.currentTimeMillis(); if(titulo_fase_concluida.GetY() < 100) titulo_fase_concluida.MoveByY(5); if((endTime - startTime) > 6000) { CriarTela(); TelasDoJogo.tela = TelaJogo.TELA_INICIAL; } } } UpdatePedras(); pato_donald.Update(scene); aguia.Update(scene); } public void Draw(Canvas canvas) { scene.Draw(canvas); seta_cima.Draw(canvas); seta_direita.Draw(canvas); seta_esquerda.Draw(canvas);
-
64
botao_chutar.Draw(canvas); foto_pato_donald.Draw(canvas); texto.SetXY(90,65); texto.DrawString(canvas, "=" + HUDInfo.life); texto.SetXY(550,65); texto.DrawString(canvas, "BOSS = " + hp_desafio); } public void onTouch(MotionEvent e) { if(e.getAction() == MotionEvent.ACTION_DOWN) { if(seta_esquerda.IsTouch(e.getX(), e.getY())) { if (podeControlar) { acaoPersonagem = Acao.ANDANDO; direcaoPersonagem = Direcao.ESQUERDA; } } else if(seta_direita.IsTouch(e.getX(), e.getY())) { if (podeControlar) { acaoPersonagem = Acao.ANDANDO; direcaoPersonagem = Direcao.DIREITA; } } else if(seta_cima.IsTouch(e.getX(), e.getY())) { if (podeControlar) { mse.TocarSom(MusicasSonsEfeito.SOM_DONALD_PULANDO); pato_donald.Jump("pulando", 5, false); } } else if(botao_chutar.IsTouch(e.getX(), e.getY())) { if (podeControlar) { mse.TocarSom(MusicasSonsEfeito.SOM_DONALD_CHUTANDO); pato_donald.Attack("chutar_pedra", 5); } } } else { if (podeControlar) { acaoPersonagem = Acao.PARADO; if (pato_donald.IsGround()) { if (!pato_donald.IsAttacking()) {
-
65
pato_donald.Idle("parado", 8, true); } } } } } public void CriarTela() { scene = new Scene(); desafio_morreu = false; aparecer_frase_fase_concluida = false; gravaStartTime = true; podeTocarMusica = true; podeControlar = true; hp_desafio = 4; pato_donald.SetX(posicao_centro_x); pato_donald.SetY(0); scene.Add(fundo_tela); scene.Add(new Image (context,R.drawable.arvore_com_folhas,- 180,altura_tela - 121 - 385,384,385,"arvore")); scene.Add(new Box(-180 + 226, altura_tela - 121 - 385 + 241,156,50,"ponto_colisao")); scene.Add(new Image (context,R.drawable.arvore_sem_folhas_inverso, largura_tela - 200,altura_tela - 121 - 385,249,385,"arvore")); scene.Add(new Box(largura_tela - 200 + 5, altura_tela - 121 - 385 + 238,140,29,"ponto_colisao")); aguia = new Aguia(context,mse, -182, -60); scene.Add(new Box(0, altura_tela - 121, largura_tela, 121,"chao")); scene.Add(new BlocoPedra(context, mse, 200, altura_tela - 121 - 48, 48, 48)); scene.Add(new BlocoPedra(context, mse, 500, altura_tela - 121 - 48, 48, 48)); scene.Add(new BlocoPedra(context, mse, 650, altura_tela - 121 - 48, 48, 48)); scene.Add(pato_donald); scene.Add(aguia);
-
66
scene.Add(titulo_fase_concluida); titulo_fase_concluida.SetY(-79); } private boolean PersonagemEstaAoLado(Character p, GameElement pedra) { if ((p.GetX() = (pedra.GetX() - p.GetWidth() - 20))) { return true; } else if ((p.GetX() >= (pedra.GetX() + pedra.GetWidth())) && (p.GetX() 0) ((Aguia) elementoAtingido).SofrerDano(); else { ((Aguia) elementoAtingido).Morrer(); podeControlar = false; desafio_morreu = true; } } } } if(((BlocoPedra) e).PodeRemoverBloco())
-
67
{ scene.Remove(e); break; } } } } }
Na figura seguinte temos uma prvia de como seria a tela do desafio:
Prvia da execuo da Tela do Desafio
Agora dentro do pacote gameutil2d.project vamos criar uma classe chamada
TelaGameOver, com o seguinte cdigo abaixo:
package gameutil2d.project; import gameutil2d.framework.OrientationMode; import gameutil2d.framework.deepducktrouble.R;
-
68
import gameutil2d.project.TelasDoJogo.TelaJogo; import android.content.Context; import android.graphics.Canvas; import android.view.MotionEvent; import gameutil2d.classes.basic.*; public class TelaGameOver { Image titulo_game_over; Context context; MusicasSonsEfeito mse; long startTime; long endTime; boolean gravaStartTime; boolean podeTocarMusica; public TelaGameOver(Context context, MusicasSonsEfeito mse) { this.context = context; this.mse = mse; gravaStartTime = true; podeTocarMusica = true; } public void onScreenLoading(int w, int h, OrientationMode orientation) { titulo_game_over = new Image(context,R.drawable.titulo_game_over, (w/2) - 170, (h / 2) - 41, 340, 82); } public void Update() { if(podeTocarMusica) { mse.RepetirMusica(MusicasSonsEfeito.MUSICA_TELA_GAME_OVER, false); mse.TocarMusica(MusicasSonsEfeito.MUSICA_TELA_GAME_OVER); podeTocarMusica = false; } if(gravaStartTime) { startTime = System.currentTimeMillis(); gravaStartTime = false; } endTime = System.currentTimeMillis(); if((endTime - startTime) > 4000) {
-
69
podeTocarMusica = true; gravaStartTime = true; TelasDoJogo.tela = TelaJogo.TELA_INICIAL; } } public void Draw(Canvas canvas) { titulo_game_over.Draw(canvas); } public void onTouch(MotionEvent e) { } }
Na figura seguinte temos uma prvia de como seria a tela de game over:
Prvia da execuo da Tela de Game Over
Agora dentro da classe GameMain (que j existe dentro do pacote
gameutil2d.project vamos digitar o seguinte cdigo destacado em azul abaixo:
-
70
package gameutil2d.project; import gameutil2d.framework.*; import gameutil2d.project.TelasDoJogo.TelaJogo; import android.content.Context; import android.graphics.Canvas; import android.view.MotionEvent; public class GameMain { TelaInicial tela_inicial; TelaChamadaFase1 tela_chamada_fase_1; TelaFase1 tela_fase_1; TelaDesafio tela_desafio; TelaGameOver tela_game_over; MusicasSonsEfeito mse; public GameMain(Context context) { mse = new MusicasSonsEfeito(context); tela_inicial = new TelaInicial(context,mse); tela_chamada_fase_1 = new TelaChamadaFase1(context, mse); tela_fase_1 = new TelaFase1(context,mse); tela_desafio = new TelaDesafio(context, mse); tela_game_over = new TelaGameOver(context, mse); TelasDoJogo.tela = TelaJogo.TELA_INICIAL; } public void onScreenLoading(int w, int h, OrientationMode orientation) { tela_inicial.onScreenLoading(w, h, orientation); tela_chamada_fase_1.onScreenLoading(w, h, orientation); tela_fase_1.onScreenLoading(w, h, orientation); tela_desafio.onScreenLoading(w, h, orientation); tela_game_over.onScreenLoading(w, h, orientation); } public void Update() { if(TelasDoJogo.tela == TelaJogo.TELA_INICIAL) tela_inicial.Update(); else if(TelasDoJogo.tela == TelaJogo.TELA_CHAMADA_FASE_1) tela_chamada_fase_1.Update(); else if(TelasDoJogo.tela == TelaJogo.TELA_FASE_1)
-
71
tela_fase_1.Update(); else if(TelasDoJogo.tela == TelaJogo.TELA_DESAFIO) tela_desafio.Update(); else if(TelasDoJogo.tela == TelaJogo.TELA_GAME_OVER) tela_game_over.Update(); } public void Draw(Canvas canvas) { if(TelasDoJogo.tela == TelaJogo.TELA_INICIAL) tela_inicial.Draw(canvas); else if(TelasDoJogo.tela == TelaJogo.TELA_CHAMADA_FASE_1) tela_chamada_fase_1.Draw(canvas); else if(TelasDoJogo.tela == TelaJogo.TELA_FASE_1) tela_fase_1.Draw(canvas); else if(TelasDoJogo.tela == TelaJogo.TELA_DESAFIO) tela_desafio.Draw(canvas); else if(TelasDoJogo.tela == TelaJogo.TELA_GAME_OVER) tela_game_over.Draw(canvas); } public void onTouch(MotionEvent e) { if(TelasDoJogo.tela == TelaJogo.TELA_INICIAL) tela_inicial.onTouch(e); else if(TelasDoJogo.tela == TelaJogo.TELA_CHAMADA_FASE_1) tela_chamada_fase_1.onTouch(e); else if(TelasDoJogo.tela == TelaJogo.TELA_FASE_1) tela_fase_1.onTouch(e); else if(TelasDoJogo.tela == TelaJogo.TELA_DESAFIO) tela_desafio.onTouch(e); else if(TelasDoJogo.tela == TelaJogo.TELA_GAME_OVER) tela_game_over.onTouch(e); } public void onExitGame() { mse.PararTodasMusicas(); } }
Explicando algumas linhas de cdigo do jogo
Irei explicar agora algumas linhas de cdigos essenciais do nosso jogo Deep
Duck Trouble, mediante a sequencia de sua execuo .
Quando executamos o nosso jogo , a primeira tela que exibida a tela inicial
(ou tela de abertura), conforme podemos conferir na figura em seguida:
-
72
Jogo em execuo Tela inicial
A classe responsvel por processar essa tela a classe TelaInicial. Se tocarmos
com o mouse a tela de nossa aplicao, ser disparado o mtodo onTouch da
classe, que ir executar o cdigo destacado em azul abaixo:
public void onTouch(MotionEvent e) { if(e.getAction() == MotionEvent.ACTION_DOWN) { podeTocarMusica = true; mse.PararMusica(MusicasSonsEfeito.MUSICA_TELA_INICIAL); HUDInfo.life = 5; TelasDoJogo.tela = TelaJogo.TELA_CHAMADA_FASE_1; } }
O cdigo destacado acima verifica se houve algum toque na tela, pela condio :
if(e.getAction() == MotionEvent.ACTION_DOWN)
Se a condio for verdadeira, o atributo podeTocarMusica assume o valor true
(indicando que quando essa tela for exibida novamente, a msica ser
reproduzida de novo).
-
73
Em seguida temos a instruo :
mse.PararMusica(MusicasSonsEfeito.MUSICA_TELA_INICIAL);
Que encerra a execuo da msica da tela inicial. Na instruo seguinte:
HUDInfo.life = 5;
Inicio a vida do nosso personagem (life) com o valor 5. E na instruo final :
TelasDoJogo.tela = TelaJogo.TELA_CHAMADA_FASE_1;
Ocorre a atribuio do valor TelaJogo.TELA_CHAMADA_FASE1 para o atributo
tela, indicando que ser exibida a tela de chamada da fase 1, conforme podemos
conferir na figura seguinte:
Jogo em execuo Tela de chamada da fase 1
Se observarmos a execuo do jogo, o ttulo TOQUE A TELA PARA INICIAR O
JOGO no exibido logo que a tela acima visualizada, e sim depois de alguns
segundos, graas ao seguinte cdigo presente dentro do mtodo Update
(destacado em azul) da classe TelaChamadaFase1 :
-
74
public void Update() { if(podeTocarMusica) { mse.RepetirMusica(MusicasSonsEfeito.MUSICA_TELA_CHAMADA_FASE_1, false); mse.TocarMusica(MusicasSonsEfeito.MUSICA_TELA_CHAMADA_FASE_1); podeTocarMusica = false; } if(gravaStartTime) { startTime = System.currentTimeMillis(); gravaStartTime = false; } endTime = System.currentTimeMillis(); }
Que calcula o tempo para a exibio do ttulo. Vejamos agora as instrues
dentro do mtodo Draw destacadas em azul :
public void Draw(Canvas canvas) { titulo_scene_1.Draw(canvas); titulo_savana.Draw(canvas); if((endTime - startTime) > 4000) { titulo_toque_tela_para_iniciar.Draw(canvas); } }
ela que determina quando o ttulo ser visualizado. Se o tempo decorrido
iniciado quando a tela visualizada passou de 4 segundos (equivalente a 4.000
milissegundos), ser exibida a frase na tela.
Ao tocarmos uma regio da tela, executado o seguinte bloco de comandos
(destacado em azul) dentro do mtodo onTouch.
public void onTouch(MotionEvent e) { if(e.getAction() == MotionEvent.ACTION_DOWN) { if((endTime - startTime) > 4000)
-
75
{ mse.PararMusica(MusicasSonsEfeito. MUSICA_TELA_CHAMADA_FASE_1); podeTocarMusica = true; gravaStartTime = true; TelasDoJogo.tela = TelaJogo.TELA_FASE_1; } } }
Que avana para a tela do jogo (que ser processada pela classe TelaFase1).
Na hora em que a tela do jogo exibida, temos a seguinda visualizao :
Jogo em execuo Tela da fase 1
Utilizando a seta de direo para a direita, podemos mover nosso personagem
para a direita. Quando nosso personagem chega perto do bloco de ferro, o
mesmo no sai do lugar :
-
76
Jogo em execuo Tela da fase 1
Esse processo realizado atravs do seguinte bloco de comandos destacado em
azul, presente no mtodo Update (da classe TelaFase1):
if ((contaPasso >= 0) && (contaPasso
-
77
else if(botao_chutar.IsTouch(e.getX(), e.getY())) { if (podeControlar) { mse.TocarSom(MusicasSonsEfeito.SOM_DONALD_CHUTANDO); pato_donald.Attack("chutar_pedra", 5); } }
Que verifica se o boto de chute foi tocado, atravs do mtodo isTouch.
Caso a condio seja verdadeira, verifico se o personagem est no controle
pelo jogador, pela instruo :
if (podeControlar) {
:
Se a condio for verdadeira, exibida a animao dele chutando a pedra e
um som de efeito reproduzindo o chute do personagem ouvido, pelas
seguintes instrues :
mse.TocarSom(MusicasSonsEfeito.SOM_DONALD_CHUTANDO); pato_donald.Attack("chutar_pedra", 5);
Agora vamos ao segundo bloco de instrues, que est dentro do mtodo
Update:
if(pato_donald.IsAttacking()) { for(GameElement e : scene.Elements()) { if(e.GetTag() == "bloco_pedra") { if(PersonagemEstaAoLado(pato_donald, e)) { ((BlocoPedra) e).VoarECair(direcaoPersonagem); } } else if(e.GetTag() == "bloco_ferro") { if(PersonagemEstaAoLado(pato_donald, e)) { ((BlocoFerro) e).DeslizarBloco(direcaoPersonagem); } } } }
-
78
O trecho de cdigo destacado em azul acima o que ser executado
durante o chute em cima do bloco de ferro.
Primeiramente avaliado se o personagem est atacando, ou melhor,
chutando uma pedra (ou bloco de ferro)
if(pato_donald.IsAttacking())
:
Se a condio for verdadeiro, ser processado o loop dentro do bloco de
cdigo. O loop dentro do cdigo varrer todos os elementos do cenrio e ir
verificar qual deles possui a tag bloco_ferro ou bloco_pedra.
No cdigo em azul verificado se o elemento verificado possui a tag
bloco_ferro, pela condio :
if(e.GetTag() == "bloco_ferro")
Caso seja verdadeira a condio, verificado se durante o chute, o
personagem est ao lado do bloco de ferro, pela condio :
if(PersonagemEstaAoLado(pato_donald, e))
Se a condio acima for verdadeira, o bloco deslizado pelo cenrio,
atingindo o primeiro inimigo que aparecer pela frente (no caso, o canguru).
Vejamos o comando abaixo:
((BlocoFerro) e).DeslizarBloco(direcaoPersonagem);
Vejamos o resultado da ao na figura abaixo:
-
79
Jogo em execuo Tela da fase 1
Quando nosso personagem est percorrendo o cenrio do jogo, chega um ponto
que o cenrio para de se deslocar e somente nosso personagem se desloca.
Quando o Pato Donald chega at um ponto do cenrio, como podemos ver na
figura seguinte:
-
80
Jogo em execuo Tela da fase 1
executado o seguinte cdigo dentro do Update :
if ((pato_donald.GetX() + pato_donald.GetWidth()) > 750) { podeControlar = false; }
Que verifica se o personagem atingiu quase o final da tela. Se a condio for
verdadeira, o atributo podeControlar vai assumir o valor false, fazendo com que o
personagem assuma automaticamente o movimento (e desabiliita os controles do
usurio).
Quando o controle passar a ser do computador nesse exato momento,
executado o seguinte bloco de comandos dentro do Update:
if(!podeControlar) { if(pato_donald.GetX() > largura_tela) { if (!surgirInimigo) {
-
81
mse.PararMusica(MusicasSonsEfeito. MUSICA_TELA_FASE_1); mse.RepetirMusica(MusicasSonsEfeito. MUSICA_TELA_DESAFIO_SURGINDO,false); mse.TocarMusica(MusicasSonsEfeito. MUSICA_TELA_DESAFIO_SURGINDO); surgirInimigo = true; } } }
Que verifica se o personagem saiu totalmente da tela, pela condio :
if(pato_donald.GetX() > largura_tela)
Se a condio acima for verdadeira, a msica de fundo encerrada e em seguida
reproduzida a msica de chamada do surgimento do inimigo, e por ultimo o
atributo surgirInimigo recebe true.
Dentro desse contexto executado tambm o seguinte cdigo dentro do Update:
if(surgirInimigo) { if(gravaStartTime) { startTime = System.currentTimeMillis(); gravaStartTime = false; } endTime = System.currentTimeMillis(); aguia.MoveByX(8); if((aguia.GetX() > largura_tela + 200) && ((endTime - startTime) > 4000)) { pato_donald.Idle("parado", 8, true); acaoPersonagem = Acao.PARADO; podeControlar = true; podeTocarMusica = true; TelasDoJogo.tela = TelaJogo.TELA_DESAFIO; surgirInimigo = false; gravaStartTime = true; CriarTela(); } }
Que verifica se o atributo surgirInimigo assume o valor true. Se verdadeiro,
exibido o inimigo voando pela tela, indo atrs do nosso personagem e ao mesmo
-
82
tempo, contabilizado um tempo de durao, que utilizaremos para definir
quando ser exibida a tela do desafio.
Para que a tela do desafio seja exibida, necessrio que seja verdadeira a
seguinte condio :
if((aguia.GetX() > largura_tela + 200) && ((endTime - startTime) > 4000))
Que avalia se o desafio (a guia) atingiu o final da tela (com mais 200 pixels) e se
o tempo contabilizado superior a 4 segundos (que seria o tempo de reproduo
da msica de chamada do surgimento do desafio). Sendo verdadeira a condio
acima, iniciada a tela do desafio.
Na tela do desafio, podemos ver inicialmente nosso desafio (a guia), voando de
um lado para o outro, como pode ver na figura seguinte :
Jogo em execuo Tela do desafio
-
83
Se observarmos o jogo, a guia voa trs vezes de um lado para o outro. Vamos
ver na classe Aguia o cdigo responsvel por esse processo (que est dentro do
mtodo Update):
if (acaoInimigo == Acao.VOANDO) { if (direcaoInimigo == Direcao.DIREITA) { MoveByX(5); if (GetX() > 900) { conta_voos++; direcaoInimigo = Direcao.ESQUERDA; SetY(-40); if (conta_voos == TOTAL_DE_VOOS) { conta_voos = 0; reiniciaAtaque = true; acaoInimigo = Acao.ATACANDO; } } } else { MoveByX(-5); if (GetX() < (-GetWidth()) - 100) { conta_voos++; direcaoInimigo = Direcao.DIREITA; SetY(-40); if (conta_voos == TOTAL_DE_VOOS) { conta_voos = 0; reiniciaAtaque = true; acaoInimigo = Acao.ATACANDO; } } }
Se observarmos o cdigo acima, toda vez que a varivel (atributo) conta_voos for
igual ao valor da constante TOTAL_DE_VOOS, sua ao alterada para o modo
de ataque. Veja o a ao de ataque na figura em seguida :
-
84
Jogo em execuo Tela do desafio
O ataque da guia feita de forma aleatria no jogo. Vejamos o cdigo que define
o modo de ataque da nossa guia:
if (acaoInimigo == Acao.ATACANDO) { if (reiniciaAtaque) { // Define movimento do ataque reiniciaAtaque = false; if (((int) Math.round(Math.random() * 100)) % 2 == 0) direcaoInimigo = Direcao.DIREITA; else direcaoInimigo = Direcao.ESQUERDA; if (((int) Math.round(Math.random() * 100)) % 2 == 0) sentidoAtaqueInimigo = SentidoAtaque.DIAGONAL_PRA_CIMA; else sentidoAtaqueInimigo = SentidoAtaque.DIAGONAL_PRA_BAIXO; if (direcaoInimigo == Direcao.DIREITA) SetX(-182); else SetX(800); if (sentidoAtaqueInimigo == SentidoAtaque.DIAGONAL_PRA_CIMA) SetY(480); else SetY(-229); }
-
85
No total so feitos 3 ataques sobre o nosso personagem. Se depois de todos os
ataques no houver mais pedras (objetos que so lanados sobre inimigo) no
cenrio, a guia joga uma pedra para o nosso personagem, caso contrrio, volta a
voar pelo jogo. Vejamos um trecho de cdigo que realiza toda essa mecnica :
if (sentidoAtaqueInimigo == SentidoAtaque.DIAGONAL_PRA_CIMA) { MoveByY(-8); if (direcaoInimigo == Direcao.DIREITA) MoveByX(8); else MoveByX(-8); if (GetY() < -GetWidth()) { conta_ataques++; if (conta_ataques == TOTAL_ATAQUES) { if (ContaPedras() > 0) { acaoInimigo = Acao.VOANDO; conta_ataques = 0; direcaoInimigo = Direcao.DIREITA; SetY(-40); SetX(-182); } else { acaoInimigo = Acao.JOGAR_PEDRA; SetX(posicao_centro_x); SetY(-229); movimentoVooInimigo = MovimentoVoo.DESCER; } } else reiniciaAtaque = true; }
Vejamos abaixo nossa guia jogando uma pedra para o nosso personagem :
-
86
Jogo em execuo Tela do desafio
Voltando agora para classe TelaDesafio, quando nosso personagem chuta todas
as 4 pedras sobre o desafio, nossa guia morre, conforme podemos ver na figura
seguinte:
-
87
Jogo em execuo Tela do desafio
Nesse momento processado o seguinte cdigo dentro do mtodo Update (na
classe TelaDesafio):
if(desafio_morreu) { if(!aparecer_frase_fase_concluida) { if (aguia.GetY() > 700) { titulo_fase_concluida.SetY(-79); aparecer_frase_fase_concluida = true; gravaStartTime = true; mse.PararMusica(MusicasSonsEfeito. MUSICA_TELA_DESAFIO); mse.RepetirMusica(MusicasSonsEfeito. MUSICA_TELA_FASE_1_CONCLUIDA, false); mse.TocarMusica(MusicasSonsEfeito. MUSICA_TELA_FASE_1_CONCLUIDA); } }
:
}
Que verfiica primeiramente se o desafio morreu, atravs da seguinte instruo :
-
88
if(desafio_morreu)
Como ns sabemos que o desafio morreu, verifico na prxima instruo se o titulo
fase concluda no est sendo visto, pela instruo :
if(!aparecer_frase_fase_concluida)
Caso o ttulo no esteja sendo visto na tela, verifico se o desafio, durante sua
derrota, ficou totalmente fora da tela , durante a sua queda (pois quando a guia
morre, ela comea e descer aos poucos) pela seguinte instruo :
if (aguia.GetY() > 700)
Se a condio for verdadeira, ser exibido na tela o ttulo fase concluda,
conforme podemos ver na figura seguinte :
Jogo em execuo Tela do desafio
Durante a exibio do ttulo , executado o seguinte cdigo abaixo:
-
89
if(gravaStartTime) { startTime = System.currentTimeMillis(); gravaStartTime = false; } endTime = System.currentTimeMillis(); if(titulo_fase_concluida.GetY() < 100) titulo_fase_concluida.MoveByY(5); if((endTime - startTime) > 6000) { CriarTela(); TelasDoJogo.tela = TelaJogo.TELA_INICIAL; }
Que responsvel por descer o ttulo ate um certo ponto da tela e tambm por
verificar se o tempo decorrido iniciado assim que o ttulo fase concluda
exibido ultrapassou 6 segundos. Se o tempo ultrapassou os 6 segundos, o jogo
ser reiniciado, voltado novamente para a tela inicial.
-
90
Concluso a respeito do Tutorial Neste tutorial aprendemos passo a passo como construir um jogo baseado no Deep Duck Trouble - Donald Duck (um jogo bastante conhecido e popular na dcada de 90, disponvel para o console Master System), atravs de todas as tcnicas apresentadas neste tutorial. Que tal experimentar o conhecimento adquiro neste tutorial para aprimorar o jogo desenvolvido ? Espero que meu tutorial lhe tenha sido til
Um forte abrao.