Skip to content

ActionRPG UI e Portali

Alessandro Bria edited this page Sep 29, 2026 · 4 revisions

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 e inventario

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.

DialogBox e menu

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.

Portali: dalla collisione al teletrasporto

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.

Maschera circolare e costo

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.

Sorgenti

Torna alla panoramica di ActionRPG oppure confronta l'uso dello stack con CustomPlatformer.

Clone this wiki locally