CAPITOLO 5.1

Introduzione ai GameObjects

Intermedio
~20 min
49 min

Cosa sono i GameObjects

In Phaser, i gameObjects sono tutti quegli elementi che utilizziamo per visualizzare oggetti all'interno della nostra scena. Tutti derivano dalla classe base Phaser.GameObjects.GameObject e la estendono con implementazioni proprie.

Nei capitoli seguenti esamineremo i seguenti gameObjects:

GameObjectScopo
textVisualizzare testo a schermo
imageVisualizzare immagini statiche
spriteVisualizzare immagini animate
tileSpriteCreare sfondi ripetuti e parallasse
groupRaggruppare e gestire gameObjects simili
containerContenere gameObjects in un contesto visuale comune

Tutti fanno parte della GameObjectsFactory. Alcuni (come container e group) non hanno un output visivo diretto ma servono a organizzare gli altri.

Creare un'istanza

Per aggiungere un gameObject alla scena si usa this.add seguito dal tipo:

create() {
  this.add.text(0, 0, "Hello World", { fontSize: "20px" });
}

this rappresenta la scena corrente, add è il metodo che accede alla GameObjectFactory. È possibile assegnare l'istanza a una variabile privata per riutilizzarla:

create() {
  this._helloWorld = this.add.text(0, 0, "Hello World", { fontSize: "20px" });
  this._helloWorld.setPosition(10, 10);
}

Proprietà comuni

Questi metodi sono disponibili su tutti i gameObjects.

.setPosition(x, y)

Setta la posizione x e y del gameObject nel mondo di gioco.

this._myObject.setPosition(400, 300);

.setDepth(value)

Controlla lo z-index del gameObject. Per default, l'ordine di visualizzazione dipende dalla sequenza di creazione nel codice: il secondo oggetto creato si sovrappone al primo.

create() {
  this._image1 = this.add.image(850, 200, "immagine1"); // sotto
  this._image2 = this.add.image(855, 200, "immagine2"); // sopra
}

Con setDepth possiamo invertire l'ordine senza cambiare la sequenza di inizializzazione:

create() {
  this._image1 = this.add.image(850, 200, "immagine1").setDepth(1); // sopra
  this._image2 = this.add.image(855, 200, "immagine2");             // sotto
}

Il valore depth di default è 0. Un valore più alto porta l'oggetto in primo piano.

.setAbove(gameObject) / .setBelow(gameObject)

Alternativa a setDepth: posiziona il gameObject immediatamente sopra o sotto un altro gameObject specifico nella display list.

this._image1.setAbove(this._image2); // image1 davanti a image2

.setToTop() / .setToBack()

Porta il gameObject in cima o in fondo alla display list della scena, senza dover conoscere i depth degli altri oggetti.

this._overlay.setToTop();  // in primo piano assoluto
this._background.setToBack(); // in fondo assoluto

.setAlpha(alpha)

Controlla l'opacità. Valori tra 0 (trasparente) e 1 (opaco).

this._myObject.setAlpha(0.5); // semi-trasparente

.setAngle(degrees) / .setRotation(radians)

Ruota il gameObject. setAngle accetta gradi, setRotation radianti.

this._myObject.setAngle(45);           // 45 gradi
this._myObject.setRotation(Math.PI);   // 180 gradi in radianti

.setTint / .setTintFill / .clearTint

setTint imposta un tint additivo: moltiplica i pixel della texture per il colore indicato. Accetta un singolo colore esadecimale oppure quattro valori per colorare i singoli angoli del gameObject.

this._sprite.setTint(0xff6600);

// angoli diversi
this._sprite.setTint(0xff0000, 0x00ff00, 0x0000ff, 0xffffff);

clearTint rimuove qualsiasi tinta applicata:

this._sprite.clearTint();

Per colorare i singoli angoli tramite proprietà dirette:

this._sprite.tintTopLeft     = 0xff0000;
this._sprite.tintTopRight    = 0x00ff00;
this._sprite.tintBottomLeft  = 0x0000ff;
this._sprite.tintBottomRight = 0xffffff;

