Categories
design pattern event linguaggio javascript piattaforme web

Phaser 3 – evento

In JavaScript è un linguaggio che utilizza gli eventi del browser.

Oltre agli eventi per le azioni del giocatore, gli eventi possono essere generati dal programmatore per ottenere un’architettura semplice dell’applicazione e con poco accoppiamento nel codice sorgente.

In questo esempio si creerà un nuovo tipo di evento e un ascoltatore (listener) per permettere la comunicazione tra due diverse Scene.

rappresentazione schematica della comunicazione di un valore da Scena1 verso Scena2

L’architettura del progetto è già stata vista nel precedente articolo

Modificheremo il precedente progetto in modo che la Scena1 possa inviare un valore (33) alla Scena2, chiamata per questo motivo Scena2Ricevitore.

Per questo scopo verrà introdotta un nuovo file sorgente Modulo.js, con il seguente contenuto

// ./src/Modulo.js

const mioEmettitore = new Phaser.Events.EventEmitter();

export default mioEmettitore;

Questo è il nuovo file main.js

// ./src/main.js

import {Scena1} from './Scena1.js'; 
import {Scena2Ricevitore} from './Scena2Ricevitore.js';
import {Scena3} from './Scena3.js'; 

const config = {
    type: Phaser.AUTO,
    scale: {
        mode: Phaser.Scale.NONE,
        parent: 'miodiv',
        autoCenter: Phaser.Scale.CENTER_BOTH,
        autoRound: true,
    },
    width: 1024,
    height: 768,
    backgroundColor: '#332222',
    parent: 'miodiv',
    scene: [ Scena1, Scena2Ricevitore, Scena3 ], 
    physics: {
        default: 'arcade',
        arcade: { debug: false }
    }
};

let game = new Phaser.Game(config);

La Scena1.js ha una nuova proprietà (this.x)

import mioEmettitore from './Modulo.js';

export class Scena1 extends Phaser.Scene
{
    constructor ()
    {
        super('Scena1');
    }

    preload () 
    {
        this.x = 33; // verrà passato alla scena successiva
        this.testo1 = this.add.text(112, 100, 'scena1-start');
    }

    create () 
    {
        // eseguo in anticipo la Scena2 (in parallelo)
        this.scene.run('Scena2Ricevitore'); 
        
        // parte eseguita SOLO quando l'utente si muove con il mouse 
        this.input.once('pointerdown', () => {
	    // emetto evento quando faccio click e poi passo all'altra Scene.
            mioEmettitore.emit('evento',this.x);
            this.scene.setVisible(true,'Scena2Ricevitore');  // visibile
            this.scene.setActive(true,'Scena2Ricevitore');  // sensibile al click
            this.scene.stop('Scena1'); 
        });
    }
    
    update()
    {
        // non è molto elegante ripetere nel main loop una istruzione
        // ma è inevitabile. Purtroppo queste istruzioni non sono efficaci nel metodo "create()"
	this.scene.setVisible(false,'Scena2Ricevitore'); // invisibile
	this.scene.setActive(false,'Scena2Ricevitore'); // insensibile al click
    }
}

Nella Scena2.js si deve attivare un ascoltatore (e poi disattivarlo al termine di Scena2.js)

// ./src/Scena2Ricevitore

import mioEmettitore from './Modulo.js';

export class Scena2Ricevitore extends Phaser.Scene
{
    constructor ()
    {
        super('Scena2Ricevitore');
    }

    preload () 
    {
        this.testo1 = this.add.text(112, 400, 'ho ricevuto un evento e un parametro x->y');
        this.testo2 = this.add.text(112, 500, 'segnaposto per y');
        // attivare l'ascoltatore su evento evento
        mioEmettitore.on('evento', this.ascoltatore, this); 
    }

    create () 
    {
        this.input.once('pointerdown', () => {
            this.scene.start('Scena3');
        });

        // arrestare l'ascoltatore al termine della scena2 
        this.events.on(Phaser.Scenes.Events.SHUTDOWN, () => { 
            mioEmettitore.off('evento', this.ascoltatore, this) 
	});
    }
    
    ascoltatore(y) {  
       // y è argomento ricevuto dalla classe precedente
       console.log(y); 
       this.testo2.text = y;
    }
}

il progetto si può ottenere da questo file compresso: