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!