CAPITOLO 11

Input Handling

Intermedio
~25 min

Keyboard

Phaser ci permette in maniera molto agevole di gestire l'input da tastiera attraverso la classe Phaser.Input.Keyboard.


Cursors

Come visto in alcuni esempi precedenti, è possibile gestire il movimento di un personaggio attraverso una classe specifica per i tasti cursore.

Prima definiamo una variabile che ospiterà l'istanza dei tasti cursore:

private _cursors: Phaser.Types.Input.Keyboard.CursorKeys;

Nel metodo create() utilizziamo createCursorKeys() per creare l'istanza:

this._cursors = this.input.keyboard.createCursorKeys();

_cursors fornisce riferimenti alle 4 direzioni (up, down, left, right) e ai tasti space e shift.

Nel metodo update() controlliamo la proprietà isDown per verificare se un tasto è premuto:

if (this._cursors.left.isDown) {
  // sposta il personaggio a sinistra
}

if (this._cursors.right.isDown) {
  // sposta il personaggio a destra
}

if (this._cursors.up.isDown) {
  // salta
}

isDown è true per tutta la durata della pressione del tasto — utile per il movimento continuo del personaggio.


Custom Keys

È possibile gestire l'input con tasti personalizzati diversi dalle frecce direzionali. Definiamo le variabili per ogni tasto:

private _w: Phaser.Input.Keyboard.Key;
private _a: Phaser.Input.Keyboard.Key;
private _s: Phaser.Input.Keyboard.Key;
private _d: Phaser.Input.Keyboard.Key;
private _space: Phaser.Input.Keyboard.Key;

Nel metodo create() utilizziamo addKey() per creare un riferimento a ciascun tasto:

this._w = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W);
this._a = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A);
this._s = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S);
this._d = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D);
this._space = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE);

Nel metodo update() controlliamo lo stato del tasto esattamente come per i cursors:

if (this._d.isDown) {
  // sposta il personaggio a destra
}

isDown vs JustDown

MetodoComportamentoUso tipico
isDowntrue per tutta la durata della pressioneMovimento del personaggio
JustDown()true solo al primo frame della pressioneSparo, salto, interazione

Quando vogliamo rilevare una singola pressione (ad esempio per sparare un proiettile), isDown non è efficace perché esegue il codice continuamente. In questi casi usiamo il metodo statico Phaser.Input.Keyboard.JustDown():

// spara un solo proiettile per pressione del tasto
if (Phaser.Input.Keyboard.JustDown(this._space)) {
  this.spara();
}

JustDown() rileva la "singola" pressione: il codice viene eseguito una sola volta per ogni pressione del tasto.

Esiste anche Phaser.Input.Keyboard.JustUp() che rileva il rilascio del tasto — utile per caricare colpi o controlli a pressione prolungata.


Un Virtual Joystick

Quando sviluppiamo giochi per dispositivi touch (smartphone e tablet) serve un'alternativa all'input da tastiera. Una soluzione è utilizzare la libreria esterna nipplejs che crea un vero e proprio joystick virtuale.

Installazione

Aggiungere la dipendenza nel file package.json:

"dependencies": {
  "nipplejs": "^0.10.1",
  "phaser": "^3.9.0"
}

Eseguire nel terminale:

npm update

Importazione

Importare la libreria nella classe del player:

import nipplejs from 'nipplejs';

Implementazione

Nel metodo di inizializzazione del player inseriamo il codice per gestire il movimento tramite virtual joystick:

// creiamo un'istanza del joystick
const joystickManager: nipplejs.JoystickManager = nipplejs.create({
  color: 'red'
});

// evento di inizio movimento
joystickManager.on('start', () => {
  // il joystick è stato toccato
});

// evento di movimento
joystickManager.on('move', (data: nipplejs.EventData, output: nipplejs.JoystickOutputData) => {
  // force: intensità dello spostamento (0-1)
  const force: number = Math.min(output.force, 1);

  // angle: angolo in radianti
  const angle: number = output.angle.radian;

  // calcola la velocità in base alla forza e alla velocità massima del player
  const speed: number = this._acceleration * force;

  // imposta la velocità usando la trigonometria
  this.setVelocity(
    speed * Math.cos(angle),
    speed * Math.sin(angle) * -1
  );
});

// evento di fine movimento
joystickManager.on('end', () => {
  // il joystick è stato rilasciato — ferma il personaggio
  this.setVelocity(0, 0);
});

Il virtual joystick funziona tramite eventi (start, move, end) — non è necessario controllarne lo stato nell'update() come si fa con i tasti della tastiera.

I parametri output.force e output.angle.radian permettono di implementare un movimento analogico: più si sposta il joystick dal centro, maggiore sarà la velocità del personaggio.


Confronto tra i metodi di input

MetodoDispositivoQuando usarlo
CursorKeysTastieraPrototipazione rapida, movimento 4 direzioni
Custom Keys (WASD)TastieraLayout alternativo, più tasti contemporanei
Virtual JoystickTouchMobile e tablet

Phaser Labs
Phaser LabsLIVE
Prova tutto dal vivo — centinaia di esempi interattivi
Phaser Labs raccoglie esempi funzionanti per ogni argomento del corso. Copia, modifica, sperimenta — direttamente nel browser.
Esempi sull'utilizzo dell'INPUT
Sh4rk0

L'input è il primo vero "dialogo" tra il giocatore e il tuo gioco — se risponde male, il resto non conta. Per questo vale la pena capire bene la differenza tra isDown e JustDown(): usare il primo dove serve il secondo è l'errore più comune (e più fastidioso da debuggare) quando un personaggio "spara a raffica" senza che tu l'abbia previsto.

Il pattern CursorKeys per il prototipo, Custom Keys per il gioco finito ti fa risparmiare tempo: parti con le frecce per validare velocemente la meccanica, poi passa a WASD (o a un rebind configurabile) quando la UX conta davvero.

Non sottovalutare il virtual joystick: se il tuo gioco gira anche su mobile, è l'unico modo per dare un controllo decente senza tastiera. E il bello è che il codice di movimento resta lo stesso — cambi solo la fonte del segnale (force/angle invece di isDown).

Tip pro: separa sempre la lettura dell'input dalla logica di movimento in due metodi distinti. Così puoi testare (o sostituire) l'input — tastiera, joystick, gamepad — senza toccare una riga della fisica del personaggio. 🎮