Foco da Matéria: Introduzir o conceito de classes em JavaScript para organizar o código do jogo. Em vez de usar variáveis globais e funções dispersas, criaremos classes (Bird, Pipe) que encapsulam suas próprias propriedades e métodos, tornando o código mais limpo e escalável.
1. 💡 Por Que Usar Classes?
À medida que o jogo cresce, o arquivo game.js se torna difícil de gerenciar. A Programação Orientada a Objetos (POO), através do uso de classes, nos permite:
- Reutilização de Código: Criar vários inimigos (tubos) a partir de um único molde.
- Encapsulamento: Manter as propriedades de um objeto (ex:
velocidadeYdo pássaro) dentro do próprio objeto, sem poluir o escopo global.
2. 🐦 Criando a Classe Bird
Vamos refatorar a lógica de movimento e pulo do Tema 3 para dentro de uma classe.
Atualize o game.js (Substitua as variáveis de estado e a função pular pelo seguinte):
JavaScript
// VARIÁVEIS DE ESTADO: Moveremos o 'birdY' e 'velocidadeY' para a classe
// --- CLASSE PÁSSARO ---
class Bird {
constructor(elementId, initialY) {
this.element = document.getElementById(elementId);
this.y = initialY; // Posição vertical
this.velocity = 0; // Velocidade vertical
}
// Método que aplica gravidade e atualiza a posição
applyPhysics() {
this.velocity += GRAVIDADE;
this.y += this.velocity;
// Limita a posição Y (evita que vá para o infinito)
if (this.y < 0) {
this.y = 0;
this.velocity = 0;
}
// Atualiza o DOM
this.element.style.top = this.y + 'px';
}
// Método de pulo
jump() {
if (isGameRunning) {
this.velocity = FORCA_PULO;
}
}
}
// Inicializa a instância do pássaro
const geekBird = new Bird('geek-bird', 200);
// Substitua a chamada do listener:
document.addEventListener('click', () => geekBird.jump());
document.addEventListener('keydown', (e) => {
if (e.code === 'Space') {
geekBird.jump();
}
});
3. ♻️ Refatorando o gameLoop e gameOver
Agora, precisamos atualizar as funções do jogo para usar o novo objeto geekBird em vez das variáveis globais birdY e velocidadeY.
Atualize as funções startGame, gameLoop e gameOver em game.js:
JavaScript
// --- FUNÇÕES DE CONTROLE (Atualizadas) ---
function startGame() {
isGameRunning = true;
score = 0;
scoreDisplay.textContent = `Pontuação: 0`;
// Reseta o pássaro usando o método da classe
geekBird.y = 200;
geekBird.velocity = 0;
// ... (Limpa tubos antigos e inicia pipeInterval) ...
requestAnimationFrame(gameLoop);
}
function gameLoop() {
if (!isGameRunning) return;
// 1. APLICAR FÍSICA NO PÁSSARO (Usando o método da classe)
geekBird.applyPhysics();
// 2. CHECAR COLISÃO COM O CHÃO/TETO (Usando geekBird.y)
const birdHeight = geekBird.element.offsetHeight; // Altura do elemento
if (geekBird.y > containerHeight - birdHeight - groundHeight) {
geekBird.y = containerHeight - birdHeight - groundHeight;
geekBird.velocity = 0;
gameOver();
}
// 3. MOVER TUBOS E CHECAR COLISÃO (Ajustar para usar geekBird.y e element)
// ... (A lógica de movimentação e colisão permanece a mesma, mas usando geekBird.element e geekBird.y para as checagens)
// ... (restante do código) ...
requestAnimationFrame(gameLoop);
}
// A classe Pipe também poderia ser criada, mas para este jogo simples, refatorar apenas o Bird já demonstra o princípio.
Com essa refatoração, o código está mais limpo, mais fácil de ler e mais preparado para receber novos elementos (como vidas extras ou power-ups) sem causar confusão nas variáveis globais.
Deixe um comentárioVocê precisa entrar para publicar um comentário.