Capítulo 19: Projeto Final - Dungeon Crawler (Parte 1) 🗡️🛡️

Chegamos à reta final do curso! Nos capítulos 19 e 20, vamos juntar tudo o que aprendemos para criar um Jogo de Dungeon Crawler (Exploração de Calabouço) baseado em texto, com o tema The Legend of Zelda, mas usando o poder e a segurança do Rust!

Nesta primeira parte, vamos planejar a estrutura usando Structs e criar o mapa do jogo.


📖 O que vamos construir?

Um jogo onde o jogador (Link) se move por uma grade (matriz), encontra uma chave e deve chegar à porta de saída para vencer! Usaremos:

  • Structs e Impl: Para representar o Jogador e o Mapa.
  • Enums: Para os itens do mapa.
  • Vetores/Matrizes: Para o cenário.

📖 Exemplo Guiado: Jogador e Mapa em Rust

Vamos criar a estrutura do Jogador e do Mapa.

  1. Crie o arquivo dungeon.rs na pasta src/:
const TAM: usize = 5; // Tamanho do mapa 5x5
 
struct Jogador {
    x: usize,
    y: usize,
    tem_chave: bool,
}
 
impl Jogador {
    fn new() -> Jogador {
        Jogador { x: 0, y: 0, tem_chave: false }
    }
 
    fn mover(&mut self, dx: i32, dy: i32) {
        // Rust não permite índices negativos, então precisamos de cuidado!
        let novo_x = self.x as i32 + dx;
        let novo_y = self.y as i32 + dy;
 
        if novo_x >= 0 && novo_x < TAM as i32 {
            self.x = novo_x as usize;
        }
        if novo_y >= 0 && novo_y < TAM as i32 {
            self.y = novo_y as usize;
        }
    }
}
 
struct Mapa {
    grade: [[i32; TAM]; TAM],
}
 
impl Mapa {
    fn new() -> Mapa {
        Mapa {
            // 0: Vazio, 2: Chave, 3: Porta
            grade: [
                [0, 0, 0, 0, 0],
                [0, 2, 0, 0, 0],
                [0, 0, 0, 0, 0],
                [0, 0, 0, 0, 0],
                [0, 0, 0, 0, 3]
            ]
        }
    }
 
    fn desenhar(&self, j: &Jogador) {
        println!("\n--- DUNGEON ---");
        for i in 0..TAM {
            for k in 0..TAM {
                if i == j.y && k == j.x {
                    print!("[L] "); // L de Link
                } else if self.grade[i][k] == 2 {
                    print!("[K] "); // K de Key (Chave)
                } else if self.grade[i][k] == 3 {
                    print!("[D] "); // D de Door (Porta)
                } else {
                    print!("[.] "); // Espaço vazio
                }
            }
            println!();
        }
    }
}
 
fn main() {
    let mut link = Jogador::new();
    let mapa = Mapa::new();
 
    mapa.desenhar(&link);
}

🕹️ Como Executar e Testar no VS Code

  1. Abra le terminal integrado.
  2. Compile: rustc dungeon.rs
  3. Execute: ./dungeon

Resultado Esperado:

--- DUNGEON ---
[L] [.] [.] [.] [.] 
[.] [K] [.] [.] [.] 
[.] [.] [.] [.] [.] 
[.] [.] [.] [.] [.] 
[.] [.] [.] [.] [D] 

📊 Ilustração Visual: Elementos do Jogo

Veja o que cada símbolo significa:

graph TD
    A["[L] = Jogador (Link)"]
    B["[K] = Chave (Key)"]
    C["[D] = Porta (Door)"]
    D["[.] = Espaço Vazio"]

🛠️ Prática Obrigatória 1: Movimento Básico

Adicione uma lógica simples na main que peça ao usuário para digitar ‘D’ (para mover para a direita). Se ele digitar, chame o método link.mover(1, 0) e desenhe o mapa novamente para ver o Link se movendo!


🔑 Gabarito de Código

Prática 1: Fragmento do código na main

    use std::io;
 
    println!("Digite D para mover para a direita: ");
    let mut comando = String::new();
    io::stdin().read_line(&mut comando).unwrap();
 
    if comando.trim() == "D" || comando.trim() == "d" {
        link.mover(1, 0);
    }
 
    mapa.desenhar(&link);

Capitulo Anterior | Proximo Capitulo