Soporte para teclado con Pixi.js usando pixi-keyboard

Como Pixi.js es básicamente un renderer, solo tiene una función, que es esa, renderizar; por lo que carece de muchas de las caracteristicas que podemos considerar necesarías para desarrollar un juego. Dependiendo del juego que queramos desarrollar, una de esas caracteristicas podría ser soporte de teclado.

La opción más común es utilizar directamente los eventos keydown y keyup de window, controlando nosotros directamente el estado de las teclas, comprobación de códigos de tecla, etcétera.

Es aquí donde podría ser útil tener un manager que nos de todo el "trabajo" hecho, y nos permita hacer cosillas más complejas con el fin de agilizar el desarrollo de nuestro juego.

Para ellos vamos a utilizar pixi-keyboard, un módulo que extiende PIXI dotandolo de las caracteristicas necesarías para gestionar el teclado.

Instalación:

Dependiendo de nuestro sistema de trabajo, tenemos dos opciones para "instalar" el módulo.

1- Usando Browserify o Webpack tan solo tenemos que instalar el módulo desde NPM con:

npm install --save-dev pixi-keyboard

Y una vez instalado lo importamos en nuestro script, siempre despúes de haber importado PIXI, nunca antes:

var keyboard = require('keyboard');
//o en es6
import keyboard from 'pixi-keyboard';

Como pixi-keyboard es un modulo preempaquetado, es posible que tengas que añadirlo al parametro noparse de browserify o webpack para evitar errores a la hora de interpretar los requireen el momento que compiles tu paquete.
Si quieres una base de código usando pixi.js con webpack y ES6 lista para trabajar, puedes usar la que he dejado en este post.

2- Si no usas ningún gestor de dependencias y añades tus dependencias directamente desde el código HTML, tan solo tienes que bajar el archivo pixi-keyboard.js del directorio build del repositiorio, y añadirlo justo despúes del script de pixi.js.

El plugin añadirá varias clases al namespace PIXI, como PIXI.KeyboardManager, PIXI.HotKey y PIXI.Key. Además instanciará la clase PIXI.KeyboardManager en PIXI.keyboard, de manera que

El siguiente paso será ejecutar el método update desde el loop de animación que estemos usando en pixi:

//PIXI renderer
var renderer = new PIXI.autoDetectRenderer(800,600);
document.body.appendChild(renderer.view);
var stage = new PIXI.Container();

function animate(){
    window.requestAnimationFrame(animate);
    renderer.render(stage);

    //Añadimos el metodo update de PIXI.keyboard 
    PIXI.keyboard.update();
}
animate();

Y ya hemos terminado, esto es todo lo que necesitamos para utilizar correctamente el plugin.

En PIXI.Key tenemos una lista de alias de diferentes KeyCodes, por ejemplo PIXI.Key.ENTER = 13, así resulta más sencillo de recordar.

El estado de las teclas se divide en tres formas, down que nos indica si una tecla está siendo pulsada, devuelve true siempre que la tecla siga pulsada, pressed que nos indica si una tecla ha sido pulsada, pero solo en el momento de hacerlo, si luego seguimos pulsando la tecla indicará false, y released que nos indica si una tecla ha sido liberada.
Tenemos varias formas para comprobar estos estados, que dependiendo de la situación podremos usar uno u otro método dependiendo de lo que nos convenga.

Comprobando directamente el estado:

Podemos comprobar directamente el estado de una tecla usando los métodos isPressed, isDown e isReleased del objeto PIXI.keyboard. Útil por ejemplo si queremos comprobar el estado dentro de algún metodo step/update de algún actor, para disparar, saltar, etcétera. Veamos un ejemplo:

var myTank = new PIXI.Sprite(texture);

//PIXI no provee de método update por defecto, debes implementarlo tu si es que lo necesitas.
myTank.update = function(delta){
    //Dispara continuamente si espacio está pulsado
    if(PIXI.keyboard.isDown(PIXI.Key.SPACE)){
        console.log('fire fire fire!!!');
    }

    if(PIXI.keyboard.isPressed(PIXI.Key.Z)){
        console.log('Acelerar');
    }else if(PIXI.keyboard.isReleased(PIXI.Key.Z)){
        console.log('Desacelerar');
    }

}
Comprobación mediante eventos:

Una forma más global, sería escuchar los eventos y ejecutar un callback una vez se disparen. Útil en situaciones donde no dependamos directamente de un actor, simulando que escribimos en pantalla, etcétera. Veamos un ejemplo con eventos:

PIXI.keyboard.on('pressed', function(key){
    if(key === PIXI.Key.ESCAPE){
        console.log('cierra la aplicación');
    }
});

PIXI.keyboard.on('down', function(key){
    if(key === PIXI.Key.UP){
        console.log('aumenta el volumen del audio');
    }else if(key === PIXI.Key.DOWN){
        console.log('disminuye el volumen del audio');
    }
});

PIXI.keyboard.on('released', function(key){
    console.log('haz algo impresionante con la tecla ' + key);
});
Usando HotKeys:

Los HotKeys nos permiten crear accesos rápidos a las teclas que nos interesan, para comprobar el estado de manera separada y sencilla. Imagina que uno de tus actores necesita saber el estado de tan solo 4 teclas, como pueden ser W, A, S y D, podríamos crear 4 HotKeys para ello:

var keyA = PIXI.keyboard.getHotKey(PIXI.Key.A);
var keyW = PIXI.keyboard.getHotKey(PIXI.Key.W);
var keyS = PIXI.keyboard.getHotkey(PIXI.Key.S);
var keyD = PIXI.keyboard.getHotKey(PIXI.Key.D);

if(keyW.isDown)console.log('arriba');
if(keyS.isDown)console.log('abajo');

//o comprobanco combinaciones
if(keyA.isDown && keyW.isDown)console.log('diagonal');

Además de los típicos isDown, isPressed e isReleased, también podemos comprobar si las teclas CTRL, SHIFT y ALT están en el estado down directamente desde cualquier HotKey:

if(keyW.isDown && keyW.ctrl){
    console.log('Haz Zoom!');
}else if(keyW.isDown){
    console.log('arriba');
}

var ctrl = keyW.ctrl;
var shift = keyW.shift;
var alt = keyW.alt;
PreventDefault:

Puede ser útil en algunas situaciones prevenir el comportamiento por defecto de ciertas teclas, por ejemplo, en una pagina con scroll puede que no queramos que este suceda al usar las teclas UP y DOWN si estás teclas ya tienen funcionalidades dentro de nuestra aplicación. Podemos prevenirlo así:

PIXI.keyboard.setPreventDefault(PIXI.Key.UP);
PIXI.keyboard.setPreventDefault(PIXI.Key.DOWN);

//Si queremos cancelarlo pasamos false como segundo parametro
PIXI.keyboard.setPreventDefault(PIXI.Key.Up, false);

Como ves la gestión del teclado en desarrollos con pixi.js resulta sencillo con este módulo, y las posibilidades de uso son amplias, espero que os sea de utilidad.

Plugin: https://github.com/Nazariglez/pixi-keyboard