Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

unfortunately MyApplication has stopped // Jogos com Android I: Desenvolvimento de jogos 2D

Infelizmente não estou conseguindo identificar onde ocorre o erro, se alguém puder ajudar

o ERRO É unfortunately MyApplication has stopped

SEGUE O CÓDIGO

CLASSE MAIN

package br.com.forca.jogos.jogodaforca;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import java.util.Random;


//public class Main extends AppCompatActivity {
public class Main extends ActionBarActivity {

    private Button btJogar;
    private Button btPlay;
    private EditText etLetra;
    private ForcaView forcaView;
    private ForcaController forcaController;

    private String[] palavra = new String[] {"alura", "caelum"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btJogar = (Button) findViewById(R.id.btJogar);
        btPlay = (Button) findViewById(R.id.btPlay);
        etLetra = (EditText) findViewById(R.id.etLetra);
        forcaView = (ForcaView) findViewById(R.id.fvJogo);

        init();


    }

    private void init() {

        btPlay.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                int qntItensNoArrayPalavras = palavra.length;
                int qntItem = qntItensNoArrayPalavras;

                    /*    nota: palavra.length
                retorna a quantidade de itens no array, neste caso do "arry palavra"
                        */

                ForcaController forcaControle;
                forcaControle = new ForcaController(palavra[new Random().nextInt(qntItem)]);
                /* forcaControle é uma instancia de ForcaController()
                sendo que é passado "palavra[new Random().nextInt(qntItem)]"
                ou seja, ...
                é passado uma palavra
                que esta contida em nosso array de palava
                esta que será passada, é definida a passagem de forma aleatória
                 */
                setForcaController(forcaControle);

                forcaView.setForcaController(getForcaController());
                etLetra.getText().clear();
                etLetra.setEnabled(true);
                btJogar.setEnabled(true);
                btPlay.setEnabled(false);
            }
        });

        btJogar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (etLetra.getText().toString().trim().length()==0) {

                    return;
                } else {

                    getForcaController().Joga(etLetra.getText().toString().trim().charAt(0));

                    forcaView.invalidate(); /* faz com que a nossa forcaview seja REDEZENHADA */
                    etLetra.getText().clear();

                    if (getForcaController().isTerminou()) {

                        btJogar.setEnabled(false);
                        btPlay.setEnabled(true);

                        String mensagem = "Terminou o Jogo :  ";

                        if (getForcaController().isMorreu()) {

                            mensagem = mensagem + " E você PERDEU!!!";

                        } else {

                            if (getForcaController().isGanhou()) {

                                mensagem = "Parabéns! você GANHOU a partida.";
                            }

                        }

                        Toast.makeText(getApplication(), mensagem, Toast.LENGTH_LONG);



                    }

                }
            }
        });


    }

    public ForcaController getForcaController() {
        return forcaController;
    }

    public void setForcaController(ForcaController forcaController) {
        this.forcaController = forcaController;
    }
}

CLASSE FORCA VIEW

package br.com.forca.jogos.jogodaforca;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;

/**
 * Created by fabio on 21/01/2016.
 */
public class ForcaView extends PlanoCartesianoView {



    private enum Membro {braco, perna}
    private enum Lado {direito, esquerdo}

    private Path pathForca;  // responsavel por desenhar TODAS AS FIGURAS GEOMETRICAS
    private Paint paintForca;

    private ForcaController forcaController;

    public ForcaView(Context context) {
        super(context);
    }

    public ForcaView(Context context, AttributeSet attrs, Canvas canvas) {
        super(context, attrs);

        setPathForca(new Path()); /* criando uma Instancia de Path() */
        /* passando como parãmetro para o método setPathForca(new Path()) */

        // onDraw(canvas);

    }

    private void plotaArmacaoDaForca() {

        /* base da Forca, onde: x,y são as coordenadas informadas abaixo respectivamente */
        getPathForca().moveTo(toPixel(1), toPixel(10));
        getPathForca().lineTo(toPixel(3), toPixel(10));

        //canvas.drawPath(getPathForca(), getPaintForca());

        /* Lateral da Forca, onde: x,y são as coordenadas informadas abaixo respectivamente */
        getPathForca().moveTo(toPixel(2), toPixel(10));
        getPathForca().lineTo(toPixel(2), toPixel(1));

         /* Barra Superior da Forca, onde: x,y são as coordenadas informadas abaixo respectivamente */
        getPathForca().rLineTo(toPixel(5), 0); //getPathForca().moveTo(toPixel(2), toPixel(1));
        //getPathForca().lineTo(toPixel(8), toPixel(1));

        /* finalizando a ESTRUTURA DA FORCA */
        getPathForca().rLineTo(0, toPixel(2));


    }


    private void plotaCabeca() {
        /* constroi a CABEÇA do boneco da forca */
        getPathForca().addCircle(toPixel(7), toPixel(3), toPixel(1), Path.Direction.CW);
    }


