🎲 P01: Guia Passo a Passo - Dados RPG (D20 Clássico)

Bem-vindo à sua primeira grande missão como desenvolvedor Android! 🚀 Neste projeto de entrada da Fase 1: Fundamentos Legados, vamos construir um Simulador de Dados D20 Clássico.

Se você já jogou RPG de mesa, sabe que o D20 é o dado que decide o seu destino. Aqui, ele vai decidir se o seu código é um sucesso crítico! Você aprenderá as bases mais importantes da plataforma Android: desenhar telas com arquivos XML e controlá-las com a linguagem Java.


✅ Pré-requisitos

Antes de começar, certifique-se de já ter estudado:


🎯 Objetivo do Projeto

Criar um app imersivo com uma interface escurecida de Dungeon Master. Ao clicar no botão vermelho “Lançar Sorte”, o app sorteia um número de 1 a 20 e atualiza o marcador central instantaneamente.

graph TD
    A[Início / App Aberto] --> B[Clique no Botão 'Lançar Sorte']
    B --> C[Executar Ação de Clique]
    C --> D[Gerar Número Aleatório de 1 a 20]
    D --> E[Converter Número para Texto]
    E --> F[Atualizar TextView com setText]
    F --> G[Fim / Esperando Próximo Clique]

📖 Dicionário do Projeto


🛠️ Passo 1: Configurando o Projeto no Android Studio

Antes de codar, precisamos preparar o terreno:

  1. Abra o Android Studio e clique em New Project.
  2. Escolha o template Empty Views Activity (Cuidado: não escolha o “Empty Activity” puro, pois ele usa Compose).
  3. Configure os dados do seu app:
    • Name: Dados RPG
    • Package Name: br.com.curso.dadosrpg
    • Language: Java (O clássico).
    • Minimum SDK: API 21 (Android 5.0) ou superior.
  4. Clique em Finish e aguarde o Gradle carregar o projeto completamente.

💡 Este projeto já inclui um .gitignore de exemplo — copie-o para a raiz do seu projeto antes do primeiro commit (veja a seção “Como Entregar seus Projetos” no índice da trilha).


🎨 Passo 2: Desenhando a Interface (XML)

No Android, o desenho da tela fica em arquivos XML. Desenharemos uma mesa imersiva de RPG com fundo preto e luzes em tons de vermelho neon.

  1. No painel esquerdo do Android Studio, vá em app > src > main > res > layout > activity_main.xml.
  2. Clique na aba Code (no topo superior direito) para ver o código de texto.
  3. Apague o código inicial e cole esta estrutura:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#121212"
    android:padding="24dp">

    <!-- Decoração de Fundo (Simulando Neon) -->
    <View
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:background="@android:drawable/screen_background_dark_transparent"
        android:alpha="0.1" />

    <!-- Título do Jogo -->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="40dp"
        android:text="DUNGEON MASTER"
        android:textColor="#FF4444"
        android:textSize="14sp"
        android:letterSpacing="0.3"
        android:textStyle="bold" />

    <!-- Container Centralizado do Dado -->
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:orientation="vertical">

        <!-- Mostrador do Resultado -->
        <TextView
            android:id="@+id/txt_resultado"
            android:layout_width="180dp"
            android:layout_height="180dp"
            android:background="@android:drawable/editbox_background_normal"
            android:backgroundTint="#1E1E1E"
            android:gravity="center"
            android:text="20"
            android:textColor="#FFFFFF"
            android:textSize="90sp"
            android:textStyle="bold" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="RESULTADO DO D20"
            android:textColor="#666666"
            android:textSize="12sp" />
    </LinearLayout>

    <!-- Botão de Ação Alinhado ao Rodapé -->
    <Button
        android:id="@+id/btn_rolar"
        android:layout_width="match_parent"
        android:layout_height="65dp"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="20dp"
        android:backgroundTint="#FF1C1C"
        android:text="LANÇAR SORTE"
        android:textColor="#FFFFFF"
        android:textSize="18sp"
        android:textStyle="bold" />

</RelativeLayout>

🧠 Passo 3: Programando a Lógica de Sorteio (Java)

Agora que a planta física está pronta, vamos ligar a energia no código Java!

  1. Abra o arquivo MainActivity.java localizado em app > src > main > java > br.com.curso.dadosrpg > MainActivity.java.
  2. Substitua o conteúdo pelo código dinâmico:
package br.com.curso.dadosrpg;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.util.Random;

public class MainActivity extends AppCompatActivity {

