No description
- Rust 100%
| assets/scripts | ||
| src | ||
| .gitignore | ||
| Cargo.toml | ||
| CONTRACT.md | ||
| LICENSE | ||
| README.md | ||
PoC4: Diálogo Ramificado (Yarn-style)
Objetivo
Demonstrar sistema de diálogo ramificado com parser .dialogue próprio (similar a Yarn Spinner), 2+ nós por arquivo, variáveis $flag sincronizadas com WorldState Rust, comandos custom <<set_quest>> e <<set_flag>>, UI de diálogo com texto + opções, trigger por tecla E perto do NPC.
Como rodar
cargo run -p poc4
Controles
- WASD / setas: mover o player (movimento livre contínuo, 200 px/s; travado enquanto um diálogo está aberto; bloqueado por obstáculos e limitado à área jogável — ver Colisão abaixo)
- E: abrir diálogo com NPC próximo (proximity check, raio de 50px)
- 1/2/3: escolher opção de diálogo
- ESC: fechar diálogo
O que aparece na tela
- Fundo: cinza/preto padrão do Bevy
- 2 quadrados coloridos 24×24:
- 🔵 Azul em (-250, -150) — Player (controlado por WASD/setas)
- 🟡 Amarelo em (0, 0) — NPC (Guide)
- 2 obstáculos cinza 40×40 (pedra/parede) em (-125, -75) e (150, 100) — o primeiro fica bem no caminho reto do player até o NPC
- Controles: andar até o NPC e apertar E perto dele abre o diálogo
- Diálogo: caixa de texto com fala do NPC + botões numerados [1], [2], [3] pra escolher opção. ESC fecha.
Colisão
- Player vs NPC/obstáculos: bloqueio circular (raio do player + raio do obstáculo); o player para na borda em vez de atravessar. Implementado em
collision.rs(Obstacle,is_blocked_by_obstacle), sem wall-sliding — se o passo colide, o player simplesmente não anda naquele frame. - Limites de cena:
SceneBounds(800×600 centrado na origem,-400..400×-300..300) clampa a posição do player para nunca sair da área jogável.
Fluxo principal
- Player spawna perto do NPC
- Aperta E →
DialogueRunnercarregaintro.dialogue - Player lê texto + escolhe opções
- Comando
<<set_flag player_met_npc>>modificaWorldState - Player sai → flag persiste
Arquitetura
poc4/src/main.rs— entry +init_resource::<WorldState>()poc4/src/collision.rs—Obstacle,SceneBounds, checagem circular de colisão e clamp de boundspoc4/src/dialogue.rs— structsDialogue,DialogueRunner,NpcDialogue,DialoguePluginpoc4/src/parser.rs— parser.dialoguecom suporte a nós, comandos<<...>>, escolhas-> texto => Alvopoc4/src/commands.rs—set_flag_command,set_quest_command,execute_commandpoc4/src/dialogue_ui.rs— UIbevy_uicom bolha de texto + botões de escolhapoc4/src/trigger.rs— proximity check + tecla E, spawnaDialogueRunnerpoc4/src/sync.rs— sincronização bidirecional$vars ↔ WorldStatepoc4/assets/scripts/intro.dialogue— exemplo com 5 nós, condicionais<<if>>, variáveis$player_name
Formato .dialogue
title: Start
---
<<set_flag intro_shown true>>
Texto do diálogo.
-> Opção 1 => AlvoNode
-> Opção 2 => OutroNode
---
Contratos com outros PoCs
- Consome
WorldStatede poc2 (set/get flags) - Emite comandos para poc6 (
QuestSet,FlagSetviaexecute_command) - API pública:
DialogueRunner,Dialogue(asset),NpcDialogue, comandos<<set_flag>>/<<set_quest>> - Contrato congelado em
CONTRACT.md— PoC6 não deve começar sem ele
Status
✅ Roda limpo após fix do init_resource | ✅ Player e NPC spawnados (fix da tela preta — main.rs registrava plugins mas nunca spawnava entidades) | Diálogo ramificado funcional | 5 nós no intro.dialogue | Testes unitários no parser e commands