90

Tutorial Android 02J Criando Jogo Deep Duck Trouble

Embed Size (px)

DESCRIPTION

Aprenda a desenvolver jogos para android criando o jogo Deep Duck Trouble

Citation preview

  • 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.