Game Loops🔗

Definição curta: O game loop é o ciclo infinito de processamento que mantém um jogo rodando — tipicamente: process input → update game state → render output → repeat (~60 vezes por segundo). É o heartbeat de todo videogame.

Antes de começar

  • Nenhum — esta seção é o ponto de entrada do guia

O que você vai aprender

  • Explicar Estrutura básica do loop com suas palavras
  • Explicar Update vs Render separation com suas palavras
  • Explicar Frame rate e Delta Time com suas palavras
  • Aplicar o conteúdo desta página a um jogo que você conhece

O que é🔗

O game loop é a estrutura de controle central de qualquer jogo. Diferente de programas normais que executam e terminam, jogos executam continuamente até o jogador sair ou o jogo terminar.

A formulação clássica é:

enquanto jogo rodando:
    processar_input()
    atualizar_estado()
    renderizar()
flowchart LR
    subgraph Loop["Game Loop (60fps tipicamente)"]
        I["Input\n(teclado, mouse,\ngamepad)"]
        U["Update\n(lógica, física,\nIA, estado)"]
        R["Render\n(graphics,\nudio, haptics)"]
    end

    I --> U --> R --> I

Índice de sub-tópicos🔗

Estrutura básica do loop🔗

Versão simples🔗

while (jogo_esta_rodando) {
    processar_input();
    atualizar_jogo();
    renderizar();
}

Versão com timing controlado🔗

float lastTime = getCurrentTime();
while (jogo_esta_rodando) {
    float currentTime = getCurrentTime();
    float deltaTime = currentTime - lastTime;
    lastTime = currentTime;

    processar_input();
    atualizar_jogo(deltaTime);
    renderizar();
}

Update vs Render separation🔗

Em engines modernas, update e render rodam em frequências diferentes:

FrequênciaUpdate (lógica)Render (visual)
Tipicamente60 Hz fixoVariável (vsync)
RazãoConsistência de físicaMax visual smoothness

Isso evita problemas de física em monitores 144Hz vs 60Hz.

Frame rate e Delta Time🔗

Delta time (dt) é o tempo desde o último frame:

  • dt curto = jogo está rodando bem
  • dt longo = frame drop (jogo lentou)

Usar dt em cálculos de movimento:

// ❌ Errado: velocidade depende do frame rate
posicao.x += velocidade;

// ✅ Correto: velocidade consistente independent de frame rate
posicao.x += velocidade * deltaTime;

Estados de jogo🔗

Jogos tipicamente têm estados (game states):

stateDiagram-v2
    [*] --> Menu: Start
    Menu --> Playing: Play
    Playing --> Paused: ESC
    Paused --> Playing: Resume
    Playing --> [*]: Quit
    Playing --> GameOver: Lose
    Playing --> Victory: Win
    GameOver --> Menu: Restart
    Victory --> Menu: Continue

Estados comuns:

  • Menu — tela inicial
  • Playing — gameplay ativo
  • Paused — jogo congelado
  • GameOver — derrota
  • Victory — vitória
  • Loading — carregamento

Fixed vs Variable timestep🔗

Variable timestep (simples)🔗

while (true) {
    float dt = getDeltaTime();
    update(dt);
    render();
}

Problema: física inconsistente se dt variar muito.

Fixed timestep (robusto)🔗

float accumulator = 0;
float fixed_dt = 1.0f / 60.0f;  // 60 Hz fixo

while (true) {
    float dt = getDeltaTime();
    accumulator += dt;

    while (accumulator >= fixed_dt) {
        fixed_update(fixed_dt);  // Update fixo
        accumulator -= fixed_dt;
    }

    render(accumulator / fixed_dt);  // Interpolação
}

Recomendado para jogos com física — garante que a física roda no mesmo ritmo independente do frame rate.

Exemplo: game loop simples🔗

import time

class GameLoop:
    def __init__(self):
        self.running = False
        self.last_time = time.time()

    def process_input(self):
        # Process keyboard, mouse, gamepad
        pass

    def update(self, dt):
        # Update physics, AI, game logic
        pass

    def render(self):
        # Draw to screen
        pass

    def run(self):
        self.running = True
        while self.running:
            current_time = time.time()
            dt = current_time - self.last_time
            self.last_time = current_time

            self.process_input()
            self.update(dt)
            self.render()

            # Cap framerate (opcional)
            time.sleep(1/60 - dt)

Veja também🔗

Erros comuns

  • Multiplicar tudo por delta time e achar que resolveu. Resolve movimento linear. Não resolve física com colisão, nem acumulação de juros, nem nada que dependa de ordem de eventos.
  • Deixar a lógica presa ao render. É o que faz o jogo rodar mais rápido em máquina melhor. Separar os dois relógios é o conserto.
  • Fixar o passo e ignorar a espiral da morte. Se um passo demora mais que o passo, o loop acumula dívida e nunca alcança. Precisa de teto.

Você aprendeu

  • Estrutura básica do loop
  • Update vs Render separation
  • Frame rate e Delta Time
  • Estados de jogo
  • Fixed vs Variable timestep

Perguntas para reflexão

  1. O que Estrutura básica do loop resolve, e o que se perde sem isso?
  2. O que Update vs Render separation resolve, e o que se perde sem isso?
  3. O que Frame rate e Delta Time resolve, e o que se perde sem isso?
  4. Que parte desta página você conseguiria explicar a alguém que nunca fez um jogo?

Artigos relacionados

Referências🔗