    private void plotaCorpo() {
        /* constroi o CORPO */
        getPathForca().moveTo(toPixel(7), toPixel(4));
        getPathForca().lineTo(toPixel(7), toPixel(7));
    }

    private void plotaMembro(Membro membro, Lado lado) {

        final int posicaoDoCorpo = 7; /* posição do corpo no Eixo X */
        final int alturaDoBraco = 5; /* em relação ao corpo no Eixo Y */
        final int alturaDaPerna = 7; /* em relação ao corpo no Eixo Y */

        int alturaFinal;

        if (membro == Membro.braco) {

            getPathForca().moveTo(toPixel(posicaoDoCorpo), toPixel(alturaDoBraco));
            alturaFinal = alturaDoBraco + 1;
        } else {

            getPathForca().moveTo(toPixel(posicaoDoCorpo), toPixel(alturaDaPerna));
            alturaFinal = alturaDaPerna + 1;

        }

        if (lado == Lado.direito) {

            getPathForca().lineTo(toPixel(posicaoDoCorpo + 1), toPixel(alturaFinal));

        } else {

            getPathForca().lineTo(toPixel(posicaoDoCorpo - 1), toPixel(alturaFinal));

        }


    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        plotaArmacaoDaForca();
        plotaCabeca();
        plotaCorpo();

        plotaMembro(Membro.braco, Lado.direito);
        plotaMembro(Membro.braco, Lado.esquerdo);
        plotaMembro(Membro.perna, Lado.direito);
        plotaMembro(Membro.perna, Lado.esquerdo);

        drawLetrasCorretas(canvas);

        plotaTracos();

        /* executa o método "Canvas", ou seja pinta os desenhos */
        canvas.drawPath(getPathForca(), getPaintForca());

    }



    public Path getPathForca() {
        return pathForca;
    }

    public void setPathForca(Path pathForca) {
        this.pathForca = pathForca;
    }

    public Paint getPaintForca() {

        this.paintForca = new Paint(); /* 1a Etapa - Inicializa a variavel "paintForca" */


        this.paintForca.setColor(Color.BLUE);
        this.paintForca.setStyle(Paint.Style.STROKE);
        this.paintForca.setStrokeWidth(8);

        return this.paintForca;
    }

    private Paint getPaintTraco() {
        Paint paint = new Paint();
        paint.setColor(Color.BLACK);
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeWidth(2);
        paint.setTextSize(25);

        return paint;
    }

    private void drawLetrasCorretas (Canvas canvas) {

        int eixoX = toPixel(3);
        getPathForca().moveTo(eixoX + 10, toPixel(10));
        eixoX += 35;
        if (getForcaController()==null) {    return;  }

        int limiteLoop = getForcaController().getPalavraAteAgora().length() -1;
        for (int i=0; i<= limiteLoop; i++) {
            char c = getForcaController().getPalavraAteAgora().charAt(i);
            int pontX = eixoX + ((toPixel(1) + 10) * i);
            int pontY = toPixel(10) - 15;
            //canvas.drawText(c+"", pontX, pontY, new Paint());
            canvas.drawText(c+"", pontX, pontY, getPaintTraco());
        }
    }

    private void plotaTracos() {

        int eixoX = toPixel(3);
        getPathForca().moveTo(eixoX+10, toPixel(10) );

        if (getForcaController()==null) {    return;  }

        int limiteLoop = getForcaController().getPalavraAteAgora().length() -1;
        for (int i=0; i<= limiteLoop; i++) {

            getPathForca().rMoveTo(10,0);
            getPathForca().rLineTo(toPixel(1),0);

                    /*
            char c = getForcaController().getPalavraAteAgora().charAt(i);
            int pontX = eixoX + ((toPixel(1) + 10) * i);
            int pontY = toPixel(10) - 15;
            //canvas.drawText(c+"", pontX, pontY, new Paint());
            canvas.drawText(c+"", pontX, pontY, getPaintTraco());
            */


        }
    }

    public ForcaController getForcaController() {
        return forcaController;
    }

    public void setForcaController(ForcaController forcaController) {
        this.forcaController = forcaController;
    }
}

CLASSE PlanoCartesianoView

package br.com.forca.jogos.jogodaforca;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by fabio on 21/01/2016.
 */
public class PlanoCartesianoView extends View {


    /* GUARDA A REFERÊNCIA DO MENOR LADO DO DISPLAY,
    SE O MENOR FOR O VERTICAL, então vai ATRIBUIR A INFORMAÇÃO DA VERTICAL
    SE O MENOR LADO FOR O HORIZONTAL, então vai ATRIBUIR o valor correspondente HORIZONTAL
     */
    private int menorLadoDisplay;
    private int unidade; /* receberá o valor do lado do DISPLAY menor, dividido por 10 */

