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

o meu codigo esta Dando um falta FATAL EXCEPTION: Thread-14339

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

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

não consigo achar o erro Eu Ja revisei o codigo todo de acordo com a video aula e a aula 5.2 Mas continua dando FATAL EXCEPTION: Thread-14339

E/AndroidRuntime: FATAL EXCEPTION: Thread-14339 Process: andre.com.br.jumper, PID: 22875 java.lang.NullPointerException: Attempt to invoke virtual method 'int andre.com.br.jumper.graphic.Tela.getAltura()' on a null object reference at andre.com.br.jumper.elements.Cano.(Cano.java:22) at andre.com.br.jumper.elements.Canos.move(Canos.java:41) at andre.com.br.jumper.enginer.Game.run(Game.java:56) at java.lang.Thread.run(Thread.java:818)

8 respostas

Olá André,

Pela Exception que está sendo exibida parece que o problema tá ocorrendo na classe Tela. O código tá tentando invocar o método getAltura() em uma referência nula. Dá uma olhadinha nessa classe e vê se consegue encontrar o porquê dessa referência estar nula.

Se ainda assim não conseguir encontrar o problema, posta aqui o código da sua classe Tela para tentarmos ajudar.

package andre.com.br.jumper.graphic;

import android.content.Context;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;

public class Tela {

    private DisplayMetrics metrics;

    public Tela (Context context){
       WindowManager wm =(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
       Display display = wm.getDefaultDisplay();
        metrics = new DisplayMetrics();
        display.getMetrics(metrics);
    }

    public int getAltura(){
        return metrics.heightPixels;
    }

    public int getLargura (){
        return metrics.widthPixels;
    }

}

Olá Andre,

Esta classe parece estar ok, posta também o código das classes Cano, Canos e Game pra gente tentar identificar o ponto problemático.

package andre.com.br.jumper.elements;

import android.graphics.Canvas;
import android.graphics.Paint;

import andre.com.br.jumper.graphic.Cores;
import andre.com.br.jumper.graphic.Tela;

public class Cano {

    private int posicao;// é o lado esquerdo do meu cano
    private int alturaDoCanoInferior;
    private Tela tela;
    private static final int TAMANHO_DO_CANO = 280;
    private static final int LARGURA_DO_CANO = 100;
    private static final Paint VERDE = Cores.getCorDoCano();
    private int alturaDoCanoSuperior;

    public Cano (Tela tela, int posicao){
        this.tela = tela;
        this.posicao = posicao;
        alturaDoCanoInferior = tela.getAltura() - TAMANHO_DO_CANO - valorAleatorio();
        alturaDoCanoSuperior =  TAMANHO_DO_CANO + valorAleatorio();
    }

    private int valorAleatorio() {
        return (int) (Math.random() * 100);
    }

    public void desenhaNo(Canvas canvas) {
        desenhaCanoInferiorNo(canvas);
        desenhaCanoSuperiorNo(canvas);
    }

    private void desenhaCanoInferiorNo(Canvas canvas) {
        canvas.drawRect(posicao, alturaDoCanoInferior, posicao + LARGURA_DO_CANO, tela.getAltura(), VERDE);
    }
    private void desenhaCanoSuperiorNo(Canvas canvas) {
        canvas.drawRect(posicao, 0, posicao + LARGURA_DO_CANO, alturaDoCanoSuperior, VERDE);
    }

    public void move() {
        this.posicao -= 5;
    }

    public boolean saiuDaTela() {
        return posicao + LARGURA_DO_CANO < 0;
    }

    public int getPosicao() {
        return posicao;
    }
}
package andre.com.br.jumper.elements;

import android.graphics.Canvas;

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

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

public class Canos {

    public static final int DISTANCIA_ENTRE_CANOS = 250;
    public static final int QUANTIDADE_DE_CANOS = 5;
    private final List<Cano> canos = new ArrayList<Cano>();
    private Tela tela;

    public  Canos (Tela tela){
        int posicao = 400;
        for (int i = 0; i <  QUANTIDADE_DE_CANOS; i++ ){
            posicao +=  DISTANCIA_ENTRE_CANOS;
            Cano cano = new Cano(tela, posicao);
            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 = (Cano) iterator.next();
            cano.move();

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

    public int getMaximo() {
        int maximo = 0;
        for(Cano cano : canos) {
            maximo = Math.max(cano.getPosicao(), maximo);
        }
        return maximo;
    }
}
package andre.com.br.jumper.enginer;

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 andre.com.br.jumper.R;
import andre.com.br.jumper.elements.Cano;
import andre.com.br.jumper.elements.Canos;
import andre.com.br.jumper.elements.Passaro;
import andre.com.br.jumper.graphic.Tela;

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

    private boolean isRunning = true;
    private SurfaceHolder holder = getHolder();
    private Bitmap background;
    private Tela tela;

    private Passaro passaro;
    private Canos canos;

    public Game(Context context) {
        super(context);

        tela = new Tela(context);

        inicializaElementos();
        setOnTouchListener(this);
    }

    private void inicializaElementos() {
        passaro = new Passaro(tela);
        canos = new Canos(tela);
        Bitmap back = BitmapFactory.decodeResource(getResources(), R.drawable.background);
        background = Bitmap.createScaledBitmap(back, tela.getLargura(), tela.getAltura(), false);

    }

    @Override
    public void run() {
        while(isRunning){
            if (!holder.getSurface().isValid()) continue;// se o holder não tiver valido não podera desenhar
            Canvas canvas = holder.lockCanvas();
            // desenho dos componentes

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

            holder.unlockCanvasAndPost(canvas);
        }
    }

    public void inicia() {
        this.isRunning = true;
    }

    public void cancela() {
        this.isRunning = false;
    }

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

}
solução!

Olá Andre,

No construtor da classe Canos, onde você recebe uma referência para a tela, ficou faltando guardar essa referência no atributo da classe. Os canos iniciais são inicializados corretamente, mas quando você precisa criar os novos canos (quando algum sai da tela) você vai precisar utilizar o atributo tela que nesse momento vai estar nulo, por isso o NullPointerException.

A correção é simples:

public  Canos (Tela tela){
        this.tela = tela;  // <---- Adicionar essa linha
        int posicao = 400;
        for (int i = 0; i <  QUANTIDADE_DE_CANOS; i++ ){
            posicao +=  DISTANCIA_ENTRE_CANOS;
            Cano cano = new Cano(tela, posicao);
            canos.add(cano);
        }
    }

Obrigado agora foi