> Manuales > Manual de Phaser

Introducción al motor de juegos Javascript Phaser y pasos para crear tu primer juego HTML5 con este potente framework de desarrollo.

Introducción a Phaser

Phaser es un motor que permite crear juegos HTML5 de una manera sencilla pero poderosa. En este artículo encontrarás una primera introducción y comenzaremos a realizar un juego elemental, con el que dar nuestros primeros pasos con Phaser.

A lo largo del Manual de Phaser iremos desarrollando una versión del mítico juego "Arkanoid" o "Breakout", incorporando diversas piezas en nivel creciente de dificultad, hasta llegar a convertir nuestro juego en una PWA (Progressive Web App) capaz de instalarse en los ordenadores de los usuarios o en ordenadores de escritorio, funcionar offline, etc.

Para que tengas una mejor idea de lo que iremos desarrollando a lo largo de los siguientes artículos te dejamos estos enlaces:

Qué es Phaser

Phaser es un motor de juegos 2D realizado sobre Javascript. Es simplemente un framework o biblioteca de código Javascript que puedes incluir en tu página y mediante la cual puedes desarrollar juegos de diferentes tipos. Soporta tanto WebGL como Canvas, de manera automática. Esto quiere decir que, siempre que sea posible usará el estándar de WebGL y, si el navegador del usuario no dispone de esta tecnología, usará un elemento Canvas común.

