✚ Sviluppo videogiochi

Gestire l'input nei giochi: tastiera, gamepad e azioni astratte

Come progettare la gestione dell'input in un videogioco: eventi e polling, azioni astratte, gamepad e zone morte, rimappatura dei tasti e accessibilità.

Il giocatore percepisce un gioco attraverso lo schermo, ma lo controlla attraverso l'input. Un ritardo di pochi fotogrammi, un tasto che a volte non risponde o una levetta analogica che fa muovere il personaggio da solo bastano a rovinare l'esperienza. Una buona gestione dell'input si basa su un'idea semplice: separare che cosa preme il giocatore da che cosa vuole fare.

Eventi e polling

Esistono due modi di leggere l'input:

  • eventi: il sistema operativo segnala «tasto premuto» o «tasto rilasciato» quando succede. Utile per azioni puntuali e per la digitazione di testo.
  • polling: a ogni fotogramma si interroga lo stato attuale, «il tasto è giù?». Utile per azioni continue come il movimento.

La soluzione più robusta li combina: si raccolgono gli eventi del fotogramma e si mantiene una tabella di stato per ogni tasto, da cui si ricavano tre informazioni distinte.

Informazione Significato Uso tipico
Premuto ora Giù in questo fotogramma, su nel precedente Saltare, sparare un colpo
Tenuto Giù in questo fotogramma Camminare, caricare un attacco
Rilasciato ora Su in questo fotogramma, giù nel precedente Interrompere un salto, lanciare

Confondere «premuto ora» con «tenuto» è uno degli errori più comuni: il personaggio salta ripetutamente finché il tasto resta giù.

Azioni astratte

Il codice di gioco non dovrebbe mai chiedere «la barra spaziatrice è premuta?», ma «l'azione salta è stata attivata?». Si definisce una mappa tra azioni e ingressi fisici:

azioni = {
  "salta":    [Tasto.SPAZIO, Pad.A],
  "spara":    [Tasto.J, Mouse.SINISTRO, Pad.X],
  "sinistra": [Tasto.A, Tasto.FRECCIA_SX, Pad.LEVETTA_SX_SINISTRA],
  "pausa":    [Tasto.ESC, Pad.START],
}

I vantaggi sono notevoli:

  • più dispositivi possono attivare la stessa azione senza duplicare il codice;
  • la rimappatura diventa semplice: si modifica la tabella, non il codice;
  • i menu e il gioco possono usare mappe diverse, attivando l'una o l'altra a seconda del contesto.

La maggior parte dei motori moderni offre un sistema di azioni di questo tipo, ed è sempre preferibile alla lettura diretta dei tasti.

Assi e input analogici

Le levette dei gamepad e i grilletti restituiscono valori continui, tipicamente da −1 a 1 per le levette e da 0 a 1 per i grilletti. Per uniformare tastiera e gamepad conviene definire anche assi astratti: l'asse «orizzontale» vale −1 se è premuto sinistra, 1 se è premuto destra, oppure il valore della levetta.

La zona morta

Nessuna levetta torna esattamente al centro: a riposo restituisce piccoli valori, come 0,03 o −0,05. Senza correzione, il personaggio si sposta lentamente da solo. La zona morta ignora i valori sotto una soglia:

lunghezza = sqrt(x*x + y*y)
se lunghezza < zona_morta:
    x, y = 0, 0
altrimenti:
    scala = (lunghezza - zona_morta) / (1 - zona_morta) / lunghezza
    x, y = x * scala, y * scala

Questa è una zona morta radiale, applicata al vettore intero. Applicarla separatamente ai due assi crea una zona a croce che rende difficili le diagonali leggere. La riscalatura fa sì che appena fuori dalla zona il valore riparta da zero invece di saltare alla soglia.

Movimento diagonale da tastiera

Con quattro tasti, premere destra e su insieme produce il vettore (1, 1), lungo circa 1,41. Il personaggio si muove più veloce in diagonale. Basta normalizzare il vettore quando la sua lunghezza supera 1.

Latenza

La latenza percepita dipende da molti fattori: frequenza di lettura dell'input, numero di fotogrammi in coda per il rendering, sincronizzazione verticale, schermo. Alcune regole pratiche:

  • leggere l'input il più tardi possibile prima dell'aggiornamento, non all'inizio di un ciclo lungo;
  • dare una risposta visiva immediata, anche solo un'animazione che parte nello stesso fotogramma;
  • evitare code di rendering profonde quando il gioco richiede riflessi rapidi.

Più giocatori e dispositivi

Nei giochi locali per più persone bisogna associare ogni dispositivo a un giocatore. Il metodo classico è una schermata di ingresso dove ciascuno preme un tasto sul proprio controller per «unirsi». Va gestita anche la disconnessione: se un gamepad si scollega a metà partita, il gioco dovrebbe mettersi in pausa e attendere, invece di lasciare un personaggio immobile.

Accessibilità

Una buona gestione dell'input rende il gioco accessibile a più persone con poco sforzo:

  • rimappatura completa di tutte le azioni, compresi i menu;
  • alternativa tra tenere premuto e premere una volta per azioni come correre o mirare;
  • regolazione della sensibilità e dell'inversione degli assi;
  • possibilità di giocare con una sola mano o con un solo dispositivo;
  • icone dei pulsanti aggiornate automaticamente in base al dispositivo in uso.

In sintesi

  • Separare gli ingressi fisici dalle azioni di gioco semplifica il codice e la rimappatura.
  • Distinguere premuto ora, tenuto e rilasciato ora evita comportamenti indesiderati.
  • Le levette richiedono una zona morta radiale con riscalatura.
  • Il movimento diagonale da tastiera va normalizzato.
  • Latenza ridotta, gestione dei dispositivi e opzioni di accessibilità completano un buon sistema di input.
MM
Marco Marzaduri

Marco Marzaduri si occupa di cybersecurity, informatica forense e sviluppo web. Laureato in informatica e in psicologia, unisce l'analisi tecnica alla comprensione del fattore umano.

Leggi anche