O Navistron implementa toda a sua física com cálculos vetoriais em JavaScript puro, sem nenhuma biblioteca de física externa. Cada entidade — nave, tiros, mísseis, meteoros, boosts, partículas e debris — tem seu próprio modelo de movimento baseado em integração de Euler (posição += velocidade × dt). Neste artigo, vamos destrinchar cada sistema físico do jogo com os valores exatos extraídos do código-fonte.
Movimento da Nave: Lerp Exponencial Frame-Rate Independent
A nave do Navistron não se teleporta para a posição do cursor — ela usa um sistema de interpolação exponencial que cria movimento suave e responsivo independente da taxa de quadros. A constante SHIP_LERP = 12 controla a velocidade de convergência.
A cada frame, o engine calcula a posição-alvo (posição do cursor clampeada dentro da tela) e aplica a fórmula: fator = 1 - e^(-12 × dt). Depois, desloca a nave em (alvo - posição_atual) × fator. A 60 FPS (dt ≈ 0.0167s), o fator é ~0.181, ou seja, a nave percorre ~18% da distância restante a cada frame. A 30 FPS (dt ≈ 0.033s), o fator sobe para ~0.329 — a nave percorre mais por frame mas chega no mesmo lugar, garantindo comportamento idêntico independente do FPS.
A posição-alvo é clampeada para manter a nave dentro da tela: X limitado entre metade da largura da nave (18px) e 522px, Y entre 24px e 706px. A nave nasce na posição (270, 630) — centralizada horizontalmente, próxima da parte inferior do canvas. Em dispositivos touch, um offset vertical de -140px é aplicado para que a nave fique acima do dedo, permitindo visibilidade.
Note que não existe velocidade ou aceleração explícita da nave — a velocidade é emergente do fator de lerp e da distância ao cursor. Movimentos longos são rápidos; ajustes finos são suaves.
Projéteis: Velocidade Fixa com Spread Angular por Nível
Os tiros do Navistron viajam a uma velocidade fixa de 520 px/s em linha reta, sem gravidade ou arrasto. A direção é determinada pelo nível de spread do jogador, que controla quantos projéteis disparam simultaneamente e o ângulo entre eles.
O sistema de spread usa ângulos em graus definidos por nível: nível 1 = 0° (tiro reto para cima), nível 2 = 12° entre tiros, nível 3 = 9°, nível 4 = 6°, nível 5 = 5°. Para níveis acima de 5, a fórmula é max(4, 14 - nível × 2) graus. Os tiros são distribuídos simetricamente: o ângulo total é (nível - 1) × graus_por_nível, e cada tiro é posicionado a partir de -total/2 com incrementos iguais.
A velocidade é decomposta em componentes: vx = sin(ângulo) × 520 e vy = -cos(ângulo) × 520 (negativo porque Y cresce para baixo no canvas). Cada tiro tem vida útil de 1.6 segundos e é removido quando a vida expira ou quando sai dos limites da tela (20px de margem lateral, 40px acima).
O dano por tiro varia conforme o tier atual: 1, 2, 4, 7, 12, 20 e 35 nos tiers I a VII. O raio visual do tiro também cresce: 4, 5, 6, 7, 8, 10 e 12 pixels. A cadência de tiro (tempo entre disparos) diminui de 0.18s no Tier I até 0.06s no Tier VII — quase 17 tiros por segundo.
Mísseis Teleguiados: Homing com Taxa de Giro
A partir de dificuldade 2.0, o Navistron adiciona mísseis teleguiados ao arsenal do jogador. O sistema de guiamento é um dos subsistemas mais sofisticados do jogo, com aquisição de alvo, perseguição angular e re-aquisição automática.
Os mísseis viajam a 320 px/s (constante MISSILE_SPEED) com uma taxa de giro máxima de 5.5 rad/s (MISSILE_TURN) e vida útil de 2.0 segundos (MISSILE_LIFE). A quantidade por salva é min(5, max(0, floor(dificuldade) - 1)), ou seja, 1 míssil na dificuldade 2, crescendo até 5 mísseis simultâneos em dificuldades altas. O cooldown entre salvas é max(0.35s, 2.0 - (quantidade - 1) × 0.25), atingindo o mínimo de 0.35 segundos.
O algoritmo de guiamento funciona assim: a cada frame, o míssil verifica se seu alvo atual ainda está vivo e na tela. Se o alvo morreu ou saiu (y > 840), o míssil re-adquire o alvo mais próximo por distância Euclidiana ao quadrado. Tendo um alvo válido, calcula o ângulo desejado via atan2, mede a diferença angular (normalizada para -π a +π), e aplica um giro de no máximo 5.5 × dt radianos naquele frame. A velocidade é então recalculada no novo ângulo, mantendo magnitude constante de 320 px/s.
Cada míssil mantém uma trilha visual de até 12 posições anteriores (FIFO), criando o rastro luminoso que acompanha a curva do míssil.
Meteoros: Velocidade Escalável com Rotação Contínua
Os meteoros do Navistron seguem física simples: velocidade constante sem aceleração, com rotação contínua para efeito visual. A velocidade vertical base é 60–120 px/s para meteoros grandes e 90–200 px/s para pequenos, multiplicada por um fator de dificuldade que pode chegar a 3.8×.
A velocidade horizontal é menor: limitada a 35% da velocidade vertical ou 40 + dificuldade × 10 pixels/s, o que for menor. Isso mantém os meteoros com trajetória predominantemente descendente, com desvio lateral sutil que aumenta com a dificuldade.
A rotação de cada meteoro é aleatória: (random - 0.5) × (2 + dificuldade × 0.25) rad/s, ou seja, velocidade angular que vai de -1 a +1 rad/s na dificuldade 1 até -2.75 a +2.75 rad/s em dificuldades extremas. A rotação é puramente visual — aplicada via ângulo += rotação × dt a cada frame, sem afetar a detecção de colisão.
Os meteoros são removidos quando passam 120px abaixo da tela (y > 840). Quando atingidos, perdem HP igual ao dano do projétil, e ao chegar a zero HP, explodem gerando partículas e pontos.
Boosts: Queda Linear com Coleta por Proximidade
Os itens de boost têm a física mais simples do jogo: queda vertical a velocidade constante de 55–90 px/s, sem movimento horizontal ou aceleração. Spawnam a y = -20 (acima da tela) em posição X aleatória entre 30 e 510 pixels, com raio de 14px.
A coleta usa detecção circle-circle com o raio do boost (14px) versus um raio de pickup de 24px na nave — significativamente maior que o hitbox de colisão da nave com meteoros (18px). Isso torna a coleta mais generosa, recompensando o jogador que se aproxima sem exigir precisão pixel-perfect.
Os boosts aparecem a cada 12–20 segundos, com o primeiro spawning após 8 segundos de jogo. Visualmente, possuem uma animação de pulso (1 + sin(pulso) × 0.4) que faz o brilho oscilar entre 60% e 140% da intensidade normal.
Debris: Gravidade Simulada com Trilhas
Quando a nave é destruída, 12 fragmentos de debris são criados com física significativamente mais complexa que qualquer outra entidade. Cada fragmento tem:
- Velocidade inicial: 40–200 px/s em direção aleatória, com bias de -20 px/s no eixo Y (impulso para cima)
- Gravidade individual: cada peça recebe 60–100 px/s² de aceleração para baixo (aplicada como
vy += gravidade × dt) - Rotação: velocidade angular de -6 a +6 rad/s (
(random - 0.5) × 12) - Raio: 3–10 pixels
- Vida: 1.5–3.0 segundos
A combinação de impulso inicial para cima com gravidade para baixo cria o efeito clássico de arco parabólico: os fragmentos sobem brevemente e depois caem, exatamente como estilhaços de uma explosão real sob gravidade. Com gravidades individuais aleatórias (60–100 px/s²), cada pedaço segue um arco diferente, criando dispersão natural.
Cada debris mantém uma trilha de até 8 posições anteriores, cada uma com vida de 0.3 segundos. As trilhas criam rastros luminosos nas cores da nave (#a8d8ff, #4488cc, #223355, #7df4ff, #ff6622, #ff3300), reforçando o impacto visual da destruição.
Partículas de Explosão: Inércia Pura sem Forças
As partículas de explosão seguem o modelo de física mais simples possível: velocidade constante sem nenhuma força. Uma vez criadas, viajam em linha reta pela velocidade inicial até a vida expirar. Não há gravidade, arrasto ou qualquer desaceleração — a partícula mantém sua velocidade vetorial do momento da explosão.
O efeito de "desvanecimento" é puramente visual: o alpha é calculado como min(vida/vidaMaxima, 1) e o raio renderizado diminui como raio × alpha, fazendo a partícula parecer encolher e desaparecer. Combinado com o shadowBlur = 8 para efeito de brilho, isso cria explosões convincentes sem cálculos de física caros.
A explosão de morte da nave gera 60 partículas (velocidade 30–310 px/s, vida 0.6–1.8s), seguida por 3 explosões secundárias de 54 partículas cada. No pico, podem haver 200+ partículas voando simultaneamente, todas processadas com simples x += vx × dt; y += vy × dt.
Invencibilidade e Feedback Visual
Ao nascer, a nave recebe 2 segundos de invencibilidade. Durante esse período, a verificação de colisão nave–meteoro é simplesmente ignorada: o código checa ship.invincible <= 0 antes de executar circleDist(). O timer é decrementado por dt a cada frame.
O feedback visual é um efeito de piscar: a função de desenho da nave retorna imediatamente (sem desenhar nada) quando Math.floor(invincível × 10) % 2 === 0. Isso alterna a visibilidade a cada 0.1 segundo, criando o clássico efeito de invencibilidade de jogos arcade.
Shockwave: Expansão Radial com Anéis Concêntricos
A onda de choque da morte expande de 0 a 180 pixels de raio em 0.8 segundos, seguindo progresso linear (progresso = tempo_decorrido / 0.8). Dois anéis concêntricos são desenhados: o externo no raio completo (largura de linha 11→3px) e o interno a 70% do raio (largura 5→1px).
O alpha decai como (1 - progresso) × 0.6, garantindo que a onda começa visível e desaparece ao atingir o tamanho máximo. A cor é rgba(125, 244, 255) (ciano brilhante) com shadowBlur = 20 para o efeito de brilho característico. Simultaneamente, um flash branco cobre a tela inteira por 0.15 segundos com alpha decrescente de 0.5 a 0.
Integração de Euler e Limites de Tela
Toda a física do Navistron usa integração de Euler explícita: posição += velocidade × dt, e para debris: velocidade += aceleração × dt. É o método mais simples de integração numérica — não há Verlet, RK4, ou qualquer método de ordem superior. Para um jogo arcade com timesteps pequenos (capeado a 50ms), Euler é perfeitamente adequado e muito mais rápido.
Cada tipo de entidade tem margens de remoção diferentes fora da tela: tiros usam 20px lateral e 40px vertical, mísseis usam 40px e 60px, meteoros 120px abaixo, boosts 60px abaixo. Margens maiores para entidades que podem voltar (mísseis curvando) e menores para entidades lineares (tiros). As estrelas são a única entidade que faz wrapping — reaparecem no topo ao sair por baixo.
FAQ — Perguntas Frequentes sobre a Física do Navistron
Os debris da nave têm gravidade real?
Sim. Cada um dos 12 fragmentos recebe uma aceleração gravitacional individual de 60–100 px/s² para baixo, aplicada como vy += gravidade × dt. Com impulso inicial para cima (-20 px/s), os debris descrevem arcos parabólicos realistas. A gravidade varia por peça para criar dispersão natural.
Por que a nave não tem velocidade máxima definida?
A nave usa lerp exponencial em vez de velocidade fixa. A velocidade é emergente: quanto mais longe o cursor, mais rápido a nave se move. Ela percorre ~18% da distância restante a cada frame (a 60 FPS), então movimentos longos são rápidos e ajustes finos são suaves. A constante SHIP_LERP = 12 controla essa convergência.
Como funciona o sistema de guiamento dos mísseis?
Os mísseis adquirem o meteoro mais próximo como alvo. A cada frame, calculam o ângulo desejado via atan2 e giram no máximo 5.5 rad/s em direção a ele, mantendo velocidade constante de 320 px/s. Se o alvo é destruído, re-adquirem automaticamente o próximo mais próximo.
As partículas de explosão sofrem influência da gravidade?
Não. Partículas de explosão têm inércia pura — velocidade constante sem nenhuma força aplicada. Apenas os debris (fragmentos sólidos da nave) sofrem gravidade. Partículas viajam em linha reta até sua vida expirar, com efeito de desvanecimento puramente visual (alpha e raio decrescentes).
Qual é a diferença entre o hitbox de colisão e o hitbox de coleta?
A nave tem hitboxes diferentes para situações diferentes: 18px de raio para colisão com meteoros (usando fator 0.72 no raio do meteoro), e 24px de raio para coleta de boosts — 33% maior, tornando a coleta mais generosa que o dano.
