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

Referência vazia

Olá.

Talvez possa me ajudar.

Por que acontece às vezes, "do nada", erro de referência vazia?

O que pode ser?

Erro:

03-02 12:23:24.679 13273-13998/jssl.brpt.ads.hitjumperrun E/AndroidRuntime: 
FATAL EXCEPTION: Thread-12776 
Process: jssl.brpt.ads.hitjumperrun, PID: 13273

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.Canvas.drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint)' on a null object reference

at jssl.brpt.ads.hitjumperrun.elements.FundoAzulESol.desenhaNo(FundoAzulESol.java:65)

at jssl.brpt.ads.hitjumperrun.engine.Game.desenhaElementosNoCanvas(Game.java:248)

at jssl.brpt.ads.hitjumperrun.engine.Game.run(Game.java:214)

at java.lang.Thread.run(Thread.java:818)

Obrigado.

4 respostas

Posta a sua classe FundoAzulESol e sua classe Game.

Obs.: para postar código, basta colocar entre três crases. ``` (sem espaço).

Eeh, Felipe! Foi vc que deu o curso online, certo?! Legal, valeu. :)

Se puder dar umas dicas aí, eu agradeço. O erro não ocorre sempre. É difícil acontecer.

package jssl.brpt.ads.hitjumperrun.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 jssl.brpt.ads.hitjumperrun.MainActivity;
import jssl.brpt.ads.hitjumperrun.R;
import jssl.brpt.ads.hitjumperrun.elements.Alimento;
import jssl.brpt.ads.hitjumperrun.elements.Arvores;
import jssl.brpt.ads.hitjumperrun.elements.Canos;
import jssl.brpt.ads.hitjumperrun.elements.CarrosEVans;
import jssl.brpt.ads.hitjumperrun.elements.FundoAzulESol;
import jssl.brpt.ads.hitjumperrun.elements.Grama;
import jssl.brpt.ads.hitjumperrun.elements.Nuvens;
import jssl.brpt.ads.hitjumperrun.elements.Passaro;
import jssl.brpt.ads.hitjumperrun.elements.Pontuacao;
import jssl.brpt.ads.hitjumperrun.elements.PredioDaGaiola;
import jssl.brpt.ads.hitjumperrun.elements.Predios;
import jssl.brpt.ads.hitjumperrun.elements.TerrenoEAsfalto;
import jssl.brpt.ads.hitjumperrun.graphics.Formatacao;
import jssl.brpt.ads.hitjumperrun.graphics.Tela;

public class Game extends SurfaceView implements Runnable, View.OnTouchListener {
    private Tela tela;
    private Context context;
    private SurfaceHolder holder;
    private Canvas canvas;
    private MotionEvent event;
    //ELEMENTOS
    private FundoAzulESol fundoAzulESol;
    private Nuvens nuvens;
    private Predios predios;
    private Arvores arvores;
    private Passaro passaro;
    private Canos canos;
    private Pontuacao pontuacao;
    private Alimento alimento;
    private Som som;
//    private Som somVeiculos;
    private TerrenoEAsfalto terrenoEAsfalto;
    private CarrosEVans carrosEVans;
    private PredioDaGaiola predioDaGaiola;
    private Grama grama;
    //INTERRUPTORES DE CONTROLE
    private boolean isRunning;
    private boolean touchInGame;
    private boolean inGame;
    private boolean somNoInicioDoJogo;
    public static boolean inPause;
    private boolean passaroVoando;
    public static boolean passaroMachucado;
    private boolean pulando;
    private boolean caindoMorto;
    private boolean fimDeJogo;
    private boolean botaoPauseAtivo;
    private boolean diminuiNumeroDeColisoes;
    private boolean predioGaiolaSaiuDaTela;
    private boolean foraDaGaiola;
    //DEFINIÇÕES
    private int BASE_DOS_PREDIOS;
    private int BASE_DOS_CANOS;
    public static int numeroMaxDeColisoes;
    public static int numeroDeVidas;
    private int numPerdeuVida;
    private int contAfastaPassaroDaColisao;
    private int tempoParaAparecerBotaoPause;

    public static int larguraDoBotaoPlayPause;
    private int alturaDoBotaoPlayPause;
    private float floatLeftBotaoPlayPause;
    private float floatTopBotaoPlayPause;

    public static int larguraDoBotaoReiniciar;
    private int alturaDoBotaoReiniciar;
    private float floatLeftBotaoReiniciar;
    private float floatTopBotaoReiniciar;

    public static int larguraDoBotaoAltoFalante;
    private int alturaDoBotaoAltoFalante;
    private float floatLeftBotaoAltoFalante;
    private float floatTopBotaoAltoFalante;

    private float velocidadeDosCanos;
    //BITMAPS
    private Bitmap botaoPause;
    private Bitmap botaoPlay;
    private Bitmap botaoReiniciar;
    private Bitmap botaoAltoFalanteLigado;
    private Bitmap botaoAltoFalanteDesligado;

    //INFO e MARCA POSIÇÃO CLICADA NA TELA
    private double toqueHorizontal;
    private double toqueVertical;
    private int tamanhoDoTextoInfo;
    public static int numeroDePulosDiminuiBarraVerde;
    public static int numeroDePulosColocaAlimentoNaTela;
    private int contadorRun;

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

    private void inicializaElementos() {

        /**************************************************************************************
         PROPORÇÕES DE TELA, ELEMENTOS E ALTURAS*/
        BASE_DOS_PREDIOS = (int) (tela.getAltura() / 1.315068493); //=1460  // 1.271); //=1510.60
        BASE_DOS_CANOS = BASE_DOS_PREDIOS + (int) (tela.getAltura() / 8.347); //distância da BASE DOS PRÉDIOS até a BASE DOS CANOS
        tela.setProporcaoLarguraDisplay(1);
        tela.setProporcaoAlturaDisplay(1);
        tela.setMargemSuperiorDisplay(1); //AINDA NÃO USADO
        tela.setMargemEsquerdaDisplay(1); //AINDA NÃO USADO
        /**************************************************************************************/

        isRunning = true;
        touchInGame = false;
        inGame = false;
        somNoInicioDoJogo = true;
        inPause = false;
        passaroVoando = true;
        passaroMachucado = false;
        pulando = true;
        caindoMorto = false;
        fimDeJogo = false;
        botaoPauseAtivo = false;
        diminuiNumeroDeColisoes = true;
        predioGaiolaSaiuDaTela = false;
        foraDaGaiola = false;

        numeroMaxDeColisoes = 4;
        numeroDeVidas = numeroMaxDeColisoes;
        numPerdeuVida = numeroMaxDeColisoes;

        tempoParaAparecerBotaoPause = 0;
        contAfastaPassaroDaColisao = 0;
        numeroDePulosDiminuiBarraVerde = 0;
        numeroDePulosColocaAlimentoNaTela = 0;

        velocidadeDosCanos = tela.getLargura() / 108;

        alturaDoBotaoPlayPause = (int) (tela.getAltura() / 14.769230769);
        larguraDoBotaoPlayPause = alturaDoBotaoPlayPause;
        floatLeftBotaoPlayPause = tela.getLargura() - larguraDoBotaoPlayPause - (float) (tela.getLargura() / 54.0);
        floatTopBotaoPlayPause = (float) (tela.getAltura() / 76.8);

        alturaDoBotaoReiniciar = (int) (tela.getAltura() / 4.923076923);
        larguraDoBotaoReiniciar = alturaDoBotaoReiniciar;
        floatLeftBotaoReiniciar = (float) (tela.getLargura() / 3.130434783);
        floatTopBotaoReiniciar = (float) (tela.getAltura() / 2.509803922);

        alturaDoBotaoAltoFalante = (int) (tela.getAltura() / 14.769230769);
        larguraDoBotaoAltoFalante = alturaDoBotaoPlayPause;
        floatLeftBotaoAltoFalante = floatLeftBotaoPlayPause;
        floatTopBotaoAltoFalante = (float) (tela.getAltura() / 11.294117647);

        int posicaoInicialDoCano = tela.getLargura();
        int margemInferiorDaTela = 0;
        int margemSuperiorDaTela = 0;

        som = new Som(context);
//        somVeiculos = new Som(context);
        fundoAzulESol = new FundoAzulESol(context, tela);
        nuvens = new Nuvens(context, tela, BASE_DOS_PREDIOS);
        predios = new Predios(context, tela, BASE_DOS_PREDIOS);
        passaro = new Passaro(tela, context, som, BASE_DOS_CANOS);
        pontuacao = new Pontuacao(context, tela, som);
        alimento = new Alimento(tela, context, passaro, pontuacao, som);
        canos = new Canos (context, tela, posicaoInicialDoCano, margemInferiorDaTela,
                margemSuperiorDaTela, pontuacao, passaro, BASE_DOS_CANOS);
        arvores = new Arvores(context, tela, BASE_DOS_PREDIOS);
        terrenoEAsfalto = new TerrenoEAsfalto(context, tela, BASE_DOS_PREDIOS);
        carrosEVans = new CarrosEVans(context, tela, som, BASE_DOS_PREDIOS);
        predioDaGaiola = new PredioDaGaiola(context, tela, velocidadeDosCanos);
        grama = new Grama(tela, context, BASE_DOS_CANOS, velocidadeDosCanos);

        bitmap();
        contadorRun = 0; // para informações de desenvolvimento
    }

    private void bitmap() {  // tamanho 150 x 150
        Bitmap bitmapPause = BitmapFactory.decodeResource(context.getResources(), R.drawable.botaopause);
        botaoPause = Bitmap.createScaledBitmap (bitmapPause, larguraDoBotaoPlayPause, alturaDoBotaoPlayPause, false);

        Bitmap bitmapPlay = BitmapFactory.decodeResource(context.getResources(), R.drawable.botaoplay);
        botaoPlay = Bitmap.createScaledBitmap (bitmapPlay, larguraDoBotaoPlayPause, alturaDoBotaoPlayPause, false);

        Bitmap bitmapReiniciar = BitmapFactory.decodeResource(context.getResources(), R.drawable.botaoreiniciar);
        botaoReiniciar = Bitmap.createScaledBitmap (bitmapReiniciar, larguraDoBotaoReiniciar, alturaDoBotaoReiniciar, false);

        Bitmap bitmapAltoFalanteLigado = BitmapFactory.decodeResource(context.getResources(), R.drawable.altofalanteligado);
        botaoAltoFalanteLigado = Bitmap.createScaledBitmap (bitmapAltoFalanteLigado, larguraDoBotaoAltoFalante, alturaDoBotaoAltoFalante, false);

        Bitmap bitmapAltoFalanteDesligado = BitmapFactory.decodeResource(context.getResources(), R.drawable.altofalantedesligado);
        botaoAltoFalanteDesligado = Bitmap.createScaledBitmap (bitmapAltoFalanteDesligado, larguraDoBotaoAltoFalante, alturaDoBotaoAltoFalante, false);
    }

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

            foraDaGaiola = predioDaGaiola.momentoEmQueOPassaroSaiDaGaiola();
            desenhaElementosNoCanvas();
            botaoPauseAtivoETempoDeAtivacao();
            moveElementos();
            verificaColisaoComCanos();
            gameOver(canvas);

            holder.unlockCanvasAndPost(canvas);
        }
    }

    @Override public boolean onTouch(View v, MotionEvent event) {
        this.event = event;
        toqueHorizontal = event.getX();
        toqueVertical = event.getY();

        if(!inGame&&!inPause) if(limiteDeToqueDoBotaoPlayPause()) { inGame = true; touchInGame = true; }

        if(fimDeJogo) if(limiteDeToqueDoBotaoReiniciar()) { reiniciaJogo(); }

        if(!fimDeJogo && !inGame) if(limiteDeToqueDoBotaoAltoFalante()) {
            Som.somLigado = !Som.somLigado;
            if(Som.somLigado && !foraDaGaiola) escolheSomDeInicioDeJogo();
        }

        if(inGame && foraDaGaiola) {
            passaroPula();
            if(numeroDeVidas > 0) alimento.passaroFoiAlimentado(toqueHorizontal, toqueVertical);
        }
        alternaEntreBotaoPlayPause();

//        numeroDeVidas = 0;   // FINALIZA DE IMEDIATO O JOGO

        return false;
    }

    private void desenhaElementosNoCanvas() {
        fundoAzulESol.desenhaNo(canvas);
        nuvens.desenhaNo(canvas);
        predios.desenhaNo(canvas);
        arvores.desenhaNo(canvas);
        terrenoEAsfalto.desenhaNo(canvas);
        carrosEVans.desenhaNo(canvas);
        canos.desenhaNo(canvas);
        grama.desenhaNo(canvas);
        alimento.desenhaNoCanvas(canvas, predioGaiolaSaiuDaTela);
        predioDaGaiola.desenhaNo(canvas);
        if(foraDaGaiola) passaro.desenhaNo(canvas, caindoMorto);
        desenhaBotaoPlayPauseNo(canvas);
        pontuacao.escreveOsPontosNo(canvas);
        pontuacao.desenhaVidasRestantes(canvas, numeroDeVidas, numPerdeuVida);
        pontuacao.desenhaBarraDeContorno(canvas);
        pontuacao.desenhaBarrasVerdes(canvas, inGame);
        desenhaBotaoAltoFalante(canvas);

//        infoDeTelaParaDesenvolvimentoDoJogo(canvas); contadorRun++;
    }

    private void escolheSomDeInicioDeJogo() {
        if(somNoInicioDoJogo) {
            int num = valorAleatorio();
            if(num >= 0 && num < 3) som.tocaSom(Som.somINICIO); somNoInicioDoJogo = false;
            if(num >= 3 && num < 6) som.tocaSom(Som.somINICIO1); somNoInicioDoJogo = false;
            if(num >= 6 && num < 10) som.tocaSom(Som.somINICIO2); somNoInicioDoJogo = false;
        }
    }

    private void botaoPauseAtivoETempoDeAtivacao() {
        if(!inGame && !inPause||caindoMorto||passaroMachucado) {
            botaoPauseAtivo = false; tempoParaAparecerBotaoPause = 0;
        } else {
            if(tempoParaAparecerBotaoPause < 60) tempoParaAparecerBotaoPause ++;
            else botaoPauseAtivo = true;
        }
    }

    private void desenhaBotaoPlayPauseNo(Canvas canvas) {
        if(!inGame && !inPause) canvas.drawBitmap(botaoPlay, floatLeftBotaoPlayPause, floatTopBotaoPlayPause, null);
        if(botaoPauseAtivo && !fimDeJogo) {
            if(!inPause) canvas.drawBitmap(botaoPause, floatLeftBotaoPlayPause, floatTopBotaoPlayPause, null);
            if(inPause) canvas.drawBitmap(botaoPlay, floatLeftBotaoPlayPause, floatTopBotaoPlayPause, null);
        }

//        tamanho 150 x 150
    }

    private void desenhaBotaoReiniciar(Canvas canvas) {
        canvas.drawBitmap(botaoReiniciar, floatLeftBotaoReiniciar, floatTopBotaoReiniciar, null);
    }

    private void desenhaBotaoAltoFalante(Canvas canvas) {
        if(!fimDeJogo && !inGame) {
            if(Som.somLigado) canvas.drawBitmap(botaoAltoFalanteLigado, floatLeftBotaoAltoFalante, floatTopBotaoAltoFalante, null);
            else canvas.drawBitmap(botaoAltoFalanteDesligado, floatLeftBotaoAltoFalante, floatTopBotaoAltoFalante, null);
        }
    }

    private boolean limiteDeToqueDoBotaoPlayPause() {
        return ((toqueHorizontal > floatLeftBotaoPlayPause && toqueHorizontal < floatLeftBotaoPlayPause + larguraDoBotaoPlayPause) &&
                (toqueVertical > floatTopBotaoPlayPause && toqueVertical < floatTopBotaoPlayPause + alturaDoBotaoPlayPause));
    }

    private boolean limiteDeToqueDoBotaoReiniciar() {
        return ((toqueHorizontal > floatLeftBotaoReiniciar && toqueHorizontal < floatLeftBotaoReiniciar + larguraDoBotaoReiniciar) &&
                (toqueVertical > floatTopBotaoReiniciar && toqueVertical < floatTopBotaoReiniciar + alturaDoBotaoReiniciar));
    }

    private boolean limiteDeToqueDoBotaoAltoFalante() {
        return ((toqueHorizontal > floatLeftBotaoAltoFalante && toqueHorizontal < floatLeftBotaoAltoFalante + larguraDoBotaoAltoFalante) &&
                (toqueVertical > floatTopBotaoAltoFalante && toqueVertical < floatTopBotaoAltoFalante + alturaDoBotaoAltoFalante));
    }

    private void alternaEntreBotaoPlayPause() {
        if(botaoPauseAtivo && !caindoMorto && limiteDeToqueDoBotaoPlayPause()) {
                    if (!inPause) { inGame = false; touchInGame = false; inPause = true; som.autoPause(); }
                    else { inGame = true; touchInGame = true; inPause = false; som.autoResume();}
        }
    }

    private void moveElementos() {
        if(inGame) {
            predioGaiolaSaiuDaTela = predioDaGaiola.move();
            if(predioGaiolaSaiuDaTela)
                canos.move(fimDeJogo);
            predios.move();
            arvores.move();
            terrenoEAsfalto.move();
            grama.move();
            carrosEVans.move();
        }
        fundoAzulESol.moveSol();
        nuvens.move();
        if(inGame && passaroVoando && foraDaGaiola) {
            if(!pulando) passaro.cai();
            if(pulando) pulando = passaro.pula();
        }
    }

    private void verificaColisaoComCanos() {
        if(!fimDeJogo && inGame) {
            if(new VerificaColisao(passaro, canos).temColisaoComCanos()) {
                if(diminuiNumeroDeColisoes) {
                    diminuiNumeroDeColisoes = false;
                    som.tocaSom(Som.somCOLISAO);
                    numeroDeVidas--;
                    numeroDePulosDiminuiBarraVerde = 0;
                    if(numeroDeVidas <1) return;
                    else escolheSomDeMachudaco();
                }
                passaroMachucado = true;
                touchInGame = false;
                passaroVoando = false;
                passaro.ajustaAlturaDoPassaroNaColuna(canos, passaro);
                passaro.resetAceleracaoDaQueda();
            } else {
                // noinspection PointlessBooleanExpression
                if(contAfastaPassaroDaColisao <= 40 && passaroVoando == false){
                    contAfastaPassaroDaColisao++;
                    passaro.afastaPassaroDaColisao();
                } else {
                    passaroMachucado = false;
                    touchInGame = true;
                    diminuiNumeroDeColisoes = true;
                    passaroVoando = true;
                    contAfastaPassaroDaColisao = 0;
                }
            }
        }
    }

    private void gameOver(Canvas canvas) {
        if(numeroDeVidas < 1) {
            fimDeJogo = true;
            passaroMachucado = true;
            touchInGame = false;
            passaroVoando = false;
            caindoMorto = true;
            if(passaro.chegouNoChaoEMorreu()) {
                finalizaJogo();
                desenhaElementosNoCanvas();
                desenhaBotaoReiniciar(canvas);
                new GameOver(tela, context).desenhaNo(canvas); //FIM DO JOGO
            }
        }
    }

    private void passaroPula() {
        if (inGame && touchInGame && !inPause) {
            pulando = true;
            som.tocaSom(Som.somPULO);
            passaro.zeraPulo();
            passaro.pula();
            numeroDePulosDiminuiBarraVerde++;
            numeroDePulosColocaAlimentoNaTela++;
        }
    }

    private void escolheSomDeMachudaco() {
        if(valorAleatorio() % 2 == 0) som.tocaSom(Som.somMACHUCADO1);
        else som.tocaSom(Som.somMACHUCADO);
    }

    private int valorAleatorio() {
        double valor = Math.random() * 10;
        return (int) valor;
    }

    public void inicializaJogo() { isRunning = true; }

    public void finalizaJogo() { isRunning = false; }

    private void reiniciaJogo() {
        MainActivity activity = (MainActivity) context;
        activity.reiniciarJogo();
    }

    public Som getSom() { return som; }

//    public Som getSomVeiculos() { return somVeiculos; }

    // INFORMAÇÕES E DADOS DO APP ESCRITOS NA TELA PARA DESENVOLVIMENTO DO JOGO
    public void infoDeTelaParaDesenvolvimentoDoJogo(Canvas canvas) {
        tamanhoDoTextoInfo = tela.getAltura() /32;
        int valor =  + (int) (tela.getAltura() / 8.727272727);

        // MARCA POSIÇÃO CLICADA NA TELA
        canvas.drawText("._.... ", (float) toqueHorizontal, (float) toqueVertical, Formatacao.getTextoPRETO(tamanhoDoTextoInfo));

        // CABEÇALHOS DE INFORMAÇÃO
        canvas.drawText("Largura x Altura " + String.valueOf(tela.getLargura()) + " | " + String.valueOf(tela.getAltura()),
                tela.getLargura() /48, (int) (tela.getAltura() /32.0) + valor,
                Formatacao.getTextoPRETO(tamanhoDoTextoInfo));

        canvas.drawText("(w) " + String.valueOf(toqueHorizontal),
                tela.getLargura() /48, (int) (tela.getAltura() /16.0) + valor,
                Formatacao.getTextoPRETO(tamanhoDoTextoInfo));

        canvas.drawText("(h) " + String.valueOf(toqueVertical),
                tela.getLargura() /48, (int) (tela.getAltura() /10.66) + valor,
                Formatacao.getTextoPRETO(tamanhoDoTextoInfo));

//        canvas.drawText("ContadorRun " + String.valueOf(contadorRun),
//                tela.getLargura() /48, (int) (tela.getAltura() /8.0) + valor,
//                Formatacao.getTextoPRETO(tamanhoDoTextoInfo));

//        canvas.drawText("TamanhoPadraoCano " + String.valueOf(Cano.TAMANHO_PADRAO_DOS_CANOS),
//                tela.getLargura() /48, (int) (tela.getAltura() /6.4) + valor,
//                Formatacao.getTextoPRETO(tamanhoDoTextoInfo)); //125
//
//        canvas.drawText("TamanhoCanoSuperior " + String.valueOf(Cano.tamanhoVariavelDoCanoSuperior),
//                tela.getLargura() /48, (int) (tela.getAltura() /5.3) + valor,
//                Formatacao.getTextoPRETO(tamanhoDoTextoInfo)); //150
//
//        canvas.drawText("TamanhoCanoInferior " + String.valueOf(Cano.tamanhoVariavelDoCanoInferior),
//                tela.getLargura() / 48, (int) (tela.getAltura() / 4.57) + valor,
//                Formatacao.getTextoPRETO(tamanhoDoTextoInfo)); //175
    }
}
package jssl.brpt.ads.hitjumperrun.elements;

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

import jssl.brpt.ads.hitjumperrun.R;
import jssl.brpt.ads.hitjumperrun.graphics.Tela;

public class FundoAzulESol {
    private Context context; //extends - getResources()
    private Tela tela;

    private Bitmap sol;
    private Bitmap fundoAzul;

    private float fundoAzulFloatLeft;
    private float fundoAzulFloatTop;
    private int larguraFundoAzul;
    private int alturaFundoAzul;

    private float solFloatLeft;
    private float solFloatTop;
    private int larguraDoSol;
    private int alturaDoSol;
    private int contMoveSol;
    private boolean solDesce;
    private boolean solSobe;

    public FundoAzulESol(Context context, Tela tela) {
        this.context = context;
        this.tela = tela;
        inicializa();
    }

    private void inicializa() {
        fundoAzulFloatLeft = 0;
        fundoAzulFloatTop = 0;
        larguraFundoAzul = tela.getLargura();
        alturaFundoAzul = tela.getAltura();

        larguraDoSol = (int) (tela.getLargura() / 5.4);
        alturaDoSol = (int) (tela.getAltura() / 9.6);
        solFloatLeft = (float) (0 - larguraDoSol);
        solFloatTop = (float) tela.getAltura() / 192; // 9.6);

        solDesce = true;
        solSobe = false;

        contMoveSol = 0;

        bitmap();
    }

    private void bitmap() {
        Bitmap bitmapFundoAzul = BitmapFactory.decodeResource(context.getResources(), R.drawable.fundoazul);
        fundoAzul = Bitmap.createScaledBitmap(bitmapFundoAzul, larguraFundoAzul, alturaFundoAzul, false);

        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.imagemsol);
        sol = Bitmap.createScaledBitmap(bitmap, larguraDoSol, alturaDoSol, false);
    }

    public void desenhaNo(Canvas canvas) {
        canvas.drawBitmap(fundoAzul, fundoAzulFloatLeft, fundoAzulFloatTop, null);
        canvas.drawBitmap(sol, solFloatLeft, solFloatTop, null);
    }

    public void moveSol() {
        contMoveSol ++;
        solFloatLeft += (float) (tela.getLargura() / 2160.0);
        if(solDesce) {
            if (contMoveSol > 2) {
                solFloatTop += (float) (tela.getAltura() / 3840.0);
                contMoveSol = 0;
            }
            if(solFloatLeft > tela.getLargura()) {
                solFloatLeft = (float) (0 - larguraDoSol);
                solDesce = false; solSobe = true;
            }
        }

        if(solSobe) {
            if (contMoveSol > 2) {
                solFloatTop -= (float) (tela.getAltura() / 3840.0);
                contMoveSol = 0;
            }
            if(solFloatLeft > tela.getLargura()) {
                solFloatLeft = (float) (0 - larguraDoSol);
                solDesce = true; solSobe = false;
            }
        }
    }
}

Na sua classe Game, em vez de fazer isso:

 public Game(Context context) {
        //...
        holder = getHolder();
        //...
    }

Tente chamar o getHolder somente aqui:

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

           //...     
      }
}
solução!

Olá. Já havia encontrado o erro.

A área do botão "reiniciar" ficava ativa antes de o botão aparecer na tela quando ocorria a última colisão em função do trecho de código abaixo. Qdo essa área era clicada sem intenção o reinício era forçado ainda com isRuning = true.

Defeito corrigido. Obrigado.

private void gameOver(Canvas canvas) {
        if(numeroDeVidas < 1) {
            fimDeJogo = true;