Organitzar el codi és fonamental per mantenir un projecte escalable, fàcil de mantenir i col·laboratiu. En aquest tema aprendràs com estructurar el teu codi de joc amb Phaser, utilitzant bones pràctiques de programació i patrons habituals en el desenvolupament de jocs.


Conceptes clau

  • Modularitat: Dividir el codi en fitxers i mòduls lògics.
  • Separació de responsabilitats: Cada part del codi ha de tenir una funció clara.
  • Reutilització: Escriure codi que pugui ser reutilitzat en diferents parts del joc.
  • Llegibilitat: Utilitzar noms clars i comentaris per facilitar la comprensió.
  • Escalabilitat: Preparar l’estructura per afegir noves funcionalitats fàcilment.

Estructura bàsica d’un projecte Phaser

Una bona organització de carpetes i fitxers pot ser la següent:

Carpeta/Fitxer Contingut
index.html Punt d’entrada del joc (carrega Phaser i el teu codi JS)
src/ Codi font del joc
src/scenes/ Escenes del joc (menú, joc principal, game over, etc.)
src/objects/ Classes d’objectes personalitzats (jugador, enemics, projectils, etc.)
src/utils/ Funcions auxiliars i utilitats
assets/ Recursos multimèdia (imatges, sons, tilemaps, etc.)
package.json Configuració de dependències (si utilitzes npm)

Exemple d’estructura:

project/
│
├── index.html
├── src/
│   ├── main.js
│   ├── scenes/
│   │   ├── BootScene.js
│   │   ├── MenuScene.js
│   │   └── GameScene.js
│   ├── objects/
│   │   ├── Player.js
│   │   └── Enemy.js
│   └── utils/
│       └── helpers.js
└── assets/
    ├── images/
    ├── audio/
    └── tilemaps/

Separació de responsabilitats amb escenes

Phaser utilitza el concepte d’escenes per dividir el flux del joc (menú, joc, pantalla de puntuació, etc.). Cada escena hauria d’estar en el seu propi fitxer i classe.

Exemple bàsic d’una escena:

// src/scenes/GameScene.js
export default class GameScene extends Phaser.Scene {
  constructor() {
    super({ key: 'GameScene' });
  }

  preload() {
    this.load.image('player', 'assets/images/player.png');
  }

  create() {
    this.player = this.add.sprite(100, 100, 'player');
  }

  update(time, delta) {
    // Lògica de joc
  }
}

Explicació:

  • constructor: Defineix la clau de l’escena.
  • preload(): Carrega recursos.
  • create(): Inicialitza objectes.
  • update(): S’executa cada frame per actualitzar la lògica.

Crear objectes personalitzats

Per mantenir el codi net, crea classes per als teus objectes de joc (jugador, enemics, etc.) i importa-les a les escenes.

// src/objects/Player.js
export default class Player extends Phaser.Physics.Arcade.Sprite {
  constructor(scene, x, y) {
    super(scene, x, y, 'player');
    scene.add.existing(this);
    scene.physics.add.existing(this);
  }

  moveLeft() {
    this.setVelocityX(-160);
  }

  moveRight() {
    this.setVelocityX(160);
  }
}

Com utilitzar-lo a l’escena:

import Player from '../objects/Player.js';

create() {
  this.player = new Player(this, 100, 100);
}

Utilitzar funcions auxiliars

Les funcions que es repeteixen o que són utilitats generals (per exemple, calcular distàncies, generar números aleatoris, etc.) han d’anar a fitxers dins de src/utils/.

// src/utils/helpers.js
export function randomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

Exemple pràctic: Organització d’una escena amb objectes

// src/scenes/GameScene.js
import Player from '../objects/Player.js';
import { randomInt } from '../utils/helpers.js';

export default class GameScene extends Phaser.Scene {
  create() {
    this.player = new Player(this, 100, 100);

    // Exemple d’ús d’una funció auxiliar
    let randomX = randomInt(0, 800);
    // Crear un enemic a una posició aleatòria
  }
}

Exercicis pràctics

Exercici 1: Crea una nova escena

Enunciat:
Crea una nova escena anomenada MenuScene dins la carpeta src/scenes/. Aquesta escena ha de mostrar el text "Benvingut al Joc!" al centre de la pantalla.

Solució:

// src/scenes/MenuScene.js
export default class MenuScene extends Phaser.Scene {
  constructor() {
    super({ key: 'MenuScene' });
  }

  create() {
    this.add.text(400, 300, 'Benvingut al Joc!', {
      fontSize: '32px',
      color: '#ffffff'
    }).setOrigin(0.5);
  }
}

Consell:
Assegura’t d’afegir la nova escena a la configuració del joc perquè es pugui mostrar.


Exercici 2: Refactoritza el codi del jugador

Enunciat:
Mou la lògica del jugador a una classe separada Player.js dins de src/objects/ i utilitza-la a la teva escena principal.

Solució:

// src/objects/Player.js
export default class Player extends Phaser.Physics.Arcade.Sprite {
  constructor(scene, x, y) {
    super(scene, x, y, 'player');
    scene.add.existing(this);
    scene.physics.add.existing(this);
  }
}

// src/scenes/GameScene.js
import Player from '../objects/Player.js';

create() {
  this.player = new Player(this, 100, 100);
}

Error comú:
Oblidar-se d’afegir l’objecte a la física o a l’escena pot fer que no aparegui o no funcioni correctament.


Resum

  • Organitzar el codi en fitxers i carpetes lògiques facilita el manteniment i l’escalabilitat.
  • Utilitza escenes per separar les diferents parts del joc.
  • Crea classes per als objectes del joc i utilitza funcions auxiliars per a tasques repetitives.
  • Segueix una estructura clara i coherent per facilitar la col·laboració i el creixement del projecte.

Amb aquests fonaments, estaràs preparat per gestionar projectes de jocs més grans i complexos de manera eficient. El següent tema tractarà la gestió de múltiples escenes per a una experiència de joc més rica i organitzada.

Phaser - Desenvolupament de jocs amb JavaScript

Mòdul 1: Introducció al desenvolupament de jocs i Phaser

Mòdul 2: Fonaments de Phaser

Mòdul 3: Sprites i animació

Mòdul 4: Física i interactivitat en el joc

Mòdul 5: Món del joc i càmera

Mòdul 6: Àudio i interfície d’usuari

Mòdul 7: Arquitectura del joc i gestió d’estats

Mòdul 8: Funcionalitats avançades de joc

Mòdul 9: Desplegament i optimització

Mòdul 10: Projecte final

© Copyright 2024. Tots els drets reservats