Skip to content

Core Input e Eventi

Alessandro Bria edited this page Oct 31, 2026 · 4 revisions

Input ed eventi

Il core distingue gli eventi discreti (pressione di un tasto, click, ridimensionamento) dallo stato continuo dei comandi (un tasto tenuto premuto). La distinzione conta: i primi arrivano tramite SDL_PollEvent(), il secondo si legge durante l'aggiornamento.

Percorso di un evento

SDL_PollEvent -> Game::dispatchEvent -> Scene::event -> eventuale sottoclasse

Game::processEvents() svuota la coda SDL prima di aggiornare le scene. dispatchEvent() gestisce prima i comandi globali, poi distribuisce gli eventi:

  1. gli eventi di finestra raggiungono tutte le scene, perché ciascuna View può dover ricalcolare il viewport; sul ridimensionamento viene aggiornata anche la Window;
  2. Ctrl+Shift+Su/Giù modifica la scala temporale globale;
  3. V attiva/disattiva il sonoro tramite Audio::toggleMute(), anche nei menu e in pausa; la ripetizione automatica del tasto viene ignorata e il comando non interviene durante l'inserimento di testo;
  4. gli altri eventi partono dalla scena in cima allo stack e scendono fino alla prima scena blocking.

Scene::event() aggiorna il viewport per gli eventi di finestra. Se ridefinisci event(), chiama prima la versione base (o GameScene::event() se derivi da GameScene), così non perdi questo comportamento e gli eventuali comandi già previsti. GameScene inoltra gli eventi di finestra anche ai propri overlay.

La richiesta di chiusura dell'applicazione o della finestra viene gestita da Game. Il tasto Esc viene invece distribuito alle scene: può aprire la pausa nel gioco o annullare lo strumento nell'editor. Una scena bloccante impedisce che lo stesso tasto raggiunga il gameplay sottostante.

Pressione singola o comando continuo?

Per un'azione che deve scattare una volta, controlla SDL_EVENT_KEY_DOWN e !evt.key.repeat dentro event():

void MyScene::event(SDL_Event& evt)
{
    GameScene::event(evt);
    if (evt.type == SDL_EVENT_KEY_DOWN &&
        evt.key.scancode == SDL_SCANCODE_SPACE && !evt.key.repeat)
        player()->jump();
}

L'esempio è schematico: jump() appartiene alla classe del giocatore del progetto, non a Object del core. Il controllo del tipo di evento deve precedere l'uso dei campi specifici di tastiera.

Per un movimento mantenuto mentre il tasto è premuto, leggi SDL_GetKeyboardState() durante l'aggiornamento. CustomPlatformer e ActionRPG impostano i comandi del personaggio in updateControls(), chiamato una volta per frame prima dei passi di updateWorld(). Attacchi e apertura dei menu passano invece da event().

Box2DPlatformer applica le forze dei controlli in PlatformerGameScene::updatePhysicsControls(), chiamato prima di ogni passo fisico. Box2D azzera le forze dopo ogni step: applicarle una sola volta per frame renderebbe il movimento dipendente da FPS e VSync. Camera ed eventi discreti conservano il proprio aggiornamento. Vedi timestep di Box2DPlatformer.

Mouse e coordinate

Le coordinate del mouse fornite da SDL sono nello spazio della finestra. Gli oggetti vivono nello spazio della scena. Prima di usare un click per selezionare o posizionare un oggetto nella scena di gioco, passa per la sua View:

PointF worldPoint = view()->mapToScene(mouseX, mouseY);
auto selected = objects(worldPoint);

mapToScene() applica posizione della camera, zoom, viewport, rapporto d'aspetto e orientamento dell'asse Y. Usare direttamente mouseX e mouseY come coordinate della scena può funzionare per caso a una risoluzione e rompersi al ridimensionamento. L'editor usa questa conversione per i click; il percorso inverso è mapFromScene().

Scene sovrapposte

Una UIScene in cima allo stack può intercettare l'input e fermare l'aggiornamento del gioco impostando setBlocking(true). Con false, l'evento continua anche verso le scene sottostanti. Non esiste un flag generico «evento consumato»: la propagazione è determinata da blocking, quindi una UI non bloccante deve essere progettata tenendo conto dell'eventuale input ricevuto anche dalla scena di gioco.

Il rendering non segue questa regola: anche con una UI bloccante, le scene sotto vengono comunque disegnate. Questo permette di mostrare un menu di pausa sopra il gioco fermo.

Sorgenti

Prosegui con Scene, oggetti e scheduling.

Clone this wiki locally