No description
Find a file
2026-08-01 09:26:31 +02:00
src feat: create first mvp 2026-08-01 09:26:31 +02:00
tests feat: create first mvp 2026-08-01 09:26:31 +02:00
.gitignore feat: create first mvp 2026-08-01 09:26:31 +02:00
Cargo.toml feat: create first mvp 2026-08-01 09:26:31 +02:00
LICENSE Initial commit 2026-08-01 07:25:35 +00:00
README.md feat: create first mvp 2026-08-01 09:26:31 +02:00

PoC1: Mapa Isométrico com 12 Áreas

Objetivo

Demonstrar um mapa isométrico com 12 áreas distintas (1 overworld 200×200 + 3 cidades subterrâneas + 8 cavernas), com transição automática entre áreas por proximidade a escadas.

Como rodar

cargo run -p poc1

Controles

  • WASD ou Setas: mover o player 1 tile por tap (snap-to-grid, 16px). Segurar a tecla continua andando: primeiro passo imediato, depois auto-repeat (delay inicial 250ms, repetição a cada 120ms). Movimento tile-a-tile com lookahead para bloqueio por paredes (inclusive pedras e árvores do Overworld) e clamp para AreaBounds da área atual.
  • Proximidade a StairsDown: transita para a área subterrânea alvo (exit-zone: player precisa sair da zona de proximidade de 32px de todas as stairs antes de poder trocar novamente; player teleportado para spawn da área destino).
  • Proximidade a StairsUp: transita de volta ao Overworld (exit-zone + teleport para spawn).

O que aparece na tela

  • Overworld: mapa 200×200 tiles com 3 cidades (16×16, 32×32, 48×48), 8 entradas de caverna, caminhos conectando cidades, ~90 decorações (árvores, pedras, arbustos). Pedras e árvores (tons cinza-pedra e verde-arbusto) bloqueiam o movimento como paredes; grama e terra são só cosméticas.
  • Cidades subterrâneas: 3 áreas (Small 16×16, Medium 32×32, Large 48×48) com floor tiles, paredes no perímetro, 1 StairsUp no centro.
  • Cavernas: 8 áreas 12×12 isoladas, cada uma com floor tiles, paredes, 1 StairsUp no centro.
  • Player: quadrado verde, spawn perto da escada da Medium City (tile 83,83 — 3 tiles na diagonal da StairsDown, fora da exit-zone de 32px). Renderiza em z=10 (PLAYER_Z), sempre em primeiro plano sobre chão, muros, bordas e escadas.
  • StairsDown: quadrado laranja 16×16 (visível no Overworld, perto de cidades/cavernas).
  • StairsUp: quadrado amarelo 16×16 (visível nas áreas subterrâneas).

HUD de Área

No canto superior-esquerdo, um label Text2d mostra o nome do AppState atual (ex: "Overworld", "CitySmallUnder", "Cave1Under"). Atualiza automaticamente quando o player troca de área.

Background Tint por Área

Um sprite fullscreen muda de cor conforme a categoria da área:

  • Overworld: cinza escuro neutro (0.15, 0.15, 0.12)
  • Cidades: azul escuro médio (0.08, 0.10, 0.20)
  • Cavernas: roxo escuro (0.12, 0.06, 0.18)

Flash de Transição

Ao mudar de área, um flash overlay cobre a tela por 0.3s:

  • Overworld: flash amarelo quente
  • Cidades: flash azul
  • Cavernas: flash roxo

Arquitetura

poc1/
  src/
    main.rs         -- entry point, plugin registration, system wiring
    lib.rs          -- exports modules for integration tests
    state.rs        -- AppState enum (12 variants)
    world_layout.rs -- WORLD_LAYOUT: 3 cities, 8 caves, 2 paths, ~90 decorations
    area_spawn.rs   -- spawn/despawn systems for each area (OnEnter/OnExit)
    entities.rs     -- Player, StairsDown, StairsUp, City, Cave, Wall, etc.
    movement.rs     -- WASD + grid snapping (16px) + wall lookahead
    collision.rs    -- AreaBounds resource + tile_collision_check (clamp)
    swap.rs         -- swap_layer_on_proximity + exit-zone + teleport
    camera.rs       -- MainCamera marker + follow_player_camera
    visuals.rs      -- placeholder sprites (player, stairs)
    hud.rs          -- HUD label, transition flash, background tint
  tests/
    integration_headless.rs -- 4 headless E2E tests (no GPU required)

AppState (state.rs)

Enum com 12 variantes:

  • Overworld (default)
  • CitySmallUnder, CityMediumUnder, CityLargeUnder
  • Cave1Under .. Cave8Under

Cada variante tem seu próprio sistema OnEnter que spawna a área e injeta AreaBounds.

WorldLayout (world_layout.rs)

LazyLock<WorldLayout> com:

  • Overworld 200×200 tiles
  • 3 cidades: Small (16×16), Medium (32×32), Large (48×48)
  • 8 cavernas: 12×12 cada, entradas distribuídas pelo overworld
  • 2 caminhos conectando cidades
  • ~90 decorações (determinísticas, sem RNG)

AreaBounds (collision.rs)

Resource injetado por cada sistema OnEnter com os bounds (min, max) em tile coords da área atual. O sistema tile_collision_check clampa o player para esses bounds.

Câmera (camera.rs)

MainCamera marker component. Sistema follow_player_camera copia a posição XY do player para a câmera a cada frame, preservando o Z da câmera.

Detalhes técnicos

  • Grid: 200×200 tiles (overworld), cada tile com 16px
  • Transição: usa State<AppState> do Bevy, sem loading screen
  • Colisão: AreaBounds resource + Wall marker query, sem plugin de física
  • Sem LDtk: todas as entidades são spawnadas por sistemas Rust (bevy_ecs_ldtk removido)

Contratos com outros PoCs

  • Fornece a base de mapa isométrico reusada por poc6 (quest system) e poc7 (minigame state transition)
  • AppState é exportado via lib.rs para uso por outros crates do workspace

Testes

59 testes passando:

  • 59 testes unitários inline (collision, movement, swap, hud, visuals, camera, area_spawn, world_layout)
  • 4 testes de integração headless (app startup, stairs transitions, camera follow)

Rodar testes:

cargo test -p poc1

Status

  • Roda sem panic
  • 12 áreas funcionais com spawn/despawn automático
  • Transições Overworld ↔ Underground funcionais por proximidade
  • 8 cavernas isoladas (sem conexões cross-cave)
  • Câmera segue player por todo o mapa 200×200
  • 63 testes passando (59 unitários + 4 integração headless)
  • Movimento tile-a-tile com snap-to-grid, lookahead para bloqueio por paredes, e clamp para AreaBounds