Repository navigation
Core Rendering
Il rendering attraversa quattro livelli distinti:
Window -> Scene -> View -> RenderableObject -> Sprite
Separarli evita che coordinate della scena, coordinate dello schermo e contenuto delle texture vengano confusi.
| Spazio | Esempio | Chi lo usa |
|---|---|---|
| Scena |
RectF di un personaggio o di una piattaforma |
Object, GameScene, collisioni |
| Finestra/renderer | posizione in pixel dopo camera e viewport | SDL, View, input del mouse |
| Texture |
RectI che seleziona un'immagine nella spritesheet |
Sprite e derivate |
pixelUnitSize specifica quanti pixel della grafica corrispondono a un'unità della scena. Non è la dimensione del viewport: quella dipende dalla finestra e dalla camera. Per esempio, un personaggio largo un'unità può usare una regione di texture larga 16 pixel, mentre sul monitor viene ingrandito in base alla View.
Window crea SDL_Window e SDL_Renderer, abilita il blending e attiva il VSync. A ogni frame:
- pulisce il renderer;
- chiede alle scene di disegnarsi nell'ordine dello stack;
- presenta il frame con
SDL_RenderPresent().
Il ridimensionamento aggiorna le dimensioni della finestra; gli eventi corrispondenti fanno ricalcolare i viewport delle scene.
Window non decide quali oggetti sono visibili: inoltra il rendering alle scene. Game::dispatchEvent() passa gli eventi di finestra a tutte le scene; Scene::event() chiede alla propria View di aggiornare il viewport. Le modalità con shader sostituiscono la classe della finestra, non l'organizzazione di scene e oggetti.
La View collega due rettangoli:
- il view rect, espresso nelle coordinate della scena;
- il viewport, espresso come porzione normalizzata della finestra.
Da questi dati calcola:
- fattore di ingrandimento;
- trasformazione scena -> schermo;
- trasformazione schermo -> scena;
- correzione dell'aspect ratio;
- area di clipping.
mapFromScene() è usato per disegnare; mapToScene() serve per trasformare mouse e input grafici nel sistema della scena.
Il view rect è la camera nella scena: spostarlo cambia la zona osservata, non la posizione degli oggetti. Il viewport è la zona della finestra in cui la camera disegna; valori normalizzati come (0, 0, 1, 1) indicano tutta la superficie. View::updateViewport() converte il viewport in pixel, applica l'eventuale aspect ratio fisso e costruisce le due trasformazioni. Se RectF::yUp è attivo, la trasformazione inverte verticalmente l'asse Y rispetto alle coordinate dello schermo SDL.
punto nella scena --mapFromScene()--> punto nel renderer
punto del mouse --mapToScene()--> punto nella scena
Con setViewport() puoi dedicare una porzione della finestra a una vista; con setClipRect() puoi restringere ulteriormente il disegno. Se l'aspect ratio fissato non coincide con quello della finestra, la View centra un'area che conserva le proporzioni invece di deformarla.
Prima di disegnare, View::render() chiede alla scena soltanto gli oggetti che intersecano il view rect. Con il quadtree attivo questa selezione evita una scansione completa degli oggetti.
La View ordina i candidati per layer, prova a convertirli in RenderableObject e chiama draw() soltanto su quelli renderizzabili. La selezione spaziale usa il rettangolo dell'oggetto: se l'immagine disegnata sporge dal suo rettangolo logico (fit = false), considera il possibile effetto sul culling vicino ai bordi della camera.
RenderableObject estende Object con:
- colore e colore di sfondo;
- bordo e spessore;
- visibilità e lampeggio;
- angolo e velocità angolare;
- flip orizzontale o verticale;
- riferimento a uno
Sprite.
Se lo sprite è nullo, l'oggetto viene disegnato come rettangolo colorato. Questo è utile per prototipi, debug e interfacce semplici.
RenderableObject::draw() può aggiungere uno sfondo colorato, un bordo, un rettangolo di debug e un breve lampeggio. RenderableObject::update() aggiorna angolo e sprite, quindi un'animazione vive nel normale ciclo degli oggetti. setVisible(false) agisce sul singolo oggetto: non lo toglie dalle query della scena, ma il suo draw() termina subito.
Gli oggetti visibili vengono ordinati per layer prima del disegno. Un valore più alto viene disegnato dopo e quindi appare davanti.
auto* shadow = new RenderableObject(scene, shadowRect, shadowSprite, 1);
auto* player = new RenderableObject(scene, playerRect, playerSprite, 2);
auto* effect = new RenderableObject(scene, effectRect, effectSprite, 3);Il layer influenza il rendering, non la logica delle collisioni.
L'ordinamento viene calcolato tra gli oggetti restituiti dalla query a ogni disegno; non cambia l'ordine del vettore mantenuto dalla scena. Oggetti con lo stesso layer non hanno qui una regola esplicita di precedenza su cui fare affidamento.
Con fit = true, lo sprite viene adattato al rettangolo dell'oggetto. Con fit = false, il core conserva proporzioni e scala coerenti con pixelUnitSize, utile quando il rettangolo logico rappresenta un collider ma l'immagine deve estendersi oltre di esso.
Il filtro nearest impostato sulle texture mantiene nitida la pixel art durante l'ingrandimento.
Il filtro è una proprietà della texture, non della camera: le funzioni di caricamento grafico in utils/sdlUtils.h impostano SDL_SCALEMODE_NEAREST per le immagini. La texture generata per il testo usa invece il filtraggio lineare. La scelta va fatta quando si crea la texture se si aggiunge un caricatore nuovo.
Game conserva l'aspect ratio desiderato. Le View possono applicarlo al proprio viewport, introducendo bande laterali o superiori invece di deformare la scena.
GameScene imposta sulla propria View l'aspect ratio fornito da Game; anche OverlayScene lo imposta. UIScene crea una View autonoma e può avere esigenze diverse. Nella GameScene standard la camera segue _player centrando il view rect sul rettangolo del giocatore, oppure si può passare al movimento manuale con le frecce e allo zoom con la rotellina. La camera non sposta gli oggetti: cambia soltanto la trasformazione usata nel disegno e nelle conversioni dell'input.
Per i click nella scena, continua con Input ed eventi; per la grafica dentro ogni oggetto, continua con Sprite, animazioni e testo.
- 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