lunes, 1 de agosto de 2016

Texto y tipografías

Un elemento muchas veces menospreciado en los juegos es el manejo de texto en pantalla y las tipografías. En primer lugar hay que diferenciar entre dos tipos de fuentes: vectoriales y bitmap. Las vectoriales son las habituales en el día a día. Las que usamos en Internet, en Word, etc. Se pueden hacer grandes y pequeñas. Hay varios formatos, pero la mayoría son en formato TrueType, OpenType y derivadas. Estas fuentes pueden ser cargadas usando CSS3, pero ten cuidado pues al principio puede que no estén cargadas.

Texto en Phaser: fuentes vectoriales

Las fuentes vectoriales las solemos encontrar en formato TTF (TrueType), OTF (OpenType) o WOFF (versión 1 o 2, son TrueType u OpenType optimizados para la web). Deberemos añadir esto al fichero CSS.

@font-face{
    font-family: 'NombreDeLaFuente';
    src: local('NombreDeLaFuente'), url('fonts/fuente.woff') format('woff');
}
Ahora podemos usar esa fuente para dibujar texto sobre la pantalla.

game.add.text(100,50,"Phaser.js Hispano",{
    font: 'NombreDeLaFuente',
    fontSize: 32,
    fill: 'purple'
});
var texto = game.add.text(200,100,"http://www.phaser-hispano.gq");
texto.font = "Agency FB";
texto.fontSize = 24;
texto.fill = "green";

Texto en Phaser: fuentes de tipo bitmap

En videojuegos también es común usar fuentes de tipo bitmap. Estas son simplemente imágenes de cada caracter.

game.load.bitmapFont('desyrel', 'assets/fonts/bitmapFonts/desyrel.png', 'assets/fonts/bitmapFonts/desyrel.xml');
...
game.add.bitmapText(200, 100, 'desyrel', 'Phaser & Pixi\nrocking!', 64);

Spritesheets

En el tutorial anterior vimos como manejar sprites. Quizá te parezca un proceso muy largo una vez tengas cientos o miles de imágenes. Los spritesheets son la solución.

¿Qué son los Spritesheets?

Los spritesheets son imágenes que contienen imágenes más pequeñas en su interior separadas por una distancia común. Esto es un spritesheet:
Phaser soporta spritesheets el uso de spritesheets en muchos lugares. A la hora de cargarlos deberemos especificarlo.

function preload(){
    ...
    game.load.spritesheet("IDdeSpritesheet","img/ArchivoSpritesheet.png",32,32,64,0,0);
    // ID de spritesheet, archivo, ancho de cada imagen, alto de cada imagen, número de imágenes (-1 las buscará automáticamente), espacio en píxeles que hay que dejar de margen al empezar el archivo (margin), espacio en píxeles de separación entre imágenes (spacing)
    ...
}
Cuando queramos usar alguna de las imágenes indivualmente, por ejemplo, cuando creamos un Sprite, debemos especificar el ID del Spritesheet así como el número asignado.

game.add.sprite(100,50,"IDdeSpritesheet",12);
Para contar llamaremos 0 a la imagen situada arriba a la izquierda. Seguiremos hacia la derecha y cuando acabemos la línea bajaremos a la siguiente (igual que si leyésemos un texto).

Creando Spritesheets

Con ImageMagick

Si tienes instalado ImageMagick es fácil generar nuevos spritesheets desde la línea de comandos con montage.
montage ImagenPrimera.png ImagenSegunda.png ImagenTercera.png -tile 4x4 -geometry 128x128+0+0 -background transparent Spritesheet.png
Indicamos las imágenes independientes al principio, con -tile indicamos como van a estar organizadas las imágenes, en este caso la rejilla será de 4 filas y 4 columnas. -geometry indica el tamaño de cada imagen (128 píxeles de ancho y alto). El fondo con -background se asigna a transparente y finalmente indicamos donde vamos a guardar el resultado.

Con GIMP

Con GIMP tendrás que copiar manualmente cada archivo a su lugar correspondiente en un nuevo archivo con las rejillas activadas.

