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

Erro "Desenvolvendo jogos para android".

Estou no capitulo 5 e não consigo achar a solucao para um erro. O erro esta na parte onde se cria um novo cano.

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

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

Se comentar as duas linha como esta no codigo o jogo roda sem problemas, no entanto so passam os 5 canos. As duas linha teoricamente deveria criar outro cano no final da list, mas esta dando erro.

10-31 10:10:27.518  20092-20114/br.com.mobile10.jumper E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-16887
    Process: br.com.mobile10.jumper, PID: 20092
    java.lang.NullPointerException
            at br.com.mobile10.jumper.elements.Cano.<init>(Cano.java:27)
            at br.com.mobile10.jumper.elements.Canos.move(Canos.java:43)
            at br.com.mobile10.jumper.engine.Game.run(Game.java:63)
            at java.lang.Thread.run(Thread.java:841)

Alguem poderia me ajudar?

3 respostas

Veja se o seu método getMaximo() está dessa forma:

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

E se o método construtor da classe Cano está dessa forma:

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

}

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

    }

Lembre-se de criar o método valorAleatorio() assim:

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

Me parece que você esqueceu algum desses passos. Espero ter ajudado. :)

Fiz a comparação e parece esta tudo igual. Já olhei com muita calma e não consigo achar o porque desse "NullPointerException". Classe Cano

public class Cano {

    private int alturaDoCanoSuperior;
    private int alturaDoCanoInferior;
    private int posicao;
    private static final int TAMANHO_DO_CANO = 250;
    private static final int LARGURA_DO_CANO = 100;
    private final Paint verde = Cores.getCorDoCano();
    private Tela tela;

    public Cano(Tela tela, int posicao) {
        this.tela = tela;
        this.posicao = posicao;

        this.alturaDoCanoSuperior = 0 + TAMANHO_DO_CANO + valorAleatorio();
        this.alturaDoCanoInferior = tela.getAltura() - TAMANHO_DO_CANO - valorAleatorio();
    }

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

    private void desenhaCanoSuperiorNo(Canvas canvas) {
        canvas.drawRect(posicao, 0, posicao + LARGURA_DO_CANO, alturaDoCanoSuperior, verde);
    }

    private void desenhaCanoInferiorNo(Canvas canvas) {
        canvas.drawRect(posicao, alturaDoCanoInferior, posicao + LARGURA_DO_CANO, tela.getAltura(), verde);
    }

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

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

    public int getPosicao() {
        return posicao;
    }

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

Classe Canos

public class Canos {

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

    public Canos(Tela tela, Pontuacao pontuacao) {
        int posicaoInicial = 200;

        for(int i=0; i < QUANTIDADE_DE_CANOS; i++) {
            posicaoInicial += DISTANCIA_ENTRE_CANOS;
            canos.add(new Cano(tela, posicaoInicial));
        }
    }

    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()) {
                pontuacao.aumenta();
                iterator.remove();
                Cano outroCano = new Cano(tela, getMaximo() + DISTANCIA_ENTRE_CANOS);
                iterator.add(outroCano);
            }
        }

    }

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

}

Classe Pontuacao

public class Pontuacao {

    private static final Paint BRANCO = Cores.getCorDaPontuacao();
    private int pontos = 0;

    public void aumenta() {
        pontos++;
    }

    public void desenhaNo(Canvas canvas) {
        canvas.drawText(String.valueOf(pontos), 100, 100, BRANCO);
    }
}

Classe Tela

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;
    }
}

Classe Game

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

    private boolean isRunning = true;
    private final SurfaceHolder holder = getHolder();
    private Passaro passaro;
    private Bitmap background;
    private Tela tela;
    private Cano cano;
    private Canos canos;
    private Pontuacao pontuacao;

    public Game(Context context) {
        super(context);
        tela = new Tela(context);
        inicializaElementos();
        setOnTouchListener(this);
    }

    private void inicializaElementos() {
        this.passaro = new Passaro(tela);
        this.canos = new Canos(tela, pontuacao);
        this.pontuacao = new Pontuacao();

        Bitmap back = BitmapFactory.decodeResource(getResources(), R.drawable.background);
        this.background = Bitmap.createScaledBitmap(back, back.getWidth(), tela.getAltura(), false);
    }

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


    }

    @Override
    public void run() {

        while(isRunning) {
            if(!holder.getSurface().isValid()) continue;
            Canvas canvas = holder.lockCanvas();

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

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

            holder.unlockCanvasAndPost(canvas);
        }
    }


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

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

No construtor da sua classe Canos, você esqueceu de atribuir os argumentos do construtor aos seus atributos da classe:

    private Tela tela;
    private Pontuacao pontuacao;

    public Canos(Tela tela, Pontuacao pontuacao) {
        int posicaoInicial = 200;

        for(int i=0; i < QUANTIDADE_DE_CANOS; i++) {
            posicaoInicial += DISTANCIA_ENTRE_CANOS;
            canos.add(new Cano(tela, posicaoInicial));
        }
    }

Quando você utiliza eles, no método move, estão nulos:

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

Para resolver isso, basta fazer:

    public Canos(Tela tela, Pontuacao pontuacao) {
        int posicaoInicial = 200;
        this.pontuacao = pontuacao;
        this.tela = tela;

        for(int i=0; i < QUANTIDADE_DE_CANOS; i++) {
            posicaoInicial += DISTANCIA_ENTRE_CANOS;
            canos.add(new Cano(tela, posicaoInicial));
        }
    }

Abraço.