Foco da Matéria: Introduzir o motor que faz o jogo se mover (o Game Loop com requestAnimationFrame) e a função que permite ao jogador interagir (os Event Listeners).
No desenvolvimento de jogos, a mágica está no Game Loop (Laço de Jogo). É uma função que se repete centenas de vezes por segundo para calcular a física, a posição dos objetos, a colisão e atualizar o que você vê na tela.
1. ⚙️ Estrutura Inicial (JavaScript)
Vamos começar nosso arquivo game.js definindo as variáveis e obtendo as referências (o DOM) dos elementos que vamos manipular.
Crie um arquivo chamado game.js:
JavaScript
// VARIÁVEIS DE CONFIGURAÇÃO DO JOGO
const GRAVIDADE = 0.5; // Força para puxar o pássaro para baixo
const FORCA_PULO = -8; // Força para impulsionar o pássaro para cima
const VELOCIDADE_TUBO = 2; // Velocidade de movimento dos tubos
const INTERVALO_TUBO = 1500; // Tempo em ms para criar um novo tubo
// VARIÁVEIS DE ESTADO
let velocidadeY = 0; // Velocidade vertical atual do pássaro
let isGameRunning = false; // Estado do jogo
let score = 0; // Pontuação atual
let birdY = 200; // Posição Y inicial do pássaro
// REFERÊNCIAS DO DOM
const gameContainer = document.getElementById('game-container');
const geekBird = document.getElementById('geek-bird');
const scoreDisplay = document.getElementById('score');
const containerHeight = gameContainer.offsetHeight;
const birdHeight = geekBird.offsetHeight;
const groundHeight = 50; // Altura do chão definida no CSS
2. 👂 Eventos: A Interação do Jogador
A primeira forma de interação é o clique ou toque. Para o Flappy Bird, o clique (ou a barra de espaço) deve acionar um pulo. Usamos o addEventListener para capturar essa ação.
Adicione a função pular() e a chamada do listener ao seu game.js:
JavaScript
// --- FUNÇÃO DE PULO ---
function pular() {
// Apenas permite pular se o jogo estiver rodando
if (!isGameRunning) return;
// Define a velocidade vertical para a força de pulo (valor negativo = sobe)
velocidadeY = FORCA_PULO;
}
// --- ESCUTA DE EVENTOS (INTERAÇÃO DO JOGADOR) ---
// Adiciona o pulo ao clique do mouse ou barra de espaço
document.addEventListener('click', pular);
document.addEventListener('keydown', (e) => {
if (e.code === 'Space') {
pular();
}
});
3. 🔄 O Loop de Jogo (requestAnimationFrame)
O coração do jogo é a função que se repete para atualizar o estado dos elementos. Em vez de usar setInterval, que pode ter inconsistências de tempo, usamos requestAnimationFrame. Ele sincroniza a animação com a taxa de atualização do navegador (geralmente 60 vezes por segundo), resultando em movimentos mais suaves.
Adicione a função gameLoop() e o controle de início ao seu game.js:
JavaScript
// --- O MOTOR DO JOGO ---
function gameLoop() {
if (!isGameRunning) {
// Se o jogo parou (game over), interrompe o loop
return;
}
// 1. APLICAR GRAVIDADE:
// A cada frame, a velocidade Y aumenta devido à gravidade.
velocidadeY += GRAVIDADE;
// 2. ATUALIZAR POSIÇÃO DO PÁSSARO:
// A posição vertical (birdY) é ajustada pela velocidade.
birdY += velocidadeY;
// 3. MOVIMENTAR OS TUBOS E CHECAR COLISÃO (Próxima Lição)
// Aqui virá o código que move os tubos e verifica se o pássaro bateu.
// 4. CHECAR COLISÃO COM O CHÃO/TETO:
// Se o pássaro atingir o chão:
if (birdY > containerHeight - birdHeight - groundHeight) {
birdY = containerHeight - birdHeight - groundHeight; // Fixa no chão
velocidadeY = 0;
gameOver(); // O jogo acaba
}
// Se o pássaro atingir o teto:
if (birdY < 0) {
birdY = 0; // Fixa no teto
velocidadeY = 0;
}
// 5. ATUALIZAR O DOM (Visual):
// Move o pássaro para a nova posição Y calculada.
geekBird.style.top = birdY + 'px';
// 6. CONTINUAR O LOOP:
// Solicita que o navegador chame gameLoop() novamente no próximo frame.
requestAnimationFrame(gameLoop);
}
// --- FUNÇÕES DE CONTROLE ---
function startGame() {
isGameRunning = true;
score = 0;
scoreDisplay.textContent = `Pontuação: 0`;
birdY = 200; // Reseta a posição
velocidadeY = 0; // Reseta a velocidade
geekBird.style.top = birdY + 'px';
// Inicia o motor do jogo
requestAnimationFrame(gameLoop);
// (Próxima lição) Inicia a criação periódica dos tubos
}
function gameOver() {
isGameRunning = false;
alert(`Game Over! Sua pontuação final foi: ${score}`);
// Limpar tubos, mostrar tela de início, etc.
}
// Inicia o jogo automaticamente ao carregar (ou adicione um botão de Start)
startGame();
Ao executar o index.html agora, o pássaro deve cair continuamente e parar no chão. Se você clicar ou pressionar a barra de espaço, ele deve pular, combatendo a gravidade, provando que o motor do jogo e a interação do usuário estão funcionando!