Otros programas

Hay más programas, algunos de pago como TexturePacker o SpriteSheet Packer. Sin embargo hay que tener cuidado pues TexturePacker puede generarnos TextureAtlas en vez de SpriteSheets. Phaser soporta ambos pero no del mismo modo, aquí solo hemos visto los Spritesheets.

Sprites

Hemos visto como crear rectángulos y otras formas geométricas simples, pero posiblemente también quieras cargar imágenes. En Phaser es muy sencillo. Recuerda en el tutorial de cargar recursos como cargábamos imágenes o audios. Si recuerdas era algo parecido a esto:


function preload(){
   ...
   game.load.image("MisterPhaser","img/MisterPhaser.png");
   ...
}
Al recurso, en este caso una imagen PNG, le asignamos un ID ("MisterPhaser" en el ejemplo). Ahora para añadir la imagen a la pantalla simplemente la añadimos, por ejemplo, dentro de la función create.


function create(){
    ...
    var sprite = game.add.sprite(300,100,"MisterPhaser");
    ...
}
Se añadirá el sprite con una imagen de ID "MisterPhaser" en las coordenadas X e Y indicadas

¿Qué es un Sprite?

No, no es la bebida. En Phaser un sprite podemos entenderlo como una superimagen o una "imagen con extras". A diferencia de una simple imagen que dibujemos en pantalla (que en Phaser también existen y se pueden hacer), un sprite contiene:
  • Funcionalidad para el motor de físicas
  • Funcionalidad para gestionar el input, la entrada de datos
  • Funcionalidad para gestionar eventos
  • Soporte para animaciones
  • Y mucho más
Por defecto todas estas funcionalidades extras vienen desactivadas y requieren de configuración extra.


Input con un Sprite

Vamos a ver como manejar la entrada de datos de un sprite con la funcionalidad de entrada de datos. En primer lugar es necesario activarlo, poniendo inputEnabled = true. Después podemos añadir eventos:


sprite.inputEnabled = true;
sprite.events.onInputDown.add(function(){
    // el sprite ha sido pulsado on el ratón o tocado en una pantalla táctil
});

Manipulando el tamaño del sprite

Es posible que el sprite sea demasiado grande o pequeño para la pantalla a la que lo estas añadiendo. En ese caso usa las propiedades width y height.

sprite.width = 200;
sprite.height = 200;

Rotando el sprite

Puedes usar radianes o grado sexagesimales. Las operaciones con radianes son ligeramente más rápidas, pero mucha gente está acostumbrada a usar grados sexagesimales por lo que se incluye su soporte aunque debe realizar la conversión a radianes.

sprite.rotation = Math.PI/6; // En radianes
sprite.angle = 30; // En grados sexagesimales

Propiedades visuales

Los sprites vienen con un conjunto de herramientas para modificar el aspecto final. Podemos por ejemplo tintar una textura con tint y especificando un color en hexadecimal

sprite.tint = 0xAA0000;
También es posible cambiar la imagen del sprite una vez ha sido creado con loadTexture.

sprite.loadTexture("CocheDeMisterPhaser");
Otra propiedad interesante es smoothed. Si queremos un elemento Pixel Art es importante que esté en false, de lo contrario Phaser tratará de redondear las esquinas.

Propiedades del juego

Los sprites son los personajes, las balas, los coches, las cajas de Mario Bros, ... todo son sprites. Phaser ha añadido unas propiedades configurables, de cuyo uso únicamente decidimos nosotros, para albergar los datos específicos de cada sprite.

La propiedad data esta vacía y es totalmente configurable. Podemos crear, editar y destruir variables dentro de ella sin afectar al funcionamiento de Phaser. Además, incluye ya prehechas las propiedades damage, heal, health, maxHealth, setHealth.


sprite.data.nombre = "Teresa";
sprite.data.inventario = ["VISA", "Teléfono móvil"];
sprite.damage = 50;
sprite.maxHealth = 100;
El coche ha sido rotado, deformado y tintado