🏗️ Cap 10: Arquitetura de Jogo (MVVM)
🎯 Objetivo da Aula: Ao final desta aula, você entenderá o padrão MVVM (Model-View-ViewModel). Você aprenderá a separar o “Cérebro” do seu jogo (a lógica de pontos e vida) do “Corpo” (a interface visual), usando as pastas padrão do curso.
🏢 O Cenário Prático (Seu Desafio): Até agora, você colocou toda a lógica (contas, variáveis) dentro da mesma função da tela. Isso funciona para apps pequenos, mas em um jogo grande vira uma bagunça impossível de consertar! Seu desafio é criar o Motor do Jogo (ViewModel): um local separado onde a vida do personagem é calculada, deixando a tela apenas com a função de mostrar o desenho.
🧠 Fundamentos: A Teoria Traduzida
📖 Dicionário do Programador
- View (Visão): É a tela (o Compose). Ela apenas desenha o que o Garçom traz.
- ViewModel (O Garçom): É quem manda no estado da tela. Ele faz os cálculos e avisa a tela: “Ei, mude o texto para 50 pontos!“.
- Encapsulamento: É esconder os dados sensíveis. A tela não pode mudar a vida do jogador diretamente; ela deve pedir ao Garçom para fazer isso.
🎨 O Mapa das Pastas (Revisão)
Crie estas pastas no seu projeto br.com.curso.game:
ui/screens/→ Coloque suas funções@Composableaqui.ui/viewmodel/→ Coloque suas classesViewModelaqui.
graph TD A[View: Tela do Game] <-->|Observa o Estado| B[ViewModel: Garçom da Lógica] B <-->|Gerencia| C[Model: Dados do Personagem]
📖 Exemplo Passo a Passo: O Garçom de Pontos
- Crie o arquivo
JogoViewModel.ktna pastaui/viewmodel. - Use o prefixo
_para o estado privado (ninguém de fora mexe) e uma variável pública para a tela ler.
package br.com.curso.game.ui.viewmodel
import androidx.lifecycle.ViewModel
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.State
class JogoViewModel : ViewModel() {
// 1. O dado secreto (Só o Garçom mexe)
private val _pontos = mutableStateOf(0)
// 2. O dado que a tela pode ver
val pontos: State<Int> = _pontos
// 3. A ação que muda o dado
fun ganharPonto() {
_pontos.value += 10
}
}🛠️ Prática Obrigatória 1:
Crie uma classe PersonagemViewModel. Ela deve ter um estado privado para vida (começando em 100) e uma função receberDano(). A função deve tirar 10 de vida, mas nunca deixar ficar menor que 0.
🛠️ Prática Obrigatória 2:
Crie a tela @Composable chamada ArenaScreen na pasta ui/screens. Ela deve usar o seu PersonagemViewModel para mostrar a vida atual e ter um botão “Receber Golpe”.
🔑 Gabarito Passo a Passo:
ViewModel:
class PersonagemViewModel : ViewModel() {
private var _vida = mutableStateOf(100)
val vida: State<Int> = _vida
fun receberDano() {
if (_vida.value > 0) _vida.value -= 10
}
}Screen:
@Composable
fun ArenaScreen(vm: PersonagemViewModel = viewModel()) {
Column {
Text("Vida: ${vm.vida.value}")
Button(onClick = { vm.receberDano() }) { Text("Receber Golpe") }
}
}📤 Instruções de Entrega (Microsoft Teams):
- Envie o código do seu
ViewModele da suaScreen. - Submeta no canal de tarefas.