Repository navigation
ActionRPG UI e Portali
ActionRPG usa lo stack del core per separare gameplay e interfaccia. Menu, HUD e dialoghi sono UIScene; il portale, invece, è un Trigger nella scena di gioco che coordina teletrasporto e shader di transizione. Qui seguiamo queste responsabilità senza confondere rendering, input e collisioni.
HUD è una UIScene singleton con coordinate 256 x 224, diversa dalla vista 16 x 14 della scena di gioco. Disegna contatori, cuori, un'icona di oggetto selezionato e una schermata di inventario collocata inizialmente sopra l'area visibile. Item rappresenta un tipo di oggetto tramite icona e label presi da SpriteFactory.
All'avvio, HUD crea una matrice 4 x 5 con tutte le 20 voci di Item::Type: è una dimostrazione grafica della selezione, non un sistema di raccolta o equipaggiamento. moveItemSelection() limita la posizione alla griglia e aggiorna cursore, icona, label e icona nell'HUD. I valori di bombe, frecce, chiavi e cuori sono inizializzati nel costruttore; i setter sostituiscono gli sprite quando cambiano.
Invio chiama HUD::inventory(true). Per circa un secondo la View dell'HUD scorre di 224 unità fino all'inventario; lo scheduler transitionOff conclude l'animazione. Durante l'apertura l'HUD diventa blocking, così la scena di gioco sotto non riceve più input e update. A inventario aperto, le frecce cambiano la selezione e Invio avvia la chiusura; al termine _blocking torna al valore precedente. È la stessa regola dello stack usata dai menu, non un sistema di pausa separato.
Una particolarità da non scambiare per una meccanica: HUD::setFPS() chiama attualmente setCoins(fps). Il numero nello slot delle monete mostra quindi gli FPS durante il gioco, sovrascrivendo il contatore iniziale.
Link::interact() può aprire il dialogo dell'NPC. DialogBox è una UIScene bloccante: applica wrapText(), crea un RenderableObject per carattere usando gli sprite di fonts.png e mostra il testo progressivamente. Clipper limita il rendering alla finestra del dialogo; quando si supera il numero di righe visibili, il testo scorre. Tenere premuta la freccia giù accelera la comparsa; la freccia destra cambia opzione e Invio conferma solo dopo la fine del testo. Nell'esempio le azioni delle opzioni stampano messaggi, senza modificare lo stato del gioco.
Il menu iniziale è bloccante; il menu di pausa offre Resume, Reset e Quit. Nel sottomenu Options, Commands e Volume sono voci dimostrative, mentre VSYNC legge e cambia davvero l'impostazione del renderer SDL. Reset chiama Game::reset(), che ricostruisce lo stack. Menu e dialogo sono scene: i loro input non devono attraversare quelli della scena di gioco quando sono bloccanti.
LevelLoader crea prima Link dalla sua regione JSON, poi un Portal per ogni geometria della categoria Portal e collega le coppie che hanno lo stesso name non vuoto (i due portali A nel file incluso). Questo campo è necessario per il collegamento; le altre regioni possono ometterlo. Portal deriva da Trigger, osserva Link e non oppone una barriera fisica. La sua logica distingue ingresso, arrivo alla destinazione e uscita, per evitare che un teletrasporto provochi subito il ritorno.
Il Trigger di base riceve un task std::function<void()> e lo esegue quando entra l'oggetto osservato. Portal specializza questa logica per programmare la transizione e gestire l'arrivo alla destinazione; il trigger generico resta indipendente dal teletrasporto.
Link entra nel Portal
-> freeze del player; setTransitionEnter(true)
-> dopo 1 s: spostamento al centro del Portal destinazione
-> setTransitionEnter(false); setTransitionExit(true)
-> dopo 1 s: fine shader; player riattivato
La posizione di arrivo usa il centro del portale di destinazione meno metà della dimensione del rettangolo di Link. Il flag _playerArrived sul portale di arrivo sopprime l'attivazione inversa finché Link non termina quel contatto. setPos() aggiorna anche l'indice spaziale; _autoKillWhenOutsideScene = false e la radice del quadtree più ampia consentono di raggiungere la casa fuori dalla mappa nominale. La pagina Quadtree spiega perché questi due confini sono distinti.
RPGGame usa GPUShaderWindow, che mantiene anche setShader() per gli effetti CPU. Durante le transizioni, RPGGameScene::update() incrementa _transitionCounter con il delta del frame, ricalcola in pixel il centro del player con View::mapFromScene() e passa a circleMaskShader() un factor che prima chiude e poi riapre la maschera. Questo update è esterno al loop fisico a _dt: la progressione visiva segue il frame corrente. Quando la transizione termina, setShader(nullptr) disattiva la maschera CPU senza rimuovere eventuali shader GPU attivi.
Gli shader CPU leggono e riscrivono i pixel del frame; durante l'effetto il costo cresce con la risoluzione della finestra. Il tasto L applica temporaneamente un altro effetto (lightShader) per prova. Gli shader GPU delle demo si attivano con 1-9 e 0 e possono convivere con queste transizioni. Per il funzionamento del post-processing, senza entrare nel dettaglio dei pixel, vedi Shader del core.
-
HUD.cpp,Item.cppeSpriteFactory.cpp -
DialogBox.cpp,NPC.cppeMenu.cpp -
Portal.cpp,Trigger.cppeRPGGameScene.cpp
Torna alla panoramica di ActionRPG oppure confronta l'uso dello stack con CustomPlatformer.
- Panoramica
- Diagramma delle classi
- Architettura e game loop
- Sequenza di un frame
- Input ed eventi
- Scene e oggetti
- Rendering e coordinate
- Sprite e testo
- UI e overlay
- Quadtree
- Servizi e asset
- Estendere il core
- Editor dei livelli
- LevelData e livelli JSON
- Shader