viernes, 26 de mayo de 2017

Usando mapas de Tiled en Phaser

Retomamos el tutorial de Tiled. Deberíamos tener ya un mapa de Tiled con dos capas (Paredes y Suelo), una con el atributo pasable en desactivado y en otro no.

Vamos a Tiled y exportamos el archivo en formato JSON (CSV también nos valdría pero no lo he probado).

Cargando el tilemap y el tileset

En la función preload cargamos el JSON con la descripción del mapa (tilemap) y las imágenes que usa el mapa (tileset). Es muy parecido a como vimos en Iniciar Phaser.js.

function preload(){
    game.load.tilemap("Mapa","Mapa.json",null,Phaser.Tilemap.TILED_JSON);
    game.load.image("Tileset-1","Wall.png");
Ahora creamos los objetos en pantalla dentro de la función create.

var map, paredes, suelo;

function create(){
    map = game.add.tilemap("Mapa");
    map.addTilesetImage("Wall","Tileset-1"); // El nombre Wall hace referencia a como se llama el tileset en Tiled
    suelo = map.createLayer("Suelo"); // El nombre hace referencia a como se llama la capa en Tiled
    paredes = map.createLayer("Paredes");
}
Es importante usar los nombres que hemos usado en Tiled previamente. Además, el orden en que llamemos a createLayer importa, ya que no tiene en cuenta el orden de las capas que hubiese en Tiled.

Colisiones

Vamos ahora a hacer que las paredes sean objetos no atravesables, mientras que el suelo sí lo sea. Para gestionar las físicas vamos a usar Arcade Physics aunque con P2 es parecido.

var map, suelo, paredes, player;

function create(){
    game.physics.startSystem(Phaser.Physics.ARCADE);

    map = game.add.tilemap("Mapa");
    map.addTilesetImage("Wall","Mapa-TileImage");
    suelo = map.createLayer("Suelo");
    paredes = map.createLayer("Paredes");

    console.log("Paredes es pasable?: "+paredes.layer.properties.pasable);
    
    map.setCollisionBetween(1,10000,true,paredes);

    suelo.resizeWorld();
    paredes.resizeWorld();
  
    ... crear player y activar arcade physics en él...
    player = game.add.sprite(100,100,"player");
    game.physics.arcade.enable(player);
}

function update(){
    game.physics.arcade.collide(paredes,player);
}


En la función create he usado la propiedad que definimos en Tiled como pasable. En realidad lo pongo como ejemplo para que se vea como es posible definir atributos arbitrarios en Tiled y acceder a ellos desde Phaser.

La función setCollisionBetween se encarga de que todos cuadrados de la capa paredes se vuelvan infranqueables. Posteriormente en update hacemos la comprobación de física con cada cuerpos ajeno al tilemap que lo necesite, habitualmente el jugador.



Desplegar un juego con Phaser en Netlify

Una vez tengamos acabado el juego necesitamos publicarlo y hacerlo accesible a los demás. Existen varias opciones, desde convertir el juego en app para Android hasta publicarlo en Steam usando Electron. ¿Y si quiero dejar mi juego en una web? Es una opción perfectamente válida que explicaremos ahora.

La búsqueda del hosting

Si has hecho una página web con anterioridad quizá sepas como va. Hay muchos tipos de hosting y un amplio rango de precios. El más simple es el hosting compartido, normalmente con PHP, aunque no lo necesitaremos usar si nuestro juego Phaser no tiene funcionalidades multijugador. También existen máquinas virtuales en cloud, existen los VPS, hay distintos PaaS,... Es un tema bastante complicado. ¿Pero qué necesitamos realmente?

En realidad un juego en Phaser suele ser una página web estática, es decir, un fichero HTML, con JavaScript y los recursos multimedia como imágenes en carpetas próximas al HTML. Salvo que hayas añadido multijugador, tu juego también será así.

Para alojar un sitio web estático existe un hosting muy potente y gratuito llamado Netlify. Netlify solo admite webs estáticos pero es muy rápido (dispone de CDNs repartidos por varios continentes) y seguro (puede generarnos certificados SSL de forma gratuita). No dispone de publicidad ni ninguna otra trampa.



Veamos como funciona Netlify.

Instalando Netlify

El primer paso es registrarse en Netlify, para lo cual no hace falta tarjeta de crédito. Si ves la sección de precios, verás una gran variedad de ellos.
Nosotros vamos a usar Netlify Pages, que son totalmente gratuitas e igual de rápidas. Sinceramente, para alojar juegos de Phaser no vamos a necesitar el resto de cosas que ofrecen los planes de pago.

A continuación vamos a instalar la herramienta de línea de comandos de Netlify, muy útil y que servirá para subir el juego a Netlify. Para ello necesitas tener Node.js instalado y npm (se instala con Node.js). Una vez lo tengas, instalamos netlify-cli con npm.

npm install netlify-cli -g


Veremos algo como esto si todo ha ido bien. Escribe lo siguiente para comprobar que la instalación ha ido bien:

netlify -h

Desplegando en Netlify

Ya tenemos todo listo. Nos desplazamos a la carpeta que contiene el fichero HTML de nuestro juego Phaser (nos desplazamos entre carpetas usando el comando cd). Una vez estes allí ejecuta:

netlify deploy

Se nos abrirá el navegador para que iniciemos sesión y el programa nos hará varias preguntas. Cuando esté todo listo subirá el juego a Netlify.

Si ahora entramos en la web de Netlify podremos ver que efectivamente se ha subido.

Podemos ver la URL donde está alojada la web.


Podemos cambiarle el nombre siempre que esté disponible bajo .netlify.com. También es posible usar nuestro propio dominio, comprado en GoDaddy, 1&1 u otro proveedor. Simplemente tienes que hacer click en Set up domain.

Conclusión

Después de probar varios servicios Netlify es el hosting estático que más me convence. El plan gratuito es muy potente y nos aseguramos una velocidad en la carga del juego envidiable. Por supuesto, con Phaser gozas de libertad y puedes usar cualquier otro hosting. Usa lo que mejor se adapte a ti y a tus usuarios.

domingo, 26 de febrero de 2017

Física: Colisiones de objetos complejos con P2

En este tutorial veremos como implementar colisiones de objetos con P2, el motor de física más avanzado disponible para Phaser. En primer lugar necesitamos los objetos, en mi caso voy a usar este cohete:
En primer lugar necesitamos generar un archivo con la forma del objeto, que sirva para tener los bordes que el motor de física usará. Yo voy a usar Physics Editor, es de pago pero tiene una prueba de uso de 7 días.
La interfaz es muy sencilla. Arrastramos las imágenes de las que queramos generar colisiones a la izquierda. Ahora para generar los bordes usamos la varita mágica. Modificamos el valor de Tolerancia para que el número de vértices sea el menor posible pero aun así coja bien la forma.
Si el trazado automático no funcionase puedes añadir polígonos y círculos así como añadir o eliminar vértices. Cuando ya tenemos la figura vamos a la derecha en Exporter y seleccionamos Phaser (P2). Y pulsamos Publish. Ese archivo JSON contendrá las formas para las colisiones de todos las imágenes cargadas en la columna de la izquierda (en nuestro caso solo contará con una entrada, "cohete").

Ahora vamos a cargar el cohete con sus físicas.

var game = new Phaser.Game(480,320,Phaser.CANVAS,"",{preload: preload, create: create, update: update});

function preload(){
  game.load.image("cohete","cohete.png");
  game.load.physics("fisica","fisica.json");
}

function create(){
  game.physics.startSystem(Phaser.Physics.P2JS);
  game.physics.p2.gravity.y = 1000;
  
  var cohete = game.add.sprite(100,100,"cohete");
  game.physics.p2.enable(cohete);
  cohete.body.clearShapes();
  cohete.body.loadPolygon("fisica","cohete");
}

function update(){

}

Los objetos P2 colisionan solamente entre ellos. Si quieres tener un objeto P2 estático debes ponerlo como static.


cohete.body.static = true;

Puede ajustar algunas propiedades de los cuerpos como la masa:

cohete.body.mass = 50;





El equipo formado por Phaser.js Hispano gana el VallaHackaton 2017

Esta semana se ha celebrado en Valladolid el VallaHackaton, esta vez con temática de videojuegos.
La temática de la game jam era ¡Rómpelos! y finalmente titulamos nuestro juego ¡No lo rompas! El jurado estuvo compuesto por gente de Pyrolite Games y de Demium Games, con la ayuda de Víctor Ferrer de Wave Engine.

La mecánica de ¡No lo rompas! es la de una patata caliente. Es un juego multijugador para dos personas en local. Cada jugador tiene que intentar que el otro rompa la tabla. Para ello el jugador selecciona un objeto de 5 para elegir (cada uno con distinto peso) y lo lanza. Si lo lanza la mal el factor multiplicador de la fuerza será mucho y puede romper la tabla.



Para realizar el juego tuvimos la tarde del jueves y el viernes hasta las 18:00. Originalmente pensamos en una cuerda pero el jurado vino el primer día a comentarnos un par de cosas. Ellos no veían la cuerda como una buena solución y además nos dijeron que teníamos que transmitir un feedback al usuario del estado de la cuerda a los jugadores para que pudieran actuar en consecuencia. Así que optamos por una tabla con diversos estados de fractura, visibles por el número de grietas.

Usamos Phaser con P2 para las físicas. Para escribir mi compañero usó Brackets y yo Visual Studio Code. Los gráficos y animaciones se realizaron con Adobe Illustrator. Para definir las colisiones para P2 usamos Physics Editor. Intentamos usar Git, pero tenemos muy poca experiencia con merges y provocamos conflictos varias veces. Al principio usamos un pincho que pusimos de nombre GIT y finalmente terminamos usando Telegram para pasarnos fragmentos de código.

El mayor problema al que nos enfrentamos tuvo que ver con el escalado de los sprites en Phaser, que no se aplican a la física y nos provocaba extraños errores.
La parte blanca era donde se aplicaba la colisión y la tabla como se puede ver se muestra más a la derecha

Finalmente tuvimos que reescalar los sprites y volver a Physics Editor para generar archivos de colisiones de nuevo.
¡Cuando la física ya funciona bien!
Fue un buen evento y volveré a asistir si es posible el año que viene, aunque no trate de videojuegos. Haciéndolo me he dado cuenta de que me faltan tutoriales sobre P2 en Phaser así que intentaré escribirlos lo antes posible.

sábado, 25 de febrero de 2017

Los Instant Games HTML5 son el futuro de cara a 2017

Las apps con el modelo tradicional de app store no pueden crecer más. En 2016 las apps empezaron a comerse a sí mismas.

Nos hacemos eco de un artículo publicado en LinkedIn Pulse por Alexander Krug, CEO de SOFTGAMES. En él explica que el modelo de las aplicaciones ha empezado a quedarse obsoleto, sobre todo respecto a los juegos. En 2016, el tiempo medio que un usuario medio de teléfono pasaba en apps de juegos ha bajado por primera vez.

Por contra, las aplicaciones de redes sociales y mensajería han aumentado de forma espectacular. ¿Qué es lo que está pasando?

Aplicaciones como Telegram, Kik o BBM han incluido bots y aplicaciones. En el caso de Telegram la plataforma Gamee proporciona juegos instantáneos HTML5. Las ventajas de tener un juego instantáneo HTML5 son muchas:
  • Reducidos tiempos de carga
  • No ocupan espacio
  • No hay que preocuparse de actualizar la aplicación
  • Al estar integradas dentro de una app de comunicación es muy fácil compartir con amigos o retarles.
El mayor problema actualmente de este sistema es el descubrimiento, pues no hay todavía un modo sencillo de que un usuario conozca un juego instantáneo de buenas a primeras.

La oportunidad es grande ahora que empieza a despegar este nuevo ecosistema. Flappy Bird no se hizo popular por la app store, sino porque la gente lo compartió en redes sociales.

Es por ello, concluye Alexander, que los juegos HTML5 que se adapten a este ecosistema se harán cada vez más populares. Su empresa ya ha diseñado más de 400 juegos para estas plataformas pero cualquiera de nosotros puede hacerlo (Y Phaser funciona a la perfección en dispositivos móviles con HTML5 😜)

jueves, 19 de enero de 2017

Animaciones

Los juegos no son juegos si no se siente vida en ellos. ¿O acaso a alguien le gustaría jugar con el Word? Una parte fundamental para dar vida a los juegos son las animaciones. Las animaciones nos hacen ver que el mundo del juego no es estático.

Un Spritesheet específico

En los juegos 2D normalmente animamos los sprites cambiándolos completamente con otro sprite similar. Normalmente todas las imágenes que van a representar un sprite se almacenan en el mismo archivo. Recuerda la lección sobre Spritehsheets.

Para este ejemplo voy a usar este spritesheet.
Es obra de Brett Steele. He hecho una modificación para que el color azul se vuelva transparente.

Generando animaciones

En primer lugar cargamos el spritesheet.


    function preload() {
        game.load.spritesheet("mujer", "mujer-alpha.png", 32, 64);
    }

Después añadimos las animaciones al sprite. El primer argumento es el nombre de la animación, el segundo es la lista de frames de los que se compone la animación. Estos son los frames del spritesheet. Por último la velocidad de la animación y si queremos que se repita.

function create() {
        cursor = game.input.keyboard.createCursorKeys();
        mujer = game.add.sprite(100, 100, "mujer");
        mujer.frame = 10;

        mujer.animations.add("left", [24, 25, 26, 27, 28, 29, 30, 31], 10, true);
        mujer.animations.add("right", [16, 17, 18, 19, 20, 21, 22, 23], 10, true);
        mujer.animations.add("up", [0, 1, 2, 3, 4], 10, true);
        mujer.animations.add("down", [8, 9, 10, 11, 12], 10, true);
    }

Después lo podemos usar en la función update donde arrancamos y paramos las animaciones según la entrada de teclado.


    function update() {
        if (cursor.left.isDown) {
            mujer.animations.play("left");
            mujer.x--;
        } else if (cursor.right.isDown) {
            mujer.animations.play("right");
            mujer.x++;
        } else if (cursor.up.isDown) {
            mujer.animations.play("up");
            mujer.y--;
        } else if (cursor.down.isDown) {
            mujer.animations.play("down");
            mujer.y++;
        } else {
            mujer.animations.stop();
            mujer.frame = 10;
        }
    }
Con <sprite>.frame podemos ajustar manualmente el frame de la animación, muy útil cuando hemos parado la animación.

Resultado

Ahora podemos ver el resultado.

viernes, 13 de enero de 2017

Diferencia entre Arcade, Ninja y P2 physics en Phaser

Mucha gente tiene dudas de por qué hay tres motores de física en Phaser. Y sin contar Box2D que es un plugin de pago para Phaser. ¿Cuáles son las diferencias entre estos tres motores?


Arcade Physics

Arcade Physics únicamente detecta colisiones de tipo AABB. Es decir, se generan rectángulos y se comprueba si se superponen entre sí. En ese caso se entiende que se ha producido una colisión. Es un sistema muy rápido pero no es muy preciso (no todos los sprites son rectángulos perfectos). Es el único motor que además cuenta soporte en la API de Partículas de Phaser.

Ninja Physics

Ninja Physics es más preciso que Arcade. Es capaz de manejar formas complejas y rotaciones. Se recomienda para el diseño de niveles, por ejemplo, de un plataformas.

P2 Physics

P2 es un motor físico completo, con más cosas aparte de colisiones complejas como fuerzas y aceleraciones. Es el más lento de los tres pero es el más completo. Se recomienda cuando tenemos objetos a los que queremos dotar de física completa, por ejemplo, los pájaros de Angry Birds.