setTintFill invece sostituisce completamente il colore dei pixel (rispettando l'alpha della texture), invece di moltiplicarli — utile per un "flash bianco" quando il personaggio viene colpito:

this._sprite.setTintFill(0xffffff);

La proprietà booleana tintFill controlla se il tint attivo è additivo (false, default) o a sostituzione (true). setTintFill() la imposta a true internamente insieme al colore.

.setBlendMode(mode)

Controlla come i pixel del gameObject si combinano con quelli già disegnati sotto. Default: Phaser.BlendModes.NORMAL (nessun effetto).

this._myObject.setBlendMode(Phaser.BlendModes.ADD);

Oppure tramite la proprietà diretta:

this._myObject.blendMode = Phaser.BlendModes.MULTIPLY;

Modalità disponibili:

BlendModeEffetto
NORMALDefault — nessun blending
ADDSomma i canali RGB: effetto luce, bagliore, esplosione
MULTIPLYMoltiplica i colori: scurisce, effetto ombra
SCREENInverso di multiply: schiarisce, effetto schermo proiettato
OVERLAYCombina multiply e screen in base alla luminosità
ERASECancella pixel dalla destinazione (solo su RenderTexture)
SOURCE_INMostra solo l'intersezione (solo Canvas)
SOURCE_OUTMostra solo la parte fuori dall'intersezione (solo Canvas)
SOURCE_ATOPSovrappone rispettando l'alpha della destinazione (solo Canvas)
DESTINATION_OVERDisegna sotto la destinazione esistente (solo Canvas)
DESTINATION_INMantiene solo l'intersezione (solo Canvas)
DESTINATION_OUTMantiene solo la parte fuori (solo Canvas)
DESTINATION_ATOPInverso di source-atop (solo Canvas)
LIGHTERCome ADD ma limitato ai valori 0, 1 (solo Canvas)
COPYSovrascrive completamente la destinazione (solo Canvas)
XORXOR bit a bit sull'alpha (solo Canvas)

Le modalità contrassegnate come solo Canvas non funzionano con il renderer WebGL. ADD, MULTIPLY, SCREEN e NORMAL funzionano su entrambi. Con type: Phaser.AUTO (vedi capitolo precedente) il renderer effettivo dipende dal browser dell'utente: testa sempre gli effetti anche in modalità Canvas.

ADD è la scelta più comune per effetti particellari, esplosioni e power-up luminosi. MULTIPLY per ombre e overlay atmosferici.

Supporto per tipo di gameObject:

GameObjectWebGLCanvas
Image, Sprite, TileSpriteTutti i mode WebGLTutti i mode Canvas
TextNORMAL, ADD, MULTIPLY, SCREENTutti
GraphicsNORMAL, ADDTutti
RenderTextureTutti + ERASETutti
ContainerEredita dal rendererEredita dal renderer
GroupNon supportato direttamenteNon supportato direttamente

.setFlip(x, y)

Capovolge il gameObject orizzontalmente e/o verticalmente. Sono disponibili anche .setFlipX() e .setFlipY().

this._myObject.setFlipX(true);  // specchio orizzontale
this._myObject.setFlip(true, false);

Il flip è puramente visivo: non modifica i valori di posizione né il corpo fisico (physics body).

roundPixels

A differenza di un controllo granulare per singolo gameObject, in Phaser 3 l'arrotondamento delle coordinate al pixel intero (utile per eliminare l'aliasing su oggetti pixel-art) si configura a livello di camera o di config globale:

// nel GameConfig
const config: Phaser.Types.Core.GameConfig = {
  render: {
    pixelArt: true,   // imposta anche roundPixels e antialias per la pixel-art
    roundPixels: true,
  },
};

// oppure sulla singola camera, a runtime
this.cameras.main.roundPixels = true;

pixelArt: true nel render del GameConfig è una scorciatoia pensata apposta per giochi con grafica pixel-art: disabilita l'antialiasing e arrotonda le coordinate, mantenendo gli sprite nitidi anche con zoom della camera.

.setScrollFactor(x, y)

Controlla quanto il gameObject si muove rispetto alla camera. Utile per elementi UI o sfondi.

ValoreComportamento
1Si muove in sincronia con la camera (default)
0Rimane fisso sullo schermo (ideale per HUD)
0.5Si muove a metà velocità rispetto alla camera (parallasse)
this._scoreText.setScrollFactor(0); // il punteggio resta fisso

.setScale(x, y)

Ridimensiona il gameObject. Se si passa un solo valore, viene applicato uniformemente.

this._myObject.setScale(2);      // doppia dimensione
this._myObject.setScale(2, 0.5); // larga e piatta

.setOrigin(x, y)

Setta il punto di ancoraggio del gameObject. I valori sono compresi tra 0 e 1, dove 0.5, 0.5 è il centro.

this._myObject.setOrigin(0, 0);     // angolo top-left
this._myObject.setOrigin(0.5, 0.5); // centro (default)
this._myObject.setOrigin(1, 1);     // angolo bottom-right

.setInteractive()

Abilita il gameObject alla ricezione di eventi di input (click, touch, hover).

this._button.setInteractive();

.on(event, callback, context)

Aggiunge un listener di eventi sul gameObject. I metodi setInteractive() e on() si concatenano spesso con setScale():

this._helloWorld
  .setScale(2)
  .setInteractive()
  .on("pointerdown", () => { /* esegui al click */ }, this)
  .on("pointerover", () => { /* esegui all'hover */ }, this)
  .on("pointerout",  () => { /* esegui all'uscita */ }, this);
EventoQuando si attiva
pointerdownClick del mouse / tap su mobile
pointerupRilascio del mouse / rilascio del dito
pointeroverIl cursore entra nel gameObject
pointeroutIl cursore esce dal gameObject

.destroy()

Rimuove il gameObject dalla scena e dalla memoria. Da usare quando un oggetto non sarà più necessario (proiettile uscito dallo schermo, nemico eliminato).

this._bullet.destroy();

Per la lista completa dei gameObjects disponibili: docs.phaser.io/phaser3

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.
Apri gli esempi
Sh4rk0

Lo so già: non hai memorizzato tutti questi metodi. E va benissimo così.

Quello che devi portarti a casa è una manciata di metodi che userai nel 90% dei casi: setPosition, setAlpha, setScale e setOrigin. Con quelli metti qualsiasi cosa dove vuoi, la dimensioni e la rendi trasparente.

setInteractive() + .on('pointerdown', ...) è il combo magico per rendere qualcosa cliccabile — pulsanti, oggetti da raccogliere, nemici da colpire.

setDepth quando qualcosa appare dietro quando dovrebbe stare davanti. destroy() quando qualcosa deve sparire per sempre.

Il resto? Lo copi dalla documentazione ogni volta che ti serve. Google e la doc di Phaser sono strumenti del mestiere, non segni di debolezza. 🔍