Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

GameOver Sem encostar nos canos

Tenho mais dois problemas, vou fazer de forma individual pois pode ajudar outros que podem ter o mesmo problema...

Neste é o gameOver que esta acontecendo sem o passaro encostar nos canos acho q ele se alinha de forma vertical mesmo estando no meio da tela. Não sei qual classe tenho q mandar para ver entao vou postar o Verificador de colisao e a classe Game

package br.com.alura.jumper.engine;

import br.com.alura.jumper.elements.Canos;
import br.com.alura.jumper.elements.Passaro;


public class VerificadorDeColisao {

    private final Passaro passaro;
    private final Canos canos;

    public VerificadorDeColisao(Passaro passaro, Canos canos) {
        this.passaro = passaro;
        this.canos = canos;

    }

    public boolean temColisao() {
        return canos.temColisaoCom(passaro);
    }
}
package br.com.alura.jumper.engine;


import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

import br.com.alura.jumper.R;
import br.com.alura.jumper.elements.Cano;
import br.com.alura.jumper.elements.Canos;
import br.com.alura.jumper.elements.GameOver;
import br.com.alura.jumper.elements.Passaro;
import br.com.alura.jumper.elements.Pontuacao;
import br.com.alura.jumper.graphic.Tela;

public class Game extends SurfaceView implements Runnable, View.OnTouchListener {

    private final Context context;
    private boolean isRunning = true;
    private SurfaceHolder holder =  getHolder();
    private Passaro passaro;
    private Canos canos;
    private Canvas canvas;
    private Bitmap background;
    private Tela tela;
    private Pontuacao pontuacao;
    private Som som;


    public Game(Context context) {
        super(context);
        this.context = context;

        tela = new Tela(context);
        //som = new Som(context);

        inicializaElementos();
        setOnTouchListener(this);

    }

    private void inicializaElementos(){
        passaro = new Passaro(tela,context,som);
        pontuacao = new Pontuacao();
        canos = new Canos(tela,pontuacao, context);
        Bitmap back = BitmapFactory.decodeResource(getResources(), R.drawable.background);
        background = Bitmap.createScaledBitmap(back, back.getWidth(), tela.getAltura(),false);
    }

    @Override
    public void run() {
        while (isRunning){
            if(!holder.getSurface().isValid()) continue;
            canvas = holder.lockCanvas();

            canvas.drawBitmap(background, 0, 0, null);
            passaro.desenhaNo(canvas);
            passaro.cai();

            canos.desenhaNo(canvas);
            canos.move();
            pontuacao.desenhaNo(canvas);

            if(new VerificadorDeColisao(passaro, canos).temColisao()){
                new GameOver(tela).desenhaNo(canvas);
                isRunning = false;
            }
            holder.unlockCanvasAndPost(canvas);
        }
    }

    public void inicia() {
        isRunning = true;
    }

    public void pausa() {
        isRunning = false;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        passaro.pula();
        return false;
    }
}
7 respostas

Sempre que você postar um código, não esqueça de formatá-lo colocando ``` (três crases, em vez de aspas simples) na primeira linha e na última. ;)

Formatei seu código. Posta a classe Canos, por favor?

package br.com.alura.jumper.elements;

import android.content.Context;
import android.graphics.Canvas;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

import br.com.alura.jumper.graphic.Tela;

public class Canos {

    private final List<Cano> canos = new ArrayList<Cano>();
    private static final int QUANTIDADE_CANOS = 5;
    private static final int DISTANCIA_ENTRE_CANOS = 200;
    private final Pontuacao pontuacao;
    private Tela tela;
    private Context context;

    public Canos(Tela tela, Pontuacao pontuacao, Context context){
        this.tela = tela;
        this.pontuacao = pontuacao;
        int posicao = 400;

        for (int i = 0; i < QUANTIDADE_CANOS; i++){
            posicao += DISTANCIA_ENTRE_CANOS;
            Cano cano = new Cano(tela, posicao, context);
            canos.add(cano);
        }
    }

    public void desenhaNo(Canvas canvas) {
        for(Cano cano : canos){
            cano.desenhaNo(canvas);
        }
    }

    public void move(){
        ListIterator<Cano> iterator =  canos.listIterator();
        while (iterator.hasNext()){
            Cano cano = iterator.next();
            cano.move();

            if (cano.saiuDaTela()) {
                pontuacao.aumenta();
                iterator.remove();
                Cano outroCano = new Cano(tela, getMaximo() + DISTANCIA_ENTRE_CANOS, context);
                iterator.add(outroCano);
            }
        }
    }

    private int getMaximo() {
        int maximo = 0;
        for(Cano cano : canos){
            maximo =  Math.max(cano.getPosicao(), maximo);
        }
        return maximo;
    }

    public boolean temColisaoCom(Passaro passaro) {
        for (Cano cano : canos){
            if(cano.temColisaoHorizontalCom(passaro) || cano.temColisaoVerticalCom(passaro)){
                return true;
            }
        }
        return false;
    }
}

Olha esse trecho do método temColisaoCom:

for (Cano cano : canos){
    if(cano.temColisaoHorizontalCom(passaro) || cano.temColisaoVerticalCom(passaro)){
        return true; //tem colisão...
    }
}

Podemos saber por que há esse comportamento do game over.

Já que o pássaro está um pouco a frente na tela, o cano passa pelo pássaro antes de ser destruído. Como consideramos a colisão comparando todos os canos, o caso que há colisão sem o pássaro tocar no cano que está a sua frente ocorre quando haveria colisão com o cano que já passou.

Bom dia

Estava pensando sobre o que você escreveu ali acima, mas não consegui relacionar com o script. Pensei que poderia ser na classe game sobre as ordens não sei se tem sentido isso...

solução!

Veja que o cano ao passar pelo pássaro não é destruído de imediato. Nós destruímos o cano somente quando a borda direita do cano sai da tela.

Vamos chamar esse cano específico de CANO.

Então, pela nossa regra de colisão horizontal, vemos que teve colisão quando:

CANO.posicao - Passaro.X < Passaro.RAIO
ou
CANO.posicao < Passaro.RAIO + Passaro.X

Oras, se o cano passou pelo pássaro, a posição do cano já é menor que a posição X do pássaro, pior ainda se somarmos com o raio.

Então, quando o cano passa pelo pássaro, esse método de colisão horizontal sempre devolverá true.

Veja no seu código que você está verificando que teve colisão quando temColisaoHorizontal ou temColisaoVertical. Logo, todo cano que passar pelo pássaro (que na realidade sempre será um) disparará uma colisão.

Para resolver esse problema, basta trocar para &&:

for (Cano cano : canos){
    if(cano.temColisaoHorizontalCom(passaro) && cano.temColisaoVerticalCom(passaro)){
        return true; //tem colisão...
    }
}

Obrigado foi falta de atenção total nessa... deu certo...