    /* Unidade, porque estamos trabalhando com PROPORÇÕES esta é a ideia
    ou seja, unidades proporcionais da tela, quando tentar desenhar.
     */




    /* ---------------------------------------------------  gets e Seters */
    public int getUnidade() {
        return unidade;
    }

    public void setUnidade(int unidade) {
        this.unidade = unidade;
    }

    public int getMenorLadoDisplay() {
        return menorLadoDisplay;
    }

    public void setMenorLadoDisplay(int menorLadoDisplay) {
        this.menorLadoDisplay = menorLadoDisplay;
    }
/* ---------------------------------------------------  gets e Seters */

    public PlanoCartesianoView(Context context) {
        super(context);
    }

    public PlanoCartesianoView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int Largura = getWidth(); /* em relação ao DISPLAY */
        int altura = getHeight(); // DO RESPECTIVO DISPOSITIVO

        if (Largura < altura) {
            setMenorLadoDisplay(Largura);
        } else {
            setMenorLadoDisplay(altura);
        }

        setUnidade(getMenorLadoDisplay() / 10);

        drawPlanocartesiano(canvas);

    }


    public void drawPlanocartesiano(Canvas canvas){

        Path path = new Path();
        /* a ideia é definir
        todos os caminhos que desejamos desenhar, uma LINHA, RETANGULO, UM CIRCULO
        SEJA O QUE FOR... (TUDO QUE DESEJAMOS DESENHAR ESTARÁ NO "path"
         */

        int max = toPixel(10);
        for (int n=0;n<=10;n++){
            //desenhando as LINHAS VERTICAIS
            path.moveTo(toPixel(n),1);
            path.lineTo(toPixel(n),max);
            //desenhando as LINHAS HORIZONTAIS
            path.moveTo(1,toPixel(n));
            path.lineTo(max,toPixel(n));

        }

        Paint paint = new Paint();


        paint.setAntiAlias(true); // determina a suavidade das linhas
        paint.setColor(Color.BLACK);
        paint.setStyle(Paint.Style.STROKE); // sem preenchimento INTERNO (DO DEZENHO) apenas bordas
        paint.setStrokeWidth(1); // a espesura fina das linhas...

        canvas.drawPath(path, paint);

    }

    public int toPixel(int vlrPixelPoint) {
        return vlrPixelPoint * getUnidade();
    }


}

CLASSE ForcaController

package br.com.forca.jogos.jogodaforca;

import java.util.HashSet;
import java.util.Set;

/**
 * Created by fabio on 24/01/2016.
 */
public class ForcaController {private String palavraParaAdivinhar; // palavra que deverá ser adivinhada

    private Set<Character> letrasUsadas; // Lista de Letras Digitados sem caracteres repetidos

    private int qntErros = -1;

    public ForcaController(String palavra) {

        this.letrasUsadas = new HashSet<Character>();
        this.palavraParaAdivinhar = palavra;
    }

    public int getQntErros() {
        return qntErros;
    }

    public void Joga(Character letra) {

        /* caso o Set já contenha letra (já foi digitada anteriormente) sair da função */
        if (letrasUsadas.contains(letra)) {

            return;

        } else {
            letrasUsadas.add(letra);
            if (palavraParaAdivinhar.contains(letra.toString())) {

                return;

            } else {
                qntErros++;
            }
        }

    }

    public String getPalavraAteAgora() {

        String visualizacao = "";

        /* a ideia é constuir um Loop, que vai rodar em cima do array de caracteres
        onde c corresponderá ao caracter corrente em relação a "palavraParaAdivinhar"
        ou seja vai variar, conforme o loop, e a palavra toda será verificada letra a letra
         */
        for (char c : palavraParaAdivinhar.toCharArray()) {

            if (letrasUsadas.contains(c)) {// existe a correspondente Letra na palavra

                visualizacao += c;

            } else {

                visualizacao += "";

            }
            /* ou seja, recebe o valor atualizando a posição conforme a palavra
            sendo acertada, recebe "C" na corrente posição ou " "
             quando a letra não existe na corrente posição.
             */
        }




        return visualizacao;

    }

    public boolean isMorreu() {

        return (getQntErros()==5);

    }

    public boolean isGanhou() {

        return (getPalavraAteAgora().contains(" "));

    }

    public boolean isTerminou() {

        return (isGanhou() || isMorreu());

    }

}

E O ARQUIVO XML

1 resposta
solução!

O erro esta na classe ForcaView

alias, no construtor, basta remover o ,Canvas canvas do metódo construtor da classe:

public ForcaView(Context context, AttributeSet attrs, Canvas canvas)

veja o método abaixo, e remova o Canvas, como informado assim

public ForcaView(Context context, AttributeSet attrs, Canvas canvas) {
        super(context, attrs);

        setPathForca(new Path()); /* criando uma Instancia de Path() */
        /* passando como parãmetro para o método setPathForca(new Path()) */

        // onDraw(canvas);

    }