    // 1. Declaramos as variáveis que representarão nossos componentes visuais
    private TextView txtResultado;
    private Button btnRolar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main); // Faz a ligação com o XML

        // 2. Fazemos a ponte: O Java localiza os componentes na tela usando os IDs
        txtResultado = findViewById(R.id.txt_resultado);
        btnRolar = findViewById(R.id.btn_rolar);

        // 3. Programamos a ação ao clicar no botão
        btnRolar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                rolarDado(); // Chama a nossa função de sorteio
            }
        });
    }

    /**
     * Sorteia um número de 1 a 20 e atualiza a tela
     */
    private void rolarDado() {
        // 4. Cria um gerador de números aleatórios
        Random gerador = new Random();

        // 5. Sorteia um número de 0 a 19 e soma 1 (resultado final: 1 a 20)
        int numero = gerador.nextInt(20) + 1;

        // 6. Atualiza o texto na tela
        // Importante: setText sempre precisa de Texto (String), por isso o String.valueOf
        txtResultado.setText(String.valueOf(numero));
    }
}

🛠️ Requisitos Críticos de Configuração

1. Suporte ao AndroidX (Evita travamentos de build)

Certifique-se de que o arquivo gradle.properties na raiz do seu projeto possui estas flags essenciais de compatibilidade ativas:

android.useAndroidX=true
android.enableJetifier=true

2. Unidades de Medida corretas no XML (Sem ponto decimal)

Diferente da programação convencional, medidas de dimensões no Android no XML não toleram números flutuantes:


📸 Resultado Esperado

Veja como sua tela deve ficar ao final deste projeto:

App Dados RPG exibindo uma Falha Crítica (D20 = 1)


🏆 Desafios para você (Upgrade!)

Se você terminou de programar a mecânica base do jogo e tudo está funcionando, experimente estes upgrades:


📖 Gabarito Oficial de Código (Para Conferência)

Use os códigos completos abaixo para validar sua implementação ou corrigir problemas de compilação.

📄 Layout Completo (activity_main.xml)

Disponível em: app/src/main/res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#121212"
    android:padding="24dp">

    <!-- Decoração de Fundo (Simulando Neon) -->
    <View
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:background="@android:drawable/screen_background_dark_transparent"
        android:alpha="0.1" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="40dp"
        android:text="DUNGEON MASTER"
        android:textColor="#FF4444"
        android:textSize="14sp"
        android:letterSpacing="0.3"
        android:textStyle="bold" />

    <!-- Container do Dado -->
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:orientation="vertical">

        <TextView
            android:id="@+id/txt_resultado"
            android:layout_width="180dp"
            android:layout_height="180dp"
            android:background="@android:drawable/editbox_background_normal"
            android:backgroundTint="#1E1E1E"
            android:gravity="center"
            android:text="20"
            android:textColor="#FFFFFF"
            android:textSize="90sp"
            android:textStyle="bold" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="RESULTADO DO D20"
            android:textColor="#666666"
            android:textSize="12sp" />
    </LinearLayout>

    <!-- Botão Estilizado -->
    <Button
        android:id="@+id/btn_rolar"
        android:layout_width="match_parent"
        android:layout_height="65dp"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="20dp"
        android:backgroundTint="#FF1C1C"
        android:text="LANÇAR SORTE"
        android:textColor="#FFFFFF"
        android:textSize="18sp"
        android:textStyle="bold" />

</RelativeLayout>

📄 Lógica Java Completa (MainActivity.java)

Disponível em: app/src/main/java/br/com/curso/dadosrpg/MainActivity.java

package br.com.curso.dadosrpg;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.util.Random;

public class MainActivity extends AppCompatActivity {

    // Componentes da Interface
    private TextView txtResultado;
    private Button btnRolar;

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

        // Ligando o Java ao XML (IDs)
        txtResultado = findViewById(R.id.txt_resultado);
        btnRolar = findViewById(R.id.btn_rolar);

        // Ação de Clique do Botão
        btnRolar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                rolarDado();
            }
        });
    }

    /**
     * Sorteia um número de 1 a 20 e atualiza a tela
     */
    private void rolarDado() {
        // Gerador de números aleatórios
        Random gerador = new Random();

        // Sorteia de 0 a 19 e soma 1 (para ficar de 1 a 20)
        int numero = gerador.nextInt(20) + 1;

        // Mostra o número no TextView (convertendo int para String)
        txtResultado.setText(String.valueOf(numero));
    }
}