2 Arquitetura
Caio Simioni edited this page 2026-10-11 21:32:09 -03:00

Arquitetura

Rust + Bevy 0.20 (ECS). Workspace com um núcleo reutilizável (ADR-009).

Camadas

┌──────────────────────────────────────────────┐
│ crates/survivors   (o JOGO)                  │
│  tunables · mapa · modelos · sons · regras   │
├──────────────────────────────────────────────┤
│ crates/shooter_core (REUTILIZÁVEL)           │
│  FPS · armas · dano · raio/colisão · IA ·    │
│  rounds · loja · HUD                         │
├──────────────────────────────────────────────┤
│ Bevy 0.20                                    │
└──────────────────────────────────────────────┘

Regras: shooter_core não importa nada de survivors; conteúdo chega por dados (WeaponDef, EnemyDef, RoundCurve, ShopCatalog, ModelDef) e por componentes/mensagens de extensão. Novo jogo = novo crate que depende de shooter_core e fornece seus dados + mapa.

Plugins

Plugin Crate Responsabilidade
ShooterCorePlugin core Agrega os abaixo
FpsControllerPlugin core Entrada, mouse look, movimento, câmera, cursor travado
WeaponsPlugin core Inventário, disparo hitscan/melee, recarga, viewmodel
CombatPlugin core Vida, dano, cabeça/corpo, morte, mensagens de dano
ShooterAiPlugin core Perseguição, linha de visada, distância preferida, rajadas
RoundsPlugin core Máquina de rounds, fila de spawn, intermissão
ShopPlugin core Balcões, interação, compra
HudPlugin core Retícula, vida, munição, pontos, indicador de dano
SurvivorsGamePlugin jogo Tunables, mapa, porta, armaria, modelos, sons, estados do app

Estados

AppState:   Loading → Menu → InGame → GameOver → (Menu | InGame)
RoundState (SubState de InGame):   Intermission → Active → Cleared → Intermission …
Pause:      Time<Virtual> pausado + overlay

Componentes principais

Componente Em Descrição
Player / FpsCamera jogador marcador / câmera filha
Health { hp, max } jogador, hostil vida
HitVolumes { body, head } hostil cápsula do corpo e esfera da cabeça
Collider(Cylinder) móveis colisão no plano XZ
StaticBox { min, max } paredes, caixas, contêineres, balcões AABB 3D (bloqueia movimento e tiro)
ShooterAi { preferred_range, burst, … } hostil comportamento de atirador
WeaponInventory jogador slots, arma ativa, munição
Points(u32) jogador pontos
ShopCounter { item, price } balcão item à venda
Door { state } porta Fechada/Abrindo/Aberta/Fechando

Mensagens

FireWeapon · Hit { target, part, amount, source, from_dir } · EntityDied · Purchase · RoundCleared · SpawnEnemy.

Colisão, tiro e linha de visada (sem engine de física — ADR-003)

  • Movimento: cilindro no plano XZ vs StaticBox → empurrar para fora pela normal (deslizamento). Sem gravidade (arena plana).
  • Raio (hitscan): raio 3D vs AABBs (método slab) para o mapa; vs cápsula/esfera para inimigos e jogador. Vale o primeiro impacto; cabeça > corpo.
  • Linha de visada da IA: mesmo raio, do olho do inimigo ao olho do jogador; bloqueado por StaticBox.
  • Separação de inimigos: grid espacial (células de 2 m) + repulsão.
  • Melee: alvos dentro de 1,9 m e do cone frontal (±55°).

Ordem de sistemas (Update)

input → look → move → collide → weapon_fire/reload → ai_sense → ai_act → hit_apply → rounds → hud

Desempenho

  • Orçamento: ≤ 16 inimigos, personagem ≤ 2 000 tris, arma ≤ 500 tris (viewmodel ≤ 1 500), 1 material por modelo.
  • Raios por frame: ≤ 16 (IA) + tiros do jogador — trivial; medir antes de otimizar.
  • Profile dev com opt-level = 1 e dependências em opt-level = 3.

Estrutura de pastas (alvo do M1)

Cargo.toml                (workspace)
crates/
  shooter_core/           (biblioteca reutilizável)
    src/{fps, weapons, combat, ai, rounds, shop, hud, raycast, collision}.rs
  survivors/              (o jogo)
    src/{main, game, map, tunables}.rs
    assets/{models, audio}