Um guia prático para simular força e gravidade em projetos de física
A maioria dos tutoriais que você vê na internet trata força e gravidade como se fossem dois conceitos separados que se encontram apenas nas fórmulas. Na prática, quando você vai implementar isso num projeto real, logo descobre que o problema nunca é a teoria. O problema é que o motor de simulação não consegue lidar com colisões em sequência quando a gravidade está escalada acima de 20m/s² sem um timestep fixo. Trabalho com simulações físicas há bastante tempo e já vi gente inteira perder dias porque ignorou essa questão. Vou explicar como fazer isso funcionar sem perder a cabeça.
O que realmente acontece com força e gravidade num motor de simulação
Força é vetor. Gravidade é, tecnicamente, uma aceleração constante aplicada a todos os corpos com massa. A maioria dos desenvolvedores novatos aplica a gravidade diretamente como uma força, e aí entra o primeiro erro. Se o seu objeto tem massa 5 e você aplica F = m × g, a gravidade vai variar conforme a massa do objeto, o que pode ser desejável ou não dependendo do seu caso. No meu primeiro projeto sério de simulação, eu queria que todos os objetos caíssem com a mesma aceleração independente da massa. Apliquei a gravidade como força em vez de aceleração pura. O resultado foi que objetos pesados caíam mais rápido no simulador, o que na física real não acontece por causa da resistência do ar, mas num vácuo simulado claramente estava errado. A correção foi simples: aplicar aceleração diretamente ao campo velocity em vez de somar força ao campo force acumulado.
Isso parece óbvio agora, mas levei duas semanas para perceber o bug porque a simulação parecia plausível a olho nu. A diferença entre aplicar como força versus aceleração só fica evidente quando você começa a variar a massa dos objetos em cenários com gravidade alta ou timestep variável.
Implementação passo a passo
Se você está usando um motor como o Box2D, Matter.js ou customizando seu próprio integrador, o padrão geral segue estas etapas: Inicialize as propriedades básicas de cada corpo: massa, posição, velocidade e aceleração. A aceleração começa em zero a cada frame.
Aplique forças externas. Neste estágio entram forças de mola, empuxo, arrasto, vento, qualquer coisa que não seja gravidade. Some todas ao acumulador de forças do corpo. Adicione a gravidade. Aqui a decisão importante: aplique como aceleração direta ou como força. Se quer comportamento newtoniano puro (todos os corpos caem iguais), use aceleração. Se quer simular resistência do ar proporcional à massa, use força e depois divida por massa no próximo passo.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Integre o movimento. O método mais básico é Euler explícito: velocity += acceleration × dt, position += velocity × dt. Funciona para simulações simples, mas se o seu timestep for maior que 0,03 segundos, a simulação começa a ganhar energia artificial e os objetos começam a flutuar ou acelerar descontroladamente. Resolva colisões. Detecte sobreposição entre corpos e aplique impulsos de reação. Este é o passo que mais causa problemas. Colisões encadeadas — quando um objeto cai em cima de outro que está em cima de um terceiro — exigem múltiplas iterações de resolução. O Box2D usa 8 iterações de posição e 3 de velocidade por padrão, o que resolve a maioria dos casos. Abaixo disso, você vê o famoso efeito "mola" onde os objetos vibram antes de estabilizar.
Problemas comuns que ninguém conta
O primeiro problema que você vai encontrar é tunneling. Quando um objeto se move rápido o suficiente, ele pode atravessar outro objeto entre dois frames sem que a detecção de colisão registre nada. A solução padrão é usar capsule casting ou CCD (continuous collision detection), mas isso custa de 3 a 5 vezes mais processamento. Num projeto meu com 200 objetos caindo, ativar CCD para todos travou a simulação completamente. Ativei CCD apenas para os objetos com velocidade acima de 50 unidades por segundo e o problema sumiu. O segundo problema é pilhas instáveis. Enfileirar objetos uns em cima dos outros parece simples, mas a menor imprecisão numérica faz a pilha tombar. A workaround que eu uso é aplicar um tiny damping global de 0,001 a 0,005 por frame. Isso estabiliza sem parecer artificial. Também recomendo usar um solver com mais iterações de posição — 10 a 20 faz diferença enorme em pilhas altas.
O terceiro problema, que é o mais chato, é que a gravidade em motores de física muitas vezes não respeita a escala do seu mundo. Se suas unidades estão em centímetros em vez de metros, uma gravidade de 9,81 vai fazer tudo parecer que está na Lua. O Box2D foi projetado para funcionar com corpos entre 0,1 e 10 metros. Fora disso, os resultados ficam imprevisíveis. Eu já vi gente usar gravidade de 981 em simulações em centímetros e chamar de correção. Não é. É um paliativo que quebra a física em outros aspectos.
Quando não usar simulação de força e gravidade
Se o seu projeto é um jogo mobile com centenas de objetos e orçamento de 16ms por frame, simulação física completa pode não ser viável. Neste caso, considere aproximações: partículas com trajetórias parabólicas pré-calculadas para projéteis, ou um sistema de keyframe para objetos que caem em cenários previsíveis. Isso elimina completamente o custo de solve de colisões. Para animações cinemáticas onde a física é só aparente, use um rig simples com constraints. Ficou comprovado que simulações de tecidos ou correntes de cordas quase nunca precisam de solved físico em tempo real — uma animação baked com 60fps consome uma fração do processamento.
Recursos práticos
Para quem quer começar do zero, o Matter.js é a biblioteca mais acessível. Tem documentação em português, comunidade ativa e roda no browser sem compilador. O código para configurar gravidade e forças básicas leva menos de 50 linhas. Se você precisa de precisão física séria, o Box2D continua sendo o padrão da indústria. A versão C++ é a mais madura, mas existem bindings para Unity, Godot e Python. O Manuual do Box2D disponível no site oficial do Erin Catto ainda é a melhor referência técnica existente, apesar de não ter sido atualizado desde 2019.
Para simulações mais avançadas com deformação de corpos macios, o projecto Soupsim ou o plugin de soft body do Blender oferecem soluções práticas sem escrever seu próprio integrador. O mais importante é testar sempre com valores conhecidos. Se você aplicar gravidade 9,81m/s² num corpo em queda livre, após 1 segundo a velocidade deve ser exatamente 9,81m/s e a distância percorrida 4,905 metros. Se seus números não batem, o integrador ou o timestep estão errados antes de qualquer outra coisa.