Colisoes Fisica - aula de fisica colisões - elastica-inelastica | PDF
aula de fisica colisões - elastica-inelastica | PDF

A verdade sobre detecção de colisão que ninguém conta em tutoriais

A maioria dos tutoriais online começa explicando o que é colisoes fisica e mostra um cubo quicando em um plano. É útil para entender o conceito, mas na prática você vai enfrentar problemas muito mais chatos do que isso. Vou tentar cobrir o que realmente importa.

A fundação:Broad Phase antes de qualquer coisa

Você precisa separar a detecção em duas etapas. A broad phase filtra quais pares de objetos precisam ser verificados. A narrow phase faz o cálculo real de interseção. Pular a broad phase é o erro mais comum que vejo em projetos novos. Testar todos contra todos escala linearmente mal. Se você tem 100 objetos dinâmicos, isso são 4.950 pares potenciais a verificar a cada quadro. Em um jogo com 500 objetos, já são 124.750 pares. O número sobe rápido demais. O que eu uso na prática é um grid espacial simples. Você divide a cena em células de tamanho fixo, digamos 64x64 pixels. Cada objeto só precisa ser verificado contra objetos nas mesmas células ou nas adjacentes. Para uma cena típica de plataforma 2D com uns 80 inimigos, Sprites e partículas, isso reduz de milhares de pares para algo em torno de 300 a 800. A diferença é absurda.

Narrow Phase: o que funciona de verdade

Circle-circle é trivial. AABB-AABB é quase tão rápido. O problema começa quando você precisa lidar com polígonos convexos arbitrários. O algoritmo que todo mundo deveria conhecer é o GJK (Gilbert-Johnson-Keerthi). Ele calcula distância mínima e interseção entre convexos usando simplex, sem precisar de decomposição. Para colisão está contra estático, SAT (Separating Axis Theorem) ainda é mais simples de implementar e suficiente para a maior parte dos casos. Polígonos convexos com até 8 vértices rodam no SAT sem dor de cabeça significativa. Aqui vai algo contraintuitivo: SAT não funciona para concavos. Não existe mágica. Você precisa dividir o polígono côncavo em convexos antes. Convex decomposition é um problema resolvido, mas ainda demanda tempo de processamento. Ferramentas como BCOLLO ou V-HACD fazem isso offline, salvando o resultado em uma malha pré-processada. NUNCA faça convex decomposition em runtime para colliders que mudam frequentemente, a menos que você tenha um problema muito específico que exija isso. O overhead não vale a pena na grande maioria dos casos.

O problema que eu enfrentei na prática

Eu estava construindo um simulador top-down onde os projéteis viajavam rápido o suficiente para tunelar através de paredes em frames específicos. A detecção discreta simplesmente pedia o objeto entre dois frames porque a velocidade era alta. O que funcionou foi implementar CCD (Continuous Collision Detection) baseado em swept SDF para círculos e rays cast para formas complexas. Para círculos, o cálculo é direto: você estima o tempo de impacto dentro do frame atual usando a velocidade relativa e o tempo de chegada mais próximo entre os dois objetos. Para polígonos, eu uso um raycast contra cada aresta da forma estática, e verifico qual aresta é atingida primeiro dentro do delta de tempo do frame. Isso adiciona custo, sim, mas em torno de 2 a 4 microssegundos por objeto em vez de 0.1 microssegundos do método discreto. Para um jogo com 30 projéteis na tela, o ganho em precisão compensa largamente o custo adicional. Outro detalhe importante: o CCD puro por si só não resolve o problema de jitter quando objetos ficam presos em superfícies irregulares. Você precisa combinar CCD com um sistema de resolução de constraint que aplicasse correções suaves ao invés de empurrões brutais. Positivo, o movimento ficou estável. Negativo, a curva de aprendizado para acertar os parâmetros de correção foi longa.

👉 Clique no botão abaixo para saber mais sobre o assunto!

Sub-stepping e a armadilha da estabilidade

Um dos maiores erros de quem tá começando com física é usar apenas um passo de simulação por frame. O problema é que o motor de física faz uma única integração, resolve restrições uma vez, e pronto. Se algo colide no meio desse intervalo, o sistema não percebe. Sub-stepping significa rodar a simulação física N vezes por frame com deltas menores. Dois sub-steps geralmente resolvem 90% dos problemas de jitter e passagem. Três a quatro são o padrão ouro para simulações mais exigentes. O custo é linear com o número de passos, então não adianta colocar 10 passos só porque quer. A prática é usar 2 a 3 passos como baseline e aumentar se necessário. Existem engines que fazem isso automaticamente. Box2D tem o b2World::Step que aceita um timeStep e um numSubSteps. Matter.js também. Se você está escrevendo seu próprio motor, ter isso disponível desde o início poupa muito tempo depois.

Quando colisoes fisica simplesmente não funciona bem

Deixa eu ser honesto aqui. Métodos baseados em volume implícito e SDF são incríveis para certos cenários, mas têm limitações sérias. Eles não lidam bem com objetos extremamente finos ou bordas afiadas, pois a discretização do campo perde esses detalhes. Além disso, SDFs são estáticos por definição — se o cenário muda dinamicamente, o custo de reconstruir o campo a cada frame pode ser proibitivo. Para jogos de plataformas 2D clássicos, isso raramente é um problema porque os tiles são fixos. Para jogos onde o terreno é escavado, não conte com SDF como solução única. Para simulações de corpos macios ou tecidos, métodos de elementos finitos ou Verlet integration são mais adequados do que qualquer detector de colisão padrão. E para fluidos, bem, é outro universo completamente separado.

O que eu recomendo se você tá começando agora

Não reescreva um motor de física do zero. Isso é trabalho de meses ou anos, e os resultados raramente competem com soluções maduras. Use Box2D para 2D ou Bullet/PhysX para 3D. Se o projeto é simples e rápido, Matter.js é uma opção válida. Aí, com a base funcionando, é que você começa a personalizar comportamentos específicos, adicionar otimizações e ajustar parâmetros para o seu caso. Se precisar de um ponto de partida concreto para Box2D em JavaScript, a biblioteca disponível em https://github.com/nicktomlin/box2d.js é uma fork recente do box2d-web original, com manutenção ativa e documentação aceitável. Para Unity, o PhysX nativo já vem pronto. Para Godot, o PhysicsServer 2D/3D também embute o que você precisa. A escolha da ferramenta correta economiza semanas de trabalho.

Erros que eu vejo todo dia

Definir restituição acima de 0.8 para objetos grandes que colidem a altas velocidades quase sempre gera instabilidade numérica. A energia do sistema explode. Limite a restituição em 0.5 ou menos para colisões pesadas e use damping para controlar a energia residual. Outro erro comum: esquecer de colocar um collider estático no chão e nos limites da cena. Sem colisores de contenção, seus objetos simplesmente caem para o infinito e você gasta horas investigando bugs que na verdade são configuração mal feita. E por fim, verifique se o seu fixed timestep está consistente com o frame rate. Se o jogo roda a 60fps mas o fixed timestep está configurado para 30fps, a simulação vai pular estados e as colisões vão ficar irregulares. Configure fixed timestep para algo como 1/60s ou 1/120s e deixe o render loop rodar independentemente. Isso evita que a física dependa de variações de FPS.