Encontraremos en Phaser una completa cantidad de características útiles, como funciones de física, sprites, animaciones basadas en sprites y otras tecnologías más avanzadas, distintas cámaras (con las que puedes realizar juegos con scroll y diversos efectos, sonidos, escalado según los dispositivos, grupos para asignar propiedades a muchos elementos a la vez, y mucho mas… además existen plugins que se pueden incluir para mejorar las posibilidades todavía más.

Se trata de un framework muy completo, aunque a decir verdad, existen otros motores de juegos para Javascript todavía más avanzados. Sin embargo es una excelente alternativa para comenzar en el desarrollo de juegos HTML5, por ser lo suficientemente poderoso como para ofrecer las herramientas necesarias en la mayoría de juegos 2D y lo suficientemente sencillo como para que no nos desanimemos cuando estamos dando los primeros pasos.

Además cuenta con una excelente comunidad, algo que resulta muy de agradecer cuando estamos desarrollando y tenemos cualquier tipo de duda. Aparte de una buena documentación, podemos encontrar numerosos ejemplos de juegos realizados con Phaser, mediante los cuales es posible aprender a hacer muchas cosas, viendo el código implementado para resolver problemas similares a los nuestros. Quizás la única pega en este área es que a veces resulta un poco lío bucear entre la documentación y los ejemplos, pues es fácil acabar cayendo en ejemplos o artículos correspondientes a diferentes versiones del framework, que no funcionan en la versión en la que te encuentras.

Cómo instalar Phaser

Phaser es un framework muy sencillo de usar. Gracias a ello, resulta incluso apropiado para desarrolladores de Javascript de nivel medio. Uno de los puntos donde vemos esta facilidad es a la hora de instalar el framework, ya que es tan sencillo como incluir el script con el código de Phaser, que podemos traernos incluso de un CDN.

<script src="//cdn.jsdelivr.net/npm/phaser@3.24.0/dist/phaser.js"></script>

Podemos también descargar Phaser desde su página web: https://phaser.io/download/stable o usar npm si lo preferimos. Una vez incluido este script, dispones de la variable global "Phaser" que puedes usar para acceder a todos los recursos que te ofrece el framework para construir tu juego.

Cualquier alternativa es válida para instalar Phaser. Nosotros por facilidad usaremos el CDN que es la manera más rápida y directa para disponerlo en nuestras prácticas.

Servidor web

El único requisito que necesitamos para que Phaser funcione correctamente es usar un servidor web para arrancar el juego. Vale cualquier servidor web que podamos tener o usar habitualmente.

Seguro que los desarrolladores más avanzados de Javascript saben a lo que nos referimos, pero sería simplemente asegurarnos que accedemos a nuestro servidor donde se encuentra el juego a través de http:// en lugar de file://.

Este requisito se debe a que Phaser hace la carga de todas las imágenes, sonidos y recursos necesarios para mover el juego mediante Ajax, por lo que es necesario abrir la página a través de http, aunque vayamos a acceder a un archivo que está en nuestra propia máquina local.

Puedes hacerte con un servidor web de muchas maneras. Por si no lo sabes, vamos a dar unas pautas:

Primeros pasos con Phaser

Abordada la necesaria introducción y los requisitos para comenzar, pasamos directamente a la práctica, para crear la estructura de archivos y carpetas para nuestro primer juego Javascript.

El HTML

Básicamente vamos a tener un archivo HTML en el que incluiremos dos scripts Javascript, el propio framework Phaser y el código del juego que vayamos a construir.

Este archivo le podríamos llamar con cualquier nombre que queramos, pero comúnmente usarás "index.html" para que sea el archivo inicial de tu proyecto.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Juego de la bola</title>
</head>
<body>
  
  <script src="//cdn.jsdelivr.net/npm/phaser@3.24.0/dist/phaser.js"></script>
  <script src="index.js" type="module"></script>
</body>
</html>

Como puedes comprobar, este archivo no tiene nada de contenido, ya que no nos hace falta ninguna etiqueta en particular para mostrar el juego. Simplemente colocaremos los mencionados scripts y Phaser se encargará de inyectar la correspondiente etiqueta para que se vea el juego dentro de la página.

El Javascript

Ahora vamos a comenzar a ver el corazón de Phaser, echando un vistazo a nuestro Javascript.

Lo primero, veamos que el archivo que hemos incluido en el HTML por medio de la etiqueta SCRIPT lo hemos cargado como módulo (fíjate en el type="module").

<script src="index.js" type="module"></script>

El type="module" no es en realidad una restricción de Phaser, es decir, en realidad no es necesario para que el juego funcione. Lo hemos hecho así para poder hacer imports dentro del código Javascript del juego, así podemos crear distintos archivos de código con las distintas partes, de modo que podremos tener un código más mantenible.

Debes tener en cuenta que si usas type="module" estás restringiendo tu Javascript para poder usarlo solamente con navegadores que tengan la capacidad de usar ES6 modules. Actualmente todos los navegadores lo soportan, pero si quisieras que el juego funcionase en Internet Explorer, no sería una alternativa, o tendrías que traspilar el código con algo como Webpack, lo que de momento queda fuera de nuestra intención. Pero vamos, que hoy trabajar con ES6 modules es de lo más normal y muy aconsejable.

Ahora veamos el código de nuestro archivo index.js:

import { Game } from './game.js';

const config = {
  type: Phaser.AUTO,
  width: 800,
  height: 500,
  scene: [Game],
  physics: {
    default: 'arcade',
    arcade: {
      gravity: { y: 400 },
      debug: false
    }
  }
}

var game = new Phaser.Game(config);

Primero importamos una declaración llamada "Game" desde el archivo "game.js". En seguida veremos el código de ese archivo, pero os adelantamos que aquí tendremos una clase (de programación orientada a objetos) que implementa la escena principal del juego.

Luego tenemos toda una declaración de la configuración del juego. En ella encontramos varios detalles interesantes:

type: Phaser.AUTO,

Esto indica que Phaser podrá usar tanto canvas como WebGL, según el navegador sea o no compatible con uno u otro. WebGL es mucho más potente y ofrece un mayor rendimiento, pero no está todavía disponible en todos los navegadores. Los más antiguos, usarán canvas.

Luego encontramos los valores de anchura y altura del juego. Pueden ser fijos como en esta ocasión, aunque Phaser también puede hacer un escalado en función del dispositivo.

width: 800,
height: 500,

A continuación encontramos una declaración de todas las escenas que componen el juego. Cada escena puede funcionar de manera más o menos autónoma y, por supuesto, podemos compartir datos y enviar mensajes de una a otra.

scene: [Game],

De momento tenemos una única escena en el juego, que será suficiente para comenzar. Como puedes ver, las escenas se entregan en un array. En ese array colocamos cada una de las clases que tienen nuestras escenas. En este caso enviamos en el array una casilla llamada "Game", que es la clase importada en la primera línea.

También es muy interesante la declaración de las físicas del juego,

physics: {
  default: 'arcade',
  arcade: {
    gravity: { y: 400 },
    debug: false
  }
}

En ella estamos indicando que la física será por defecto "arcade", que es la más fácil para comenzar a desarrollar nuestro juego. Arcade incluye movimiento, colisiones, gravedad y en general todo lo que necesitarías para un juego de plataformas. De todos modos, Phaser admite hasta 4 tipos distintos de física.

La gravedad en nuestro caso la hemos ajustado a 400, que será el empuje de los elementos hacia el suelo, en la vertical. A mayor valor, más rápido caen los objetos al suelo, aunque la velocidad también dependerá de la otros factores, como un hipotético desplazamiento hacia abajo, la fuerza de un salto, etc.

Por último tenemos la creación del juego propiamente dicha, que recibe simplemente el objeto de configuración del mismo.

var game = new Phaser.Game(config);

Con esto arrancará el juego, mostrando la escena que tengamos definida en la primera casilla del array "scenes" que hemos entregado en la configuración.

Una escena sencilla

Para poder ver algo, y comprobar que el juego está funcionando, vamos a definir una escena rápidamente, aunque solamente con un par de imágenes estáticas por el momento.

export class Game extends Phaser.Scene {

  constructor() {
    super({ key: 'game' });
  }

  preload() {
    this.load.image('background', 'images/background.png');
    this.load.image('gameover', 'images/gameover.png');
  }

  create() {
    this.add.image(410, 250, 'background');
    this.gameoverImage = this.add.image(400, 90, 'gameover');
  }

}

Vamos comentando cada parte de esta clase para que lo entendamos mejor.

export class Game extends Phaser.Scene {

Aquí usamos "export" para que esta clase se pueda conocer desde fuera. Además creamos una nueva clase que se llama "Game" que extiende por herencia la clase Phaser.Scene.

Phaser.Scene contiene una escena básica y nosotros la extendemos para darle la funcionalidad que requiere nuestro juego.

constructor() {
    super({ key: 'game' });
}

El constructor hace una llamada al constructor de la clase padre, pasando el nombre de la escena. Este nombre nos servirá para referirnos a la escena siempre que sea necesario, por ejemplo para escuchar mensajes, para cambiar la escena activa, etc.

preload() {
    this.load.image('background', 'images/background.png');
    this.load.image('gameover', 'images/gameover.png');
}

El método preload es uno de los métodos básicos del ciclo de vida de una escena. En él podemos hacer la precarga de todos los elementos que requiere esta escena para funcionar, como imágenes, sonidos, etc. Incluso podemos hacer la precarga de los elementos que van a requerir otras escenas más adelante, así evitamos esperas durante el juego, porque tendremos cargadas todas las cosas que serán necesarias.

Es importante darse cuenta que cada uno de los recursos cargados tiene un nombre. Por ejemplo en este caso tenemos dos imágenes. A la primera la hemos llamada "background" y a la segunda "gameover". Estos nombres son únicos y podemos acceder a los recursos asociados a lo largo de todo el juego.

create() {
    this.add.image(410, 250, 'background');
    this.gameoverImage = this.add.image(400, 90, 'gameover');
}

El método create se ejecuta cuando ya se han cargado todos los elementos y tiene el código necesario para crear la escena. En este método se colocarán todos los elementos necesarios, como el jugador, las plataformas, enemigos, decorados, etc.

En nuestro caso simplemente hemos agregado dos imágenes. Fíjate que algunas ocasiones las imágenes las tenemos que almacenar en propiedades del objeto, porque así podremos referirnos a ellas más adelante, mostrarlas, ocultarlas, cambiar su posición, definir colisiones.... De hecho, lo normal es justamente que las guardemos como propiedades del objeto escena, porque generalmente necesitamos acceder a ellas para muchas cosas. Sin embargo, hay elementos como el fondo que quizás no hace falta hacer nada con él, porque siempre va a estar ahí y por eso simplemente lo hemos añadido y punto.

Sobre los elementos hay que comentar que se colocan en una posición, que tiene como eje de coordenadas la esquina superior izquierda. Pero el eje de referencia que posicionamos es el centro de la imagen. Por ejemplo, en el caso de la imagen de "gameover" estamos colocándola para que el centro de esta imagen se sitúe en el punto 400x90 con respecto a la esquina superior izquierda. Como el juego mide 800 x 500, la imagen aparecerá centrada, y bastante cerca del borde superior.

Tal cual está este proyecto observaríamos la imagen del fondo y encima otra imagen con el motivo del "game over".

Introducción a Phaser

Archivos y carpetas hasta el momento

Para que puedas verificar la marcha de tu trabajo, puedes ejecutar tu juego ahora mismo. Pero claro, necesitarás las imágenes y que estén en la carpeta correcta. Para tu referencia este es el árbol de archivos y carpetas hasta el momento.

Estructura de carpetas del juego Phaser3

En este enlace de Github te hemos dejado el código y las imágenes del juego, tal como lo hemos montado hasta este punto.

En el siguiente artículo profundizaremos en la escena del juego, para aportarle más elementos y, por supuesto, algo de interactividad.

Videotutorial de Phaser

Te presentamos un videotutrial de Phaser 3 que hemos publicado en Youtube, que cubre los tres primeros capítulos del Manual de Phaser, en los que crearemos un juego, una plataforma que podremos mover con los cursores del ratón y una bola para hacerla botar sobre la plataforma. Algo sencillo pero jugable!, que te servirá para reforzar las explicaciones de estos artículos.

Miguel Angel Alvarez

Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...

Manual