<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Nazarí González]]></title><description><![CDATA[Blog sobre desarrollo de apps y juegos HTML5, frontend y backend  Javascript, node.js y otras hierbas...]]></description><link>http://www.nazariglez.com/</link><generator>Ghost 0.5</generator><lastBuildDate>Tue, 11 Apr 2023 21:43:49 GMT</lastBuildDate><atom:link href="http://www.nazariglez.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Object Pool en Javascript de manera sencilla]]></title><description><![CDATA[<p>La gestión de memoria en lenguajes como <strong>Javascript</strong>, los cuales están basados en "<em><a href="https://es.wikipedia.org/wiki/Recolector_de_basura">Recolectores de Basura</a></em>" (<em>Garbage Collector</em>) escapa en gran parte al control del programador, ya que es el propio mecanismo del <strong>Garbage Collector</strong> el que decide en que momento ha de ejecutarse para compactar la memoria.</p>

<p>Este proceso automatizado, en principio no supone ningún problema, puesto que por lo general es una gestión imperceptible para el usuario final, pero hay ciertos casos donde puede ser útil tener más control de la memoria. Como por ejemplo, en aplicaciones donde se usen algunos objetos que son muy costosos de instanciar, o en el desarrollo de videojuegos donde se destruyen y creen constantemente actores, objetos de calculo, etcétera, provocando caídas en los <strong>FPS</strong> (<em>frames por segundo</em>) cuando el Garbage Collector trabaja.</p>

<p>El patrón de diseño <strong>Object Pool</strong> puede sernos de utilidad en estos casos, ya que nos permite "<em>cierto</em>" control de la memoria evitando que los objetos se destruyan, y por lo tanto evitando darle trabajo al Garbage Collector. </p>

<p>Básicamente, un Object Pool no es otra cosa que una lista de "<em>instancias</em>" de un mismo objeto, el cual nos permite reciclar continuamente estas instancias. La manera de hacer esto es sencilla, cuando necesitamos una instancia de nuestro objeto, se la pedimos al Pool, el cual, cogería la primera de su lista si tuviera, o crearía una nueva instacia si no tuviera ninguna almacenada, una vez entregada, elimina la referencia de su lista. Cuando nuestra aplicación ha terminado con esta intancia, no la destruimos, sino que la devolvemos al Pool, de manera que esta podrá ser reutilizada la próxima vez que se pida una nueva instancia.</p>

<p>Hay muchas formas de crear y gestionar un Object Pool, pero me gustaría compartir un pequeño modulo que ya hace todo el trabajo para nosotros. </p>

<p>Si estamos usando <strong><a href="https://nodejs.org/en/">Node.js</a></strong>, <strong><a href="http://www.nazariglez.com/2015/02/19/primeros-pasos-con-browserify/">Browserify</a></strong>, o <strong><a href="https://webpack.github.io/">Webpack</a></strong> podemos instalarlo desde <strong>NPM</strong>:</p>

<pre><code>npm install --save obj-pool
</code></pre>

<p>Y requerirlo así:</p>

<pre><code>var ObjPool = require('obj-pool');
</code></pre>

<p>También podemos añadir directamente <a href="https://raw.githubusercontent.com/Nazariglez/obj-pool/master/build/obj-pool.js">el script</a> en nuestro HTML, haciendo que <code>ObjPool</code> sea añadido a <code>window</code>:</p>

<pre><code>if(ObjPool)console.log('todo ok!');
</code></pre>

<p>Su uso es bastante simple, tan solo debemos de instanciar nuestro Pool pasandole el constructor del objeto que queremos almacenar:</p>

<pre><code>var myPool = new ObjPool( MyObject );
</code></pre>

<p>De esta forma, el pool creará las instancias según las demandemos con el método <code>.alloc()</code>:</p>

<pre><code>var myInstance = myPool.alloc(); 
//Hago lo que quiera con myInstance
</code></pre>

<p>Y una vez hemos terminado con la instancia en cuestión, la devolvemos al Pool con <code>.free()</code> y eliminamos la referencia de nuestro código:</p>

<pre><code>myPool.free(myInstance);
myInstance = null;

//Si el scope es local, no haría falta eliminar la referencia
</code></pre>

<p>Simple ¿verdad?, ahora pongamos el caso de que no quieres que las instancias se creen bajo demanda, puesto que pueden ser muchas y muy costosas de instanciar, y prefieres controlar el momento de su creación, para esto podemos pasarle como segundo parámetro a <code>ObjPool</code> <code>{ amount: N }</code>, de esta forma se crearán N instancias de nuestro objeto al crear el Pool:</p>

<pre><code>//Crea un pool con 100 instancias de MyObject
var myPool = new ObjPool( MyObject, { amount: 100});
</code></pre>

<p>De esta forma tendremos 100 instancias a nuestra disposición al crear el pool, y en caso de que todas se usen, se empezarían a crear nuevas bajo demanda. Si por el contrario, no queremos que se instancien de golpe en la creación del pool, y preferimos otro momento, podemos usar el método <code>.generate( amount )</code> para gestionarlo:</p>

<pre><code>var myPool = new ObjPool( MyObject );
//Hago cosas
myPool.generate(100); // Genero 100 nuevas instancias que se almacenan en el pool
</code></pre>

<p>Pongamos ahora que queremos crear un Pool de un objeto al que necesitamos pasarle parámetros al instanciarlo, para ello podemos indicarle como segundo parámetro al <code>ObjPool</code> <code>{ args : [params...]}</code>, usemos por ejemplo la clase <code>Audio( src )</code>:</p>

<pre><code>//Creamos un pool de Audios con './assets/audio.mp3' como src
var myPool = new ObjPool( Audio, {args: ['./assets/audio.mp3')]});
</code></pre>

<p>Podemos pasarle todos los parámetros que queramos a nuestro objeto separando estos con comas (<em>,</em>) dentro del array de <code>args</code>.</p>

<p>Además podremos comprobar en todo momento cuantas instancias tiene el pool mediante <code>.length</code>:</p>

<pre><code>if(myPool.length === 0)console.log('vacío');
</code></pre>

<p>Y cuando terminemos, podremos eliminar la lista de instancias con <code>.clear()</code>, dandole así nuevamente trabajo al Garbage Collector. En el caso de un juego, podríamos aprovechar cargas entre niveles, o momentos similares para limpiar los pools si fuera necesario, momentos donde algún que otro parón no sea molesto para el usuario.</p>

<p>También en algún momento podríamos necesitar de realizar acciones cuando el pool nos entrega la instancia y cuando la devolvemos de vuelta al pool, acciones como inicializar y resetear el objeto por ejemplo. Para estos casos, el pool buscará los métodos <code>.init()</code> y <code>.reset()</code> del objeto que hemos usado, y los ejecutará si estos existieran:</p>

<pre><code>function MyEntity(){
}

MyEntity.prototype.constructor = MyEntity;

MyEntity.prototype.init = function(){
    //Hacemos cualquier acción al salir del pool
}

MyEntity.prototype.reset = function(){
  //Hacemos cualquier acción al volver al pool
}

var pool = new ObjPool(MyEntity);
var entity = pool.alloc(); //Ejecutará .init();
pool.free(entity); //Ejecutará .reset();
</code></pre>

<p>Para terminar os dejo el enlace al modulo den <strong>Github</strong>, donde podréis consultar la documentación, mejorarlo, etcétera. Espero que os sea de utilidad!</p>

<p><strong>ObjPool en Github</strong>: <a href="https://github.com/Nazariglez/obj-pool">https://github.com/Nazariglez/obj-pool</a></p>]]></description><link>http://www.nazariglez.com/2016/02/14/object-pool-en-javascript-de-manera-sencilla/</link><guid isPermaLink="false">ca5f2c5b-79b4-46c0-90e7-57eca9d7b3b8</guid><category><![CDATA[Javascript]]></category><category><![CDATA[npm]]></category><category><![CDATA[objetos]]></category><category><![CDATA[games]]></category><category><![CDATA[pool]]></category><category><![CDATA[objpool]]></category><dc:creator><![CDATA[Nazarí Glez]]></dc:creator><pubDate>Sun, 14 Feb 2016 19:12:35 GMT</pubDate></item><item><title><![CDATA[Soporte para teclado con Pixi.js usando pixi-keyboard]]></title><description><![CDATA[<p>Como <a href="http://www.pixijs.com/">Pixi.js</a> 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.</p>

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

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

<p>Para ellos vamos a utilizar <a href="https://github.com/Nazariglez/pixi-keyboard">pixi-keyboard</a>, un módulo que extiende <strong>PIXI</strong> dotandolo de las caracteristicas necesarías para gestionar el teclado.</p>

<h5 id="instalacin">Instalación:</h5>

<p>Dependiendo de nuestro sistema de trabajo, tenemos dos opciones para <em>"instalar"</em> el módulo.</p>

<p><strong>1-</strong> Usando <a href="http://www.nazariglez.com/2015/02/19/primeros-pasos-con-browserify/">Browserify</a> o <a href="https://webpack.github.io/">Webpack</a> tan solo tenemos que instalar el módulo desde <a href="https://www.npmjs.com/">NPM</a> con:</p>

<pre><code>npm install --save-dev pixi-keyboard
</code></pre>

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

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

<p><em>Como <code>pixi-keyboard</code> es un modulo preempaquetado, es posible que tengas que añadirlo al parametro <code>noparse</code> de browserify o webpack para evitar errores a la hora de interpretar los <code>require</code>en el momento que compiles tu paquete. <br>
Si quieres una base de código usando pixi.js con webpack y ES6 lista para trabajar, puedes usar la que he dejado en <a href="http://www.nazariglez.com/2016/01/31/pixi-js-con-ecmascript-2015-es6/">este post</a>.</em></p>

<p><strong>2-</strong> 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 <code>pixi-keyboard.js</code> del directorio <a href="https://github.com/Nazariglez/pixi-keyboard/tree/master/build">build del repositiorio</a>, y añadirlo justo despúes del script de pixi.js.</p>

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

<p>El siguiente paso será ejecutar el método update desde el <a href="http://www.nazariglez.com/2016/01/24/controlando-el-requestanimationframe-en-pixi-con-pixi-animationloop">loop de animación</a> que estemos usando en pixi: </p>

<pre><code>//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();
</code></pre>

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

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

<p>El estado de las teclas se divide en tres formas, <code>down</code> que nos indica si una tecla está siendo pulsada, devuelve true siempre que la tecla siga pulsada, <code>pressed</code> 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 <code>released</code> que nos indica si una tecla ha sido liberada. <br>
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.</p>

<h6 id="comprobandodirectamenteelestado">Comprobando directamente el estado:</h6>

<p>Podemos comprobar directamente el estado de una tecla usando los métodos <code>isPressed</code>, <code>isDown</code> e <code>isReleased</code> del objeto <code>PIXI.keyboard</code>. Ú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:</p>

<pre><code>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');
    }

}
</code></pre>

<h5 id="comprobacinmedianteeventos">Comprobación mediante eventos:</h5>

<p>Una forma más <em>global</em>, 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:</p>

<pre><code>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);
});
</code></pre>

<h5 id="usandohotkeys">Usando HotKeys:</h5>

<p>Los HotKeys nos permiten crear <em>accesos</em> 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:</p>

<pre><code>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 &amp;&amp; keyW.isDown)console.log('diagonal');
</code></pre>

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

<pre><code>if(keyW.isDown &amp;&amp; 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;
</code></pre>

<h5 id="preventdefault">PreventDefault:</h5>

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

<pre><code>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);
</code></pre>

<p>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.</p>

<p><strong>Plugin</strong>: <a href="https://github.com/Nazariglez/pixi-keyboard">https://github.com/Nazariglez/pixi-keyboard</a></p>]]></description><link>http://www.nazariglez.com/2016/02/07/soporte-para-teclado-con-pixi-js-usando-pixi-keyboard/</link><guid isPermaLink="false">22fd8f65-a95c-4219-9ca0-8274a7bb1a36</guid><category><![CDATA[HTML5]]></category><category><![CDATA[pixi]]></category><category><![CDATA[games]]></category><category><![CDATA[keyboard]]></category><dc:creator><![CDATA[Nazarí Glez]]></dc:creator><pubDate>Sun, 07 Feb 2016 21:03:54 GMT</pubDate></item><item><title><![CDATA[Pixi.js con ECMAScript 2015 (ES6)]]></title><description><![CDATA[<p>En Junio del 2015 fue aprobada la versión 6 de <strong>ECMAScript</strong>, que es el estándar en el que se basa Javascript (<em>realmente ECMAScript es el lenguaje y Javascript un dialecto de este</em>). Lo interesante de este nuevo estandar es que supone un cambio enorme en cuanto a la versión 5. Introduce muchísimas mejoras convirtiendo a Javascript en un lenguaje mucho más potente y desde mi punto de vista más ordenado, al permitir de manera sencilla la creación de módulos y la programación orientada a objetos.</p>

<p>Precisamente por esto, lo veo como una opción perfecta para usarlo en los desarrollos con <strong><a href="http://www.pixijs.com/">Pixi.js</a></strong>. Normalmente cuando pienso en programar un juego, divido mentalmente todo en objetos, ya sean objetos que se van a renderizar o no, lo ideal para mí es tenerlos bien definidos y separados por ficheros, de manera que me resulte relativamente sencillo mantener el juego, ampliarlo, modificarlo, etcétera. </p>

<p>Hasta el momento organizaba mi código con gestores de tareas como pueden ser <a href="http://www.nazariglez.com/2014/07/21/primeros-pasos-con-gulp-js/">Gulp.js</a> o <a href="http://gruntjs.com/">Grunt</a> junto con <a href="http://www.nazariglez.com/2015/02/19/primeros-pasos-con-browserify/">Browserify</a>, y programaba orientado a objetos de la manera típica:</p>

<pre><code>function Batman(){
    this.name = "Batman";
}

Hero.prototype.constructor = Hero;

Hero.prototype.sayHello = function(){
    console.log("I'm " + this.name + "!");
}

var batman = new Batman();
</code></pre>

<p>Pero esto es mucho más sencillo con <strong>ES6</strong>:</p>

<pre><code>class Batman(){
    constructor(){
        this.name = "Batman";
    }

    sayHello(){
        console.log(`I'm ${this.name}!`);
    }
}

let batman = new Batman();
</code></pre>

<p>Por supuesto, esto no es todo, las ventajas de ES6 son muchísimas, quizás más adelante me anime a hacer un post sobre el tema, pero de momento tienes toda la información sobre <strong>ES6</strong> <a href="http://www.ecma-international.org/ecma-262/6.0/">aquí</a>, y si buscas en google hay muchísimos sitios ofreciendo pequeñas introducciones y guías sobre el estándar. </p>

<p>El porqué seguimos usando ES5 ahora mismo es simple, porque todo estándar debe ser implementado, actualmente los navegadores y Node.js están poco a poco implementando características de ES6, pero aún estamos lejos de tener soporte completo en todas las plataformas.</p>

<p>Aquí es donde entra en juego <strong><a href="https://babeljs.io/">Babel</a></strong>. Babel es básicamente un transpilador que usa código Javascript en ES6 como entrada, y devuelve a la salida el mismo código en ES5, de manera que puedes programar usando el nuevo estándar, y conseguir que el código resultante sea ejecutable en todas las plataformas actuales. </p>

<p>Usando <strong>Babel</strong> y <strong><a href="https://webpack.github.io/">Webpack</a></strong> he montado un <em>boilerplate</em> para poder <strong>usar Pixi.js usando ES6</strong> en pocos pasos. El único requisito es tener instalado <strong>Webpack</strong> en global, para ello (<em>si no lo tienes ya</em>) hacemos:</p>

<pre><code>npm install webpack -g
</code></pre>

<p>Ahora clonamos el repositorio del boilerplate:</p>

<pre><code>git clone https://github.com/Nazariglez/es6-pixi-bolierplate.git
</code></pre>

<p>Y lo instalamos:</p>

<pre><code>npm install
</code></pre>

<p>Y listo, en el directorio <code>src</code> tenemos todo el código en ES6 y en el directorio <code>build</code> tendremos el bundle de nuestra aplicación. Como podrás ver ya hay un pequeño ejemplo creado que puedes usar como punto de partida.</p>

<p>Para generar el bundle minificado tan solo debemos ejecutar <code>npm run build</code>, y si queremos que el bundle se genere automáticamente cada vez que cambiamos algo en algún modulo, o cuando añadimos alguno nuevo, debemos usar <code>npm start</code> o <code>npm run dev</code>. </p>

<p>Como ya te imaginarás puedes usar cualquier modulo que se encuentre en <strong><a href="https://www.npmjs.com/">NPM</a></strong>, es la magia de <strong>Webpack</strong> y <strong>Browserify</strong>, por ejemplo, queremos añadir <code>lodash</code> a nuestra app:</p>

<pre><code>npm install --save-dev lodash
</code></pre>

<p>Y lo importamos desde cualquier modulo de nuestra aplicación:</p>

<pre><code>import _ from 'lodash';
</code></pre>

<p>Y eso es todo, espero que os sea útil y os animéis a usar Pixi.js con ES6.</p>

<p><strong>Repositorio</strong>: <a href="https://github.com/Nazariglez/es6-pixi-bolierplate">https://github.com/Nazariglez/es6-pixi-bolierplate</a></p>]]></description><link>http://www.nazariglez.com/2016/01/31/pixi-js-con-ecmascript-2015-es6/</link><guid isPermaLink="false">e888f788-e56f-4bb3-8d5e-73f18e06727a</guid><category><![CDATA[npm]]></category><category><![CDATA[pixi]]></category><category><![CDATA[babel]]></category><category><![CDATA[es6]]></category><category><![CDATA[ecmascript2015]]></category><category><![CDATA[webpack]]></category><dc:creator><![CDATA[Nazarí Glez]]></dc:creator><pubDate>Sun, 31 Jan 2016 20:55:30 GMT</pubDate></item><item><title><![CDATA[Controlando el requestAnimationFrame en pixi.js con pixi-animationloop]]></title><description><![CDATA[<p>Cuando creamos un juego o una animación usando el canvas de <strong>HTML5</strong>, sea en 2dContext o usando WebGL, tenemos varías opciones para crear el loop de animación, entre las que se encuentran <a href="https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval">setInterval</a>, y <a href="https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame</a>.</p>

<p>Durante mucho tiempo setInterval fue la opción más usada, definíamos el tiempo que debía durar el frame y listo, pero no era lo más optimo, así que los navegadores empezaron a incorporar <strong>requestAnimationFrame</strong>, su función es similar al setInterval, salvo que aquí no podemos controlar el tiempo entre frames, sino que es el propio navegador el que se encarga de ejecutar el loop de la forma más óptima pudiendo ser esta diferente dependiendo del dispositivo que se esté usando.</p>

<p>Veamos un ejemplo con setInterval:</p>

<pre><code>var myActor = new Actor();
var frameTime = 1000/60; //60fps
var interval = setInterval(animate, frameTime);

function animate(){
    //loop de animación
    myActor.x += 1; //Movemos el actor 1px a la derecha a cada frame
}
</code></pre>

<p>Mismo ejemplo usando requestAnimationFrame:</p>

<pre><code>var myActor = new Actor();

function animate(){
    requestAnimationFrame(animate); //Ejecutamos RAF dentro del loop
    myActor.x += 1;
}

animate(); //Iniciamos el loop
</code></pre>

<p>Ambos ejemplos hacen lo mismo, mueven un actor hacia la derecha 1px en cada frame, la diferencia reside en la forma en la que se gestiona el loop, mientras que el loop con setInterval se va a ejecutar 60 veces por segundo, de manera obligatoria, tal y como hemos declarado, el segundo loop puede variar la velocidad de ejecución en base a muchos otros factores.</p>

<p>Centremonos entonces, en <strong>requestAnimationFrame</strong>, que es, actualmente (<em>salvo exepciones</em>) el que se debe usar para crear animaciones. </p>

<p>Teniendo en cuenta que el <strong>RAF</strong> (<em>requestAnimationFrame</em>) puede que no se ejecute a velocidades constantes, y nuestro actor se mueve 1px a cada frame, tenemos un problema. Imagina ejecutar nuestro ejemplo en dos dispositivos diferentes, a la misma vez, veremos que la posición de nuestro actor empieza siendo la misma en ambos, pero a medida que transcurre el tiempo muy posibilemente varien, y uno de los actores se encuentre por delante del otro. Esto se debe a que quizás uno de los dispositivos ha ejecutado el loop a 55fps y el otro a 60, lo que a 1px por fps equivale a una diferencia de 5px entre ambos actores. Es un ejemplo un poco pobre, pero creo que se entiende el problema. </p>

<p>La solución pasa por calcular el <strong>delta time</strong>, que es basicamente el tiempo que ha pasado desde la última ejecucción del loop. Y cambiar el enfoque de nuestro movimiento de 1px por frame a 1px por segundo (1px o 100, o los que sean). De esta forma será más preciso el movimiento, y ambos actores avanzarán de forma identica independientemente de la velocidad del loop.</p>

<p>Veamos un ejemplo del calculo del delta time:</p>

<pre><code>var myActor = new Actor();
var time = 0; //tiempo total
var lastTime = 0; //tiempo total en el último update
var last = 0; //Date.now() en el ultimo update
var delta = 0; //tiempo delta

function animate(){
    requestAnimationFrame(animate); //Ejecutamos RAF dentro del loop

    var now = Date.now();
    time += (now-last)/1000;
    delta = time-lastTime;
    lastTime = time;
    last = now;

    myActor += 1*delta;

    console.log(delta, time);
}

last = Date.now(); //Indicamos el tiempo actual antes de ejecutar el primer fps
animate();
</code></pre>

<p>Gracias a este simple calculo el movimiento de nuestro actor será mucho más preciso que al principio, y este pequeño snippet nos sirve de manera universal tanto si usamos el elemento canvas directamente, o si usamos cualquier otro renderer como pueden ser <a href="http://threejs.org/">three.js</a> o <a href="http://www.pixijs.com/">pixi.js</a>.</p>

<p>Concretamente para <strong>pixi.js</strong> (<em>renderer que suelo usar asiduamente</em>), he creado un pequeño modulo que hará estos calculos y algunas cosillas más, como parar el loop y recuperarlo si la pestaña del navegador pierde el foco, limitar el tiempo máximo del frame por si el dispositivo de congela y de esta manera evitar saltos bruscos en la animación, etc...</p>

<p>El modulo se llama <strong><a href="https://github.com/Nazariglez/pixi-animationloop">pixi-animationloop</a></strong> y se encuentra publicado en <strong>Github</strong>. </p>

<p>Hay varias formas de usarlo; <em>la de toda la vida</em>, bajar el script del directorio build/pixi-animationloop.js y añadirlo en tu index.html justo debajo del script de PIXI. O si usas browserify o Webpack, tan solo tienes que hacer:</p>

<pre><code>npm install pixi-animationloop
</code></pre>

<p>El modulo añadirá una nueva clase a pixi, y solo tenemos crear la instancia pasandole el renderer de pixi, y ejecutar el metodo start:</p>

<pre><code>var renderer = new PIXI.autoDetectRenderer(800,600);
document.body.appendChild(renderer.view);

var animationLoop = new PIXI.AnimationLoop(renderer);
animationLoop.start();
</code></pre>

<p>Tan fácil como eso, y ya tenemos nuestro loop funcionando, con todos los calculos de tiempo accesibles desde la variable animationLoop. Por ejemplo: <code>.time</code> nos indicaría el tiempo total que ha pasado "dentro" de la animación desde el primer frame, <code>.realTime</code> nos indicaría el tiempo real (<em>sin contar posibles paradas, etc...</em>), <code>.speed</code> nos permitiría alterar la velocidad a la que pasa el tiempo, útil para efectos de tiempo bala o similares, en <code>.delta</code> tendríamos el calculo del <strong>delta time</strong> en segundo y <code>.deltaMS</code> sería el mismo valor pero en milisegundos. </p>

<p>Si conoces pixi.js, te habrás fijado en que no he creado un contenedor para usarlo como <em>Stage</em>, esto es porque el modulo ya lo crea internamente, pero si quieres puedes pasarle tu propio <code>PIXI.Container</code> como segundo parametro y quedaría referido en <code>animtionLoop.stage</code>.</p>

<p>Además, el modulo emite diferentes eventos que puedes escuchar para ejecutar tus propias instrucciones, como <code>start</code>, <code>stop</code>, <code>prerender</code>, <code>postrender</code> y <code>visibilitychange</code>. Muy útil por ejemplo para añadir un método step/update usando <code>prerender</code> o <code>postrender</code>:</p>

<pre><code>function update(){
    //Metodo update, this es animationLoop.
    myActor += 1 * this.delta;
}

animationLoop.on('prerender', update);
</code></pre>

<p>Si quieres saber más sobre la gestión de eventos te recomiendo ir  a la documentación de <strong>node.js</strong> sobre estos: <a href="https://nodejs.org/api/events.html">https://nodejs.org/api/events.html</a></p>

<p>Para terminar dejo el link al modulo en github. Te recomiendo que eches una vistazo rápido a la documentación para entender todo lo que puedes hacer, como parar el loop, eventos, velocidad máxima, etcetera.</p>

<p><strong>Link a pixi-animationloop</strong>: <a href="https://github.com/Nazariglez/pixi-animationloop">https://github.com/Nazariglez/pixi-animationloop</a></p>]]></description><link>http://www.nazariglez.com/2016/01/24/controlando-el-requestanimationframe-en-pixi-con-pixi-animationloop/</link><guid isPermaLink="false">edb3ebf3-b624-43a9-8b30-8d743839e3a4</guid><category><![CDATA[HTML5]]></category><category><![CDATA[pixi]]></category><category><![CDATA[games]]></category><category><![CDATA[requestAnimationFrame]]></category><dc:creator><![CDATA[Nazarí Glez]]></dc:creator><pubDate>Sun, 24 Jan 2016 22:38:21 GMT</pubDate></item><item><title><![CDATA[He migrado el blog de Wordpress a Ghost]]></title><description><![CDATA[<p>Al fin he migrado el blog de Wordpress a <a href="https://ghost.org/"><strong>Ghost</strong></a>!. Llevaba bastante tiempo pensando en hacer la migración, y más tiempo aún pensando en que wordpress simplemente no era lo que necesitaba para mi blog, demasiado pesado, demasiadas funcionalidades, configuraciones; incluso he encontrado <a href="http://www.nazariglez.com/2013/02/07/wordpress-esta-bien-pero-quizas-yo-busco-otra-cosa/">un post de hace dos años</a> donde ya comentaba esto.</p>

<p>Creo que Ghost cumple con todo lo que necesito, una plataforma enfocada 100% en blogs, que me permite añadir paginas estaticas y temas, ademá es ligero, rápido de configurar, y un largo etcétera.</p>

<p>Por supuesto tiene puntos malos, como no permitir programar la fecha del post, o cosas como que no permite menús dinámicos de momento, pero es algo que no me preocupa, siempre se pueden añadir los enlaces mediante html en la plantilla. Aún así, el desarrollo de la plataforma no para, y dia a dia avanzan y añaden features nuevas.</p>

<p>He aprovechado también para cambiar el estilo del blog, buscando un tema centrado totalmente en el contenido, y ya que estaba metido en faena he migrado de servicio de hosting, de iFastNet a DigitalOcean.</p>

<p>Ya usaba <a href="https://www.digitalocean.com/"><strong>DigitalOcean</strong></a> para pequeños proyectos y estaba bastante contento, así que me pareció una tontería pagar dos servicios de hosting por separado, mejor tenerlo todo en el mismo sitio.</p>

<p>Tenía pensado escribir una entrada tipo "<em>Migra tu blog de Wordpress a Ghost</em>", pero lo cierto es que ya hay muchos y muy buenos post que lo explican, y aunque hay diferentes formas de hacerlo, y los problemas que te puedes encontrar pueden ser diferentes también, la esencia es la misma. Yo os recomiendo el que usé de guia, aunque no hice todo lo que pone tal y como lo pone, pero tiene explicado todo lo necesario para hacer la migración: <a href="http://mviera.io/blog/migrando-de-wordpress-a-ghost/">http://mviera.io/blog/migrando-de-wordpress-a-ghost/</a>.</p>

<p>Aún quedan bastante flecos que corregir después de la migración, como links que no funcionan, etiquetas repetidas, o post mal maquetados, intentaré esta semana poco a poco ponier todo en orden.</p>

<p>¿Que os parece ghost?, ¿Lo veis una buena alternativa para vuestros blogs?</p>]]></description><link>http://www.nazariglez.com/2015/03/08/he-migrado-el-blog-de-wordpress-a-ghost/</link><guid isPermaLink="false">16581a80-0120-4767-b346-33f547b9bf34</guid><category><![CDATA[Off Topic]]></category><category><![CDATA[wordpress]]></category><category><![CDATA[ghost]]></category><dc:creator><![CDATA[Nazarí Glez]]></dc:creator><pubDate>Mon, 09 Mar 2015 00:10:52 GMT</pubDate></item><item><title><![CDATA[Primeros pasos con Browserify]]></title><description><![CDATA[<p>Me apetece hablar un poco hoy sobre <strong><a href="http://browserify.org/" title="Browserify Website">Browserify</a></strong>, el cual es sin duda uno de los paquetes más populares que podemos encontrar en <a href="https://www.npmjs.com/" title="npm Website">npm</a>. Hace algo de tiempo que conozco está herramienta, pero no fue realmente hasta hace poco que decidí probarla, y creo firmemente que ha entrado dentro de mis imprescindibles del día a día.</p>

<p>Browserify es básicamente una herramienta que nos permite gestionar dependencias en forma de módulos del lado del cliente (<em>en el navegador</em>). A grandes rasgos podemos decir que lo que nos permite es crear y requerir módulos tal y como hacemos con <a href="http://nodejs.org/" title="Node.js Website">Node.js</a>; y digo a grandes rasgos porque no es exactamente así, ya que con browserify no tendremos en el build final varios ficheros javascript, sino que crearemos un bundle con la herramienta y tan solo tendremos un fichero javascript.</p>

<p>Pero vayamos por partes, primero que nada deberás de tener instalada la herramienta de manera global con npm:</p>

<pre><code>npm install -g browserify
</code></pre>

<p>Una vez hecho esto, podremos ejecutar directamente browserify desde nuestra terminal, es importante que la instalación haya sido global, o en caso contrario no funcionará, puedes hacer la prueba pidiendo la versión del paquete:</p>

<pre><code>browserify -v
</code></pre>

<p>Si te ha devuelto un numero (en mi caso 8.1.3) es que todo está correcto.</p>

<p>Vamos a crear ahora nuestro primer modulo, que, para no perder las buenas costumbres será el típico “hello world”. Lo llamaremos hello.js:</p>

<pre><code>var str = "hello world"; 
module.exports = function(name){ 
    console.log(str + ' ' + name); 
};
</code></pre>

<p>Ahora creamos otro modulo en el mismo directorio llamado index.js, y hacemos <em>require</em> al modulo hello.js:</p>

<pre><code>var hello = require('./hello.js'); 
hello('Juan'); //hello world Juan
</code></pre>

<p>Todo listo para crear nuestro archivo final, ahora simplemente debemos de ir a nuestro terminal y ejecutar browserify indicandole el archivo de entrada, que es el script desde donde tiene que empezar a “seguir” todas las dependencias, y el nombre del fichero final que debe generar, así:</p>

<pre><code>browserify index.js &gt; bundle.js
</code></pre>

<p>Esto nos generará un script llamado bundle.js (o el nombre que tu quieras) que es el que debemos incluir en nuestro fichero HTML como cualquier otro script. Como podrás ver, el proceso de gestión de módulos es automático, browserify se encarga de seguir todas las dependencias e incluirlas dentro del archivo final, fácil y rápido.</p>

<h6 id="quepasasihacemosrequiredosvecesalmismosscript">¿Que pasa si hacemos require dos veces al mismos script?</h6>

<p>Si lo que te preocupa es que se incluya un modulo varias veces, puedes estar tranquilo, browserify incluirá el modulo solo una vez en el bundle final, y luego tu podrás usarlo las veces que quieras.</p>

<p>Hagamos una prueba, volvamos a nuestro modulo hello.js y añadamosle algunos logs:</p>

<pre><code>var str = "hello world"; 
console.log('Soy el modulo hello.js'); 
module.exports = function(name){ 
    console.log(str + ' ' + name); 
};
</code></pre>

<p>Y en el index.js hacemos require de hello.js en dos ocaciones:</p>

<pre><code>var hello = require('./hello.js'); //Soy el modulo hello.js
hello('Juan'); //hello world Juan 
var helloAgain = require('./hello.js');
</code></pre>

<p>Genera nuevamente el bundle y carga tu html, comprobarás que la frase “<em>Soy el modulo hello.js</em>” solo se ha visto una vez en la consola, no dos. De esta forma tu puedes usar el mismo modulo tantas veces como quieras, cargando por ejemplo hello.js en varios módulos diferentes, sin tener que preocuparte de que se ejecute cada vez las rutinas del modulo hello.js, o de que el peso del archivo final sea excesivamente grande.</p>

<h6 id="quepasaconelmbitodelasvariables">¿Que pasa con el ámbito de las variables?</h6>

<p>Otra de las ventajas de browserify es que cada modulo será totalmente independiente, quedando todo lo que hagas encapsulado y exponiendo hacia el exterior solo lo que tu quieras que sea expuesto mediante module.exports.</p>

<p>Si quieres, puedes hacer una prueba muy sencilla con lo que ya tenemos hecho, si te fijas en hello.js se ha declarado la variable str, no se encuentra dentro de ninguna función, pero solo tiene validez dentro de ese modulo. Para comprobarlo vamos a añadir a index.js lo siguiente:</p>

<pre><code>var hello = require('./hello.js'); //Soy el modulo hello.js
hello('Juan'); //hello world Juan 

//Comprobando el scope 
if(str){ 
    console.log('Esto no se ejecutará nunca');
}else{ 
    console.log('la variable str no existe en este módulo, porque pertenece al módulo hello.js'); 
}
</code></pre>

<p>Como dice el ejemplo, la frase “<em>Esto no se ejecutará nunca</em>” no la verás nunca en la consola. De esta forma, cualquier variable que declares, o función que definas tendrá validez solamente dentro del scope del propio módulo, por lo que puedes declarar lo que tu quieras fuera de funciones o closures sin miedo a contaminar el objeto window.</p>

<h6 id="usandomodulosdenpm">Usando modulos de npm</h6>

<p>Otra de las grandes ventajas de usar browserify es que puedes usar módulos instalados desde npm en el navegador. Por ejemplo jQuery, vamos a instalarlo mediante npm:</p>

<pre><code>npm install jquery
</code></pre>

<p>Ahora simplemente debemos hacerle require sin indicar path, y lo tendremos incluido en nuestro bundle.</p>

<pre><code>var $ = require('jquery'); 
$(function(){ 
    console.log('jQuery'); 
});
</code></pre>

<p>Si usamos npm para gestionar todos los módulos que podamos, nos facilitaremos la vida a nosotros mismos, porque no deberemos de preocuparnos por nada más que no sea hacer un npm install o un npm update para mantener en orden y funcionando nuestras aplicaciones.</p>

<h6 id="vigilandoloscambiosconwatchify">Vigilando los cambios con Watchify</h6>

<p><strong><a href="https://github.com/substack/watchify" title="Watchify">Watchify</a></strong> es otra herramienta que nos hará la vida más fácil cuando trabajemos con browserify. Este paquete se encarga de vigilar todos los cambios que ocurren en nuestro código y generar el bundle cada vez que exista una modificación. Para instalarlo, volveremos a recurrir a npm:</p>

<pre><code>npm install -g watchify
</code></pre>

<p>En este caso la instalación ha de ser también usando <em>-g</em> para que este disponible globalmente. Y la forma de usarlo es casi identica a como usamos browserify:</p>

<pre><code>watchify index.js -o bundle.js
</code></pre>

<p>Con esta ultima sentencia le estamos indicando que use como punto de entrada index.js vigilando todos los cambios en este script y en todos los referenciados mediante require de todo el árbol de dependencias, si alguno de estos se modifica, se generaría nuevamente el bundle.js sin que tengamos que intervenir.</p>

<h6 id="usandogulpybrowserify">Usando Gulp y Browserify</h6>

<p>Aunque trabajar con browserify y watchifiy es bastante sencillo, aún podríamos facilitarlo más relegando todo el trabajo a un gestor de tareas como <a href="http://gulpjs.com/" title="Gulp Website">Gulp</a>, si no lo conoces te recomiendo leer <a href="http://www.nazariglez.com/2014/07/21/primeros-pasos-con-gulp-js/" title="Primeros pasos con Gulp.JS">este post</a>.</p>

<p>Primero que nada vamos a instalar los 4 módulos que usaremos como dependencias de desarrollo (asegurate de tener el package.json de tu proyecto).</p>

<pre><code>npm install gulp browserify watchify vinyl-source-stream --save-dev
</code></pre>

<p>Y creamos nuestro gulpfile.js en la raíz del proyecto:</p>

<pre><code>var gulp = require('gulp'), 
    browserify = require('browserify'), 
    watchify = require('watchify'), 
    source = require('vinyl-source-stream');
</code></pre>

<p>Ahora pasaremos a iniciar browserify y watchify, pero según la documentación de watchifiy al crear la instancia de browserify debemos de pasarle un objeto con 3 propiedades de manera obligada, estas propiedades son, cache, packageCache, y fullPaths, aunque la manera más sencilla es pasarle directamente el objeto args de watchify, que es justo lo que haremos:</p>

<pre><code>var entry = './index.js'; //Script de entrada 
var args = watchify.args; 
args.debug = true; //Genera el sourcemap para debuguear
args.fullPaths = false; //Evita el uso de paths absolutos 
var bundler = watchify(browserify(entry, args));
</code></pre>

<p>Una vez creada la instancia con los parámetros que queremos, pasamos a gestionar el bundle y las tareas:</p>

<pre><code>function createBundle(){ 
    console.log('Now building...'); 
    return bundler.bundle() 
        .pipe(source('bundle.js')) //Nombre del bundle final
        .pipe(gulp.dest('./build')); //Directorio de destino
} 

gulp.task('dev', createBundle); 
bundler.on('update', createBundle); //A cada modificación generamos un nuevo bundle 

//Proporcionamos algo de información al generar el bundle
bundler.on('time', function(time){ 
    console.log('Done at ' + (time/1000)); 
});
</code></pre>

<p>Y listo, a estas alturas el archivo gulpfile.js tendría que verse más o menos así:</p>

<pre><code>var gulp = require('gulp'), 
    browserify = require('browserify'), 
    watchify = require('watchify'), 
    source = require('vinyl-source-stream'); 

var entry = './index.js'; //Script de entrada 
var args = watchify.args; 
args.debug = true; //Genera el sourcemap para debuguear
args.fullPaths = false; //Evita el uso de paths absolutos 

var bundler = watchify(browserify(entry, args)); 

function createBundle(){ 
    console.log('Now building...'); 
    return bundler.bundle() 
        .pipe(source('bundle.js')) //Nombre del bundle final
        .pipe(gulp.dest('./build')); //Directorio de destino
} 

gulp.task('dev', createBundle); 
bundler.on('update', createBundle); //A cada modificación generamos un nuevo bundle 

//Proporcionamos algo de información al generar el bundle
bundler.on('time', function(time){ 
    console.log('Done at ' + (time/1000)); 
});
</code></pre>

<p>Ahora cuando trabajemos en nuestro proyecto solo deberemos de ejecutar <em>gulp dev</em> en la terminal, y olvidarnos de todo, que gulp y browserify se encargarán de hacer todo el trabajo repetitivo, y nosotros solo tendremos que centrarnos en generar buen código ;)</p>

<p>Si te interesa el tema, te animo a que busques más información en google, porque esto que ves aquí es solo una de las pocas formas que existen de trabajar con browserify, sobre todo no te pierdas “<a href="https://github.com/substack/browserify-handbook#transforms" title="Browserify Handbook">Browserify Handbook</a>“.</p>

<p>Anímate y comenta que opinas de browserify, si lo has usado o planeas usar, si lo usas con algunos módulos, o cualquier otra cosa relacionada, cualquier comentario es bienvenido.</p>]]></description><link>http://www.nazariglez.com/2015/02/19/primeros-pasos-con-browserify/</link><guid isPermaLink="false">2b4ecfc4-167c-4b52-93f9-c9adf094baf9</guid><category><![CDATA[browserify]]></category><category><![CDATA[dependencias en navegador]]></category><category><![CDATA[gulp]]></category><category><![CDATA[Javascript]]></category><category><![CDATA[modulos]]></category><category><![CDATA[Programación]]></category><category><![CDATA[Tutoriales]]></category><category><![CDATA[watchifiy]]></category><dc:creator><![CDATA[Nazarí Glez]]></dc:creator><pubDate>Thu, 19 Feb 2015 08:30:49 GMT</pubDate></item><item><title><![CDATA[Bee Quest: El nuevo Match3 de Ludei]]></title><description><![CDATA[<p>Hace bastante tiempo que no escribo nada en el blog, y voy a aprovechar este pequeño post para “<em>publicitar</em>” un poco el ultimo juego en el que he trabajado junto con <a href="https://twitter.com/hyperandroid">Ibon Tolosana</a>, <a href="https://twitter.com/rogersolsona">Roger Solsona</a>, y <a href="https://twitter.com/zigor">Zigor Samaniego</a> (entre otros) en <a href="http://ludei.com/">Ludei.</a></p>

<p>El juego en cuestión es <strong>Bee Quest</strong> (<a href="https://play.google.com/store/apps/details?id=com.ludei.beequest" title="Bee Quest para Android en Google Play">Android</a> || <a href="https://itunes.apple.com/us/app/bee-quest/id933854005?mt=8" title="Bee Quest para iphone e ipad en la App Store">iOS</a>). Se trata de un Match3 muy entretenido y desafiante, con un aspecto visual precioso (magia de <a href="https://twitter.com/zigor">Zigor</a>) en el que se respira variedad en todas y cada una de sus mecánicas. En el tomamos el rol de Thoven, una abeja que deberá jugar con las flores para ayudar a su colmena.</p>

<p>A medida que vas jugando y pasando niveles van entrando en escena diferentes mecánicas que te harán estrujarte la cabeza, como por ejemplo los cambios de modos de juegos, siendo estos el ya clásico intercambio de fichas, la selección de flores por cercanía arrastrando tu dedo por encima de estás, o el modo de toque, donde tocar una flor con flores similares alrededor hacen que exploten.</p>

<p>Otro factor a tener en cuenta es el cambio del viento, que altera el movimiento de las flores del tablero, pudiendo estas ir en cualquier dirección, ya sea hacia arriba, abajo, o hacia cualquiera de los laterales.</p>

<p>Hay mucho más por supuesto, desde arañas que con su tela bloquearán tus fichas, a movimientos especiales, enredaderas que se comerán el espacio que es para tus flores, teletransportadores que te pondrán todo patas arriba, y un largo etcétera que será mejor que descubras por ti mismo!</p>

<p>Sobre la parte técnica del juego no quiero hablar mucho en este blog, porque no es el sitio que le corresponde, ya que su sitio es el <a href="http://blog.ludei.com/" title="Blog de Ludei">blog de ludei</a>, pero como habrás imaginado al ser un trabajo de ludei, es un juego desarrollado en HTML5, javascript, y <a href="https://www.ludei.com/cocoonjs/" title="Cocoon">Cocoon</a>, más concretamente en WebGL corriendo sobre Canvas+.</p>

<p>Sin más espero que todo el que “caiga” por aquí le de una oportunidad, lo pruebe, y si quiere dejar un comentario sobre que le parece, o mejor aún, quiere dejar una review en la store, pues se le agradecería mucho!</p>

<p>Google Play: <a href="https://play.google.com/store/apps/details?id=com.ludei.beequest">https://play.google.com/store/apps/details?id=com.ludei.beequest <br>
</a>App Store: <a href="https://itunes.apple.com/us/app/bee-quest/id933854005">https://itunes.apple.com/us/app/bee-quest/id933854005</a></p>]]></description><link>http://www.nazariglez.com/2015/02/12/bee-quest-el-nuevo-match3-de-ludei/</link><guid isPermaLink="false">e2a29136-b021-4d72-b748-5b0a9e5cdb3d</guid><category><![CDATA[Android]]></category><category><![CDATA[Canvas]]></category><category><![CDATA[cocoon]]></category><category><![CDATA[cocoonjs]]></category><category><![CDATA[HTML5]]></category><category><![CDATA[ios]]></category><category><![CDATA[Javascript]]></category><category><![CDATA[Juegos]]></category><category><![CDATA[juegos movil]]></category><category><![CDATA[match3]]></category><category><![CDATA[Programación]]></category><dc:creator><![CDATA[Nazarí Glez]]></dc:creator><pubDate>Thu, 12 Feb 2015 20:05:32 GMT</pubDate></item><item><title><![CDATA[Recopilación: 30 motores que te permitirán publicar tus juegos en HTML5]]></title><description><![CDATA[<p>Cada día que pasa <strong>HTML5</strong> está cogiendo más fuerza en el mundo de los juegos y de las apps, aunque aún queda mucho camino por recorrer lo cierto es que en apenas un par de años se ha avanzado muchísimo en este campo. Actualmente son muchas las empresas que han visto una buena forma de distribuir sus juegos en HTML5, es lógico, hacer que tu juego funcione en cualquier dispositivo que disponga de navegador sin obligar al usuario a descargar ningún plugin externo es, a mi entender, una ventaja.</p>

<p>En un principio, y dado el estado primitivo de HTML5, los juegos eran básicamente en 2D, usando SVG, la api del contexto 2d de canvas, o combinaciones de DOM con CSS y Javascript. Con el tiempo y a medida que el estándar ha ido avanzando, la api de canvas ha ganado importancia siendo hoy por hoy la forma más extendida de realizar juegos en html5.</p>

<p>Poco después llega el 3d a los juegos de navegador de la mano del maravilloso <strong>WebGL</strong>, el cual permitió expandir aún más el poder de los juegos de navegador dando acceso a recursos que antes no se podía (como la gpu), permitiendo hacer juegos bastante más complejos y con un mejor rendimiento gracias a la aceleración por hadware.</p>

<p>El ultimo gran paso que se ha dado en este campo, es la creación de emscripten/asm.js, una herramienta que nos permite compilar código c/c++ a javascript y ejecutarlo dentro de un navegador, y en el caso que nos interesa, usar juegos que fueron principalmente diseñador en c/c++ para otros entornos, bajo webgl en el navegador. Esta herramienta ha sido básicamente la culpable de que empresas con motores de juegos consolidados hayan decidido incluir exportadores a html5 de los juegos creados bajo su producto. (<a href="https://www.youtube.com/watch?v=BV32Cs_CMqo">Video de Unreal Engine 3 en Mozilla Firefox</a>).</p>

<p>Ahora, desde mi punto de vista, hay que diferenciar bien que es lo que buscamos, como he dicho en otras ocasiones cada motor es un mundo, y puede que prefiramos un motor u otro dependiendo del tipo de desarrollo que tenemos entre manos. Si usamos motores javascript, un contexto 2d nos va a permitir hacer juegos 2d sin aceleración por hadware, un contexto webgl nos va a permitir crear tanto juegos 2d como juegos 3d acelerados por hadware, pero bajo apis diferentes (lo que quiere decir que tendrás que aprender dos formas de trabajar diferentes), y un desarrollo basado en <strong>emscripten/asm.js</strong> nos va a permitir lo mismo que en webgl pero usando otro tipo de herramientas u otro tipo de lenguajes, a cambio posiblemente sacrificaremos algo de rendimiento en dispositivos “más” antiguos al existir una capa intermedia (ojo, aunque no será lo mismo que trabajar directamente en javascript, el rendimiento puede ser muy bueno).</p>

<p>Llegado a este punto, dirás que esto es un rollo, que estás peor que al principio y que tu solo quieres desarrollar juegos sin preocuparte de nada más, en ese caso, estás de suerte porque existe muchísima variedad en cuanto a motores se refieren, algunos se encargarán ellos mismos de aplicar el contexto adecuado sin que el developer se tenga que preocupar de aprender nada externo a la api propia del motor, y otros usaran emscripten/asm.js dándole al programador un fichero html que subir, y listo.</p>

<p>He recopilado unos cuantos motores que de una forma u otra te permitirán crear juegos para navegadores, y la he organizado en 3 categorías para ayudarte a elegir, estas son: javascript/2d, javascript/webgl, y por ultimo emscripten/asm.js.</p>

<h2 id="javascript2d">Javascript / 2d</h2>

<h6 id="1cutjs">1. CutJS</h6>

<p><strong>Precio:</strong> Gratuito <br>
<strong>Open Source:</strong> Si <br>
<strong>Web:</strong> <a href="http://cutjs.org/">http://cutjs.org/</a></p>

<h6 id="2impactjs">2. ImpactJS</h6>

<p><span style="font-weight: bold;">Precio:</span> 99$ <br>
<span style="font-weight: bold;">Open Source:</span> No <br>
<span style="font-weight: bold;">Web:</span> <a href="http://impactjs.com/">http://impactjs.com/</a></p>

<h6 id="3wade">3. Wade</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito bajo ciertas condiciones <a href="http://www.clockworkchilli.com/index.php/main/policy/wade_eula">http://www.clockworkchilli.com/index.php/main/policy/wade_eula</a> <br>
<span style="font-weight: bold;">Open Source:</span> No <br>
<span style="font-weight: bold;">Web:</span> <a href="http://www.clockworkchilli.com/index.php/developers">http://www.clockworkchilli.com/index.php/developers</a></p>

<h6 id="4frozenjs">4. FrozenJS</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="http://frozenjs.com/docs/">http://frozenjs.com/docs/</a></p>

<h6 id="5quintus">5. Quintus</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="http://html5quintus.com/">http://html5quintus.com/</a></p>

<h6 id="6fabricjs">6. FabricJS</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="http://fabricjs.com/">http://fabricjs.com/</a></p>

<h6 id="7melonjs">7. MelonJS</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="http://melonjs.org/index.html">http://melonjs.org/index.html</a></p>

<h6 id="8limejs">8. LimeJS</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="http://www.limejs.com/">http://www.limejs.com/</a></p>

<h6 id="9booty5">9. Booty5</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="https://github.com/mrmop/Booty5">https://github.com/mrmop/Booty5</a></p>

<h2 id="javascriptwebgl">Javascript / WebGL</h2>

<h6 id="10pixijs">10. PixiJS</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="http://www.pixijs.com/">http://www.pixijs.com/</a></p>

<p>*No es realmente un motor o famework de juegos, más bien es un renderer</p>

<h6 id="11phaser">11. Phaser</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="http://phaser.io/">http://phaser.io/</a></p>

<h6 id="12pandajs">12. PandaJS</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="http://www.pandajs.net/">http://www.pandajs.net/</a></p>

<h6 id="13construct2">13. Construct2</h6>

<p><span style="font-weight: bold;">Precio:</span> Dispone de diferentes planes de precios. <br>
<span style="font-weight: bold;">Open Source:</span> No <br>
<span style="font-weight: bold;">Web:</span> <a href="https://www.scirra.com/">https://www.scirra.com/</a></p>

<h6 id="14babylonjs">14. BabylonJS</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="http://www.babylonjs.com/">http://www.babylonjs.com/</a></p>

<h6 id="15trubulenz">15. Trubulenz</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="http://biz.turbulenz.com/">http://biz.turbulenz.com/</a></p>

<h6 id="16spelljs">16. SpellJS</h6>

<p><span style="font-weight: bold;">Precio:</span> Dispone de planes de precios <br>
<span style="font-weight: bold;">Open Source:</span> No <br>
<span style="font-weight: bold;">Web:</span> <a href="http://spelljs.com/">http://spelljs.com/</a></p>

<h6 id="17threejs">17. ThreeJS</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="http://threejs.org/">http://threejs.org/</a></p>

<h6 id="18kiwijs">18. KiwiJS</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="http://www.kiwijs.org/">http://www.kiwijs.org/</a></p>

<h6 id="19caat">19. CAAT</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="https://github.com/hyperandroid/caat">https://github.com/hyperandroid/caat</a></p>

<h6 id="20craftyjs">20. CraftyJS</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="http://craftyjs.com/">http://craftyjs.com/</a></p>

<h6 id="21voxeljs">21. VoxelJS</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="http://voxeljs.com/">http://voxeljs.com/</a></p>

<h6 id="22playcanvas">22. PlayCanvas</h6>

<p><span style="font-weight: bold;">Precio:</span> Dispone de planes de precios <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="https://playcanvas.com/">https://playcanvas.com/</a></p>

<h6 id="23cocos2djs">23. Cocos2d-JS</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="http://www.cocos2d-x.org/wiki/Cocos2d-JS">http://www.cocos2d-x.org/wiki/Cocos2d-JS</a></p>

<h6 id="24lycheejs">24. LycheeJS</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="http://lycheejs.org/index.html">http://lycheejs.org/index.html</a></p>

<h6 id="25enchantjs">25. EnchantJS</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="http://enchantjs.com/es/">http://enchantjs.com/es/</a></p>

<h6 id="26haxor">26. Haxor</h6>

<p><span style="font-weight: bold;">Precio:</span> Gratuito <br>
<span style="font-weight: bold;">Open Source:</span> Si <br>
<span style="font-weight: bold;">Web:</span> <a href="http://haxor.thelaborat.org/">http://haxor.thelaborat.org/</a></p>

<h2 id="emscriptenasmjs">Emscripten / asm.js</h2>

<h6 id="27gamesalad">27. GameSalad</h6>

<p><span style="font-weight: bold;">Precio:</span> Dispone de planes de precios <br>
<span style="font-weight: bold;">Open Source:</span> No <br>
<span style="font-weight: bold;">Web:</span> <a href="http://gamesalad.com/">http://gamesalad.com/</a></p>

<h6 id="28gamemakerstudiohtml5">28. Game Maker Studio HTML5</h6>

<p><span style="font-weight: bold;">Precio:</span> 199.98$ (GMS Pro 99.99$ + HTML5 Module 99.99$) <br>
<span style="font-weight: bold;">Open Source:</span> No <br>
<span style="font-weight: bold;">Web:</span> <a href="https://www.yoyogames.com/">https://www.yoyogames.com/</a></p>

<h6 id="29unity5">29. Unity 5</h6>

<p><span style="font-weight: bold;">Precio:</span> Dispone de planes de precios <br>
<span style="font-weight: bold;">Open Source:</span> No <br>
<span style="font-weight: bold;">Web:</span> <a href="https://unity3d.com/es/5">https://unity3d.com/es/5</a></p>

<h6 id="30unrealengine4">30. UnrealEngine 4</h6>

<p>*No he podido encontrar mucha más información acerca del exportador html5 de UnrealEngine4</p>

<p><span style="font-weight: bold;">Precio:</span> ??? <br>
<span style="font-weight: bold;">Open Source:</span> ??? <br>
<span style="font-weight: bold;">Web:</span> <a href="https://docs.unrealengine.com/latest/INT/Platforms/HTML5/GettingStarted/index.html">https://docs.unrealengine.com/latest/INT/Platforms/HTML5/GettingStarted/index.html</a></p>

<h6 id="comentariofinal">Comentario final</h6>

<p>Me hubiera gustado añadir algunos comentarios sobre cada uno de los motores para tratar de ayudar a decidir a los indecisos, pero no me pareció adecuado, ya que no he probado todos los motores aquí listados y no podría ofrecer un “juicio” real de ellos.</p>

<p>Lo que si puedo hacer para futuros post es comentar un poco los que si he usado, mi opinión y experiencia con ellos. Igualmente si has usado cualquiera de estos motores, y quieres añadir o compartir información al respecto me agradaría leerla en los comentarios, y si conoces algún otro motor que no esté aquí listado, y que consideres que puede interesar a otras personas, me gustaría que lo compartieras también en los comentarios.</p>]]></description><link>http://www.nazariglez.com/2014/09/22/recopilacion-30-motores-que-te-permitiran-publicar-tus-juegos-en-html5/</link><guid isPermaLink="false">02e5fefc-542c-410a-a3ef-f660f776b3ef</guid><category><![CDATA[engines]]></category><category><![CDATA[frameworks]]></category><category><![CDATA[game engines]]></category><category><![CDATA[Game Maker]]></category><category><![CDATA[HTML5]]></category><category><![CDATA[html5 engines]]></category><category><![CDATA[Javascript]]></category><category><![CDATA[Juegos]]></category><category><![CDATA[motores html5]]></category><category><![CDATA[videojuegos]]></category><dc:creator><![CDATA[Nazarí Glez]]></dc:creator><pubDate>Mon, 22 Sep 2014 08:00:35 GMT</pubDate></item><item><title><![CDATA[Desarrollando juegos móviles para diferentes pantallas]]></title><description><![CDATA[<p>Por lo general cuando estamos desarrollando un juego para móviles nos encontramos a menudo con el problema de la amplia gama de tamaños de pantalla que tenemos en el mercado, y ya no tanto con los tamaños de las pantallas sino realmente con los diferentes Aspect Ratios que estas tienen.</p>

<p>Conseguir que un desarrollo se vea perfectamente, o de manera similar en todos los dispositivos posibles es todo una odisea, teniendo en cuenta que hacer un desarrollo para cada dispositivo no suele ser una opción debido a la perdida de tiempo y esfuerzo, duplicidades, y un largo etcétera.</p>

<p>Personalmente el lidiar con este tema se me hace bastante pesado, sobre todo cuando nuestro juego ha de verse correctamente en las gamas bajas y altas de android, los diferentes iphone y los nuevos ipad (retina); vamos lo que vendría a ser lo ideal, que se vea bien en todo.</p>

<p>Para que te hagas una idea, un Samsung Galaxy s4 tiene un aspect ratio de 16:9, mientras que un Ipad Air tiene un aspect ratio de 4:3, como te podrás imaginar, tu juego no se va a ver perfecto en ambos tan fácilmente, si todo fuera tan fácil la vida sería aburrida :P.</p>

<p>Tenemos diferentes formas de afrontar este tema, y cada maestrillo tiene su librillo, como en todo, pero hay 3 formas que suelen ser las más usadas, el <strong>escalado</strong>, el <strong>cropping</strong>, y el <strong>letterboxing</strong> o <strong>pillarboxing</strong>.</p>

<h6 id="elescalado">El Escalado</h6>

<p>Imagina que has diseñado tu juego pensando en un Aspect Ratio de 16:9, existen muchos modelos de móviles que comparten este aspect ratio y tu decides tomar la opción más sencilla para que se adapte a todas las pantallas, que es escalar toda la capa visible de nuestro juego para que ocupe todo el espacio de la pantalla que lo muestra, pero esto implica que cuando la pantalla no comparta el mismo aspect ratio que para el que fue diseñado, la imagen se verá deformada, ya que escalara el Eje X y el Eje Y por separado. Si la diferencia de ratios no es mucha, como, quizás un 16:10, podría pasar inadvertido (que ningún diseñador me apuñale por favor!), pero si es algo más extrema, por ejemplo un ipad, en ese caso si notaremos el cambio. Esto hace que la opción más sencilla quizás no sea la más adecuada en la mayoría de los casos.</p>

<h6 id="elcropping">El Cropping</h6>

<p>Sigue manteniendo en tu imaginación que has diseñado tu juego para nuestro (mi) aspect ratio favorito, 16:9, y que has probado el sistema de escalado pero no te ha terminado de convencer debido a la deformación que puede provocar al cambiar de dispositivo.  Así que decides optar por el sistema de cropping.</p>

<p><img src="http://www.nazariglez.com/content/images/2014/08/crop_16_9_4_3.png" alt="cropping 1:9 a 4:3"></p>

<p>Cropping no es otra cosa que recortar la escena manteniendo el foco en lo que nos importa. Por ejemplo, si nuestro juego es landscape (apaisado), podemos usar la altura de nuestra escena como referencia, esta escalaría hasta adaptarse a la pantalla (manteniendo siempre la proporción del aspect ratio), y de esta forma nuestra escena no se vería deformada, ya que el espacio sobrante están situados fuera de la pantalla.</p>

<p>El principal problema de este sistema, es que nuestra GUI (interfaz de usuario) y el contenido de nuestra escena ha de ser bastante flexible, de manera que permita recolocar los elementos que necesitamos a nuestro antojo dependiendo de la pantalla a la que nos adaptamos para no dejar fuera de la vista nada importante, y esto tampoco es posible en todos los tipos de juegos.</p>

<h6 id="letterboxingopillarboxing">Letterboxing o pillarboxing</h6>

<p>En este punto ya hemos probado los sistemas anteriores, pero no terminan de encajar con la forma en la que hemos diseñado/pensado ese juego que nos hará retirarnos al caribe, así que buscamos más opciones.</p>

<p>El letterboxing y el pillarboxing básicamente son lo mismo, simplemente debemos de mantener inamovible nuestro aspect ratio y adaptar uno de nuestros tamaños (ancho o alto) a el tamaño de la pantalla. De esta manera dejamos dos franjas negras en los bordes, si ajustamos a lo alto quedarán dos franjas negras por los laterales (pillarboxing) y si ajustamos a lo ancho nos quedarán dos franjas negras por arriba y por debajo de nuestra escena (letterboxing).</p>

<p>Seguro que esto lo has visto mucho en el cine, y también en algunos juegos, principalmente en los juegos de PC; pero en los juegos móviles normalmente se intenta evitar esto, ya que da la impresión de que se está desaprovechando esa gran pantalla por la que el usuario ha pagado una pasta, así que en vez de dos franjas negras se suelen mostrar adornos de algún tipo, de manera que se entienda que son una parte más de la escena.</p>

<p>Un ejemplo de juego que recurre al pillarboxing puede ser el juego <strong>The Sandbox</strong>:</p>

<p><img src="http://www.nazariglez.com/content/images/2014/08/IMG_0516-300x169.png" alt="The Sandbox pillarboxing"></p>

<p>Si nos fijamos podemos ver como la escena de juego, donde transcurre la acción, se ha adaptado a la pantalla usando el alto como referencia a seguir, y al ser la pantalla de un aspect ratio con un ancho mayor a como fue diseñado el juego, se ha optado mostrar dos pilares de piedra a los laterales. De esta forma todo el espacio de la pantalla queda cubierta y tu mantienes la proporción de tu juego intacta y no te complicas alterando la escena sobre la marcha ni nada por estilo.</p>

<p>Como ejemplo de letterboxing podemos mirar el juego <strong>Jetpack Joyride</strong>:</p>

<p><a href="http://www.nazariglez.com/content/images/2014/08/jetpackjoyride_letterboxing.png"><img src="http://www.nazariglez.com/content/images/2014/08/jetpackjoyride_letterboxing-300x225.png" alt="Jetpack Joyride letterboxing" title=""></a></p>

<p>Al contrario que en The Sandbox, el Jetpack Joyride se adapta a la pantalla usando el ancho como referencia, en este caso cuando el aspect ratio no es el mismo que con el que el juego fue diseñado se muestran dos franjas en la parte superior e inferior del juego, que serían las que están afuera de las lineas rojas.</p>

<p>Hay que resaltar en este caso, que la integración visual es tan buena que he tenido que marcar con lineas rojas lo que no pertenece al núcleo del juego para que se pueda apreciar correctamente.</p>

<h6 id="extra">Extra</h6>

<p>En <a href="http://ludei.com/" title="Ludei">Ludei</a> he aprendido otro método para gestionar la forma en la que los juegos se han de adaptar a las pantallas, principalmente gracias a motores como <a href="https://github.com/hyperandroid/CAAT">CAAT</a> que permiten gestionar los objetos como contenedores de otros trasmitiendoles posiciones y escalas a sus hijos de manera transparente para el programador. Básicamente es una combinación de los métodos anteriormente nombrados. Se utiliza un background sencillo que se adapta al tamaño total de la pantalla, y de manera separada se sitúa encima de este un contenedor que contiene todos los elementos del juego; mientras que el background se adapta (escalado), el contenedor junto a todos sus hijos mantiene siempre el aspecto y la proporción con la que fueron diseñados (letterboxing o pillarboxing), de esta forma ocupamos toda la pantalla, no alteramos el diseño original, y el mismo desarrollo sirve para todos los tipos de pantallas.</p>

<h6 id="conclusin">Conclusión</h6>

<p>La única conclusión que puedo sacar de todos estos métodos es que no hay ninguno perfecto, como ya he mencionado cada desarrollo requerirá que uses uno u otro, con mejor o peor suerte en tu elección, pero sin duda es un aspecto que hay que tener pensado y solucionado antes de empezar con la lógica del juego si quieres evitar dolores de cabeza. También hay que pensar que el motor con el que desarrollemos es un condicionante importante en muchos sentidos, y que la forma en la que podemos adaptar el juego a los diferentes dispositivos puede estar entonces condicionada también, cada motor es un mundo.</p>

<p>En lo personal creo que la técnica que nunca usaré por si sola es la del escalado, no me gusta nada que un juego se vea “encogido”, “estirado” o simplemente deformado al cambiar de dispositivo.</p>

<p>Te animas a contarnos que problemas te has encontrado al portar a diferentes dispositivos, y ¿como lo has solucionado?</p>

<p>— <br>
 PD: <em>La imagen de ejemplo con el paisaje la saqué de <a href="http://imagenespaisaje.blogspot.com.es/2013/01/hermosos-grandes.html">aquí</a>, he intentado buscar de donde proviene pero no he encontrado nada.</em></p>]]></description><link>http://www.nazariglez.com/2014/08/04/desarrollando-juegos-moviles-para-diferentes-pantallas/</link><guid isPermaLink="false">50174ee5-86b6-4723-9192-422d15d6c48f</guid><category><![CDATA[android]]></category><category><![CDATA[aspect ratio]]></category><category><![CDATA[desarrollo]]></category><category><![CDATA[diseño]]></category><category><![CDATA[ios]]></category><category><![CDATA[ipad]]></category><category><![CDATA[juego]]></category><category><![CDATA[Juegos]]></category><category><![CDATA[Programación]]></category><dc:creator><![CDATA[Nazarí Glez]]></dc:creator><pubDate>Mon, 04 Aug 2014 08:00:40 GMT</pubDate></item><item><title><![CDATA[Primeros pasos con Gulp.JS]]></title><description><![CDATA[<p>No se si conocéis <strong><a href="http://gulpjs.com/" title="GulpJS">GulpJS</a></strong> pero voy a intentar hacer una breve introducción a está librería, que, para los no lo conozcan se podría decir que es un gestor de tareas similar a <strong><a href="http://gruntjs.com/" title="GuntJS">Grunt</a></strong>. Esta basado en <a href="http://nodejs.org/" title="NodeJS">NodeJS</a>, pero básicamente no tienes porque tocar “nada” de node para trabajar con gulp, simplemente tener instalado <a href="http://nodejs.org/download/">node</a> y <a href="https://www.npmjs.org/">npm</a>. Lo que si tienes que tener son conocimientos de javascript, aunque mínimos, no hay nada del otro mundo en un script de gulp.</p>

<p>GulpJS nos permite gestionar fácilmente las tareas que debemos realizar a la hora de pasar nuestro proyecto del estado de desarrollo al estado de producción, como por ejemplo minificación de css, renombrado de ficheros, compresión de javascript, e incluso nos permite hacer watching (monitorizar) los archivos o directorios que le indiquemos para que al cambiar algo de estos ejecute las tareas que le asignamos de manera automática. Pero esto no es todo, hay muchos módulos que proveen a gulp de funcionalidades realmente útiles, seguro que encuentras alguna que haga exactamente lo que buscas, y sino es así, siempre podrás hacerla tu!.</p>

<p>Por ejemplo, yo actualmente lo estoy usando en el proyecto de una webapp, donde monitoriza la carpeta donde tengo mis módulos javascript y mis ficheros <a href="http://lesscss.org/" title="lesscss">LESS</a>, si detecta un cambio en alguno de los ficheros javascript ejecuta la tarea de comprimir todos los módulos en un solo fichero y moverlo al directorio del proyecto donde está la versión de producción, igual pasa con los ficheros less, si cambio alguno automaticamente compila todos mis ficheros a un solo fichero css y lo mueve a producción; lo mejor de todo esto es que ocurre realmente rápido, casi imperceptible, hago un cambio, refresco la web y el cambio ya está ahí. Entonces… ¿Empezamos?.</p>

<h6 id="instalandogulp">Instalando Gulp</h6>

<p>Dando por hecho que tienes instalado en tu sistema node y npm vamos a abrir un terminal y instalar gulp:</p>

<pre><code>sudo npm install -g gulp
</code></pre>

<p>A continuación vamos a crear el fichero package.json de tu proyecto, para ellos disponemos de dos formas, la primera y más sencilla es poner en la terminal desde el directorio de tu proyecto:</p>

<pre><code>npm init
</code></pre>

<p>El programa te irá haciendo una serie de preguntas, las cuales mayormente podrás dejar en blanco o poner lo que el mismo terminal te sugiere, la otra opción es creando tu mismo el fichero a mano, que ha de contener algo como esto:</p>

<pre><code>{
    "name" : "nombre-de-mi-proyecto",
    "version": "0.0.0"
}
</code></pre>

<p>Una vez que lo tengamos creado instalamos gulp como dependencia de desarrollo de nuestro proyecto:</p>

<pre><code>npm install --save-dev gulp
</code></pre>

<p>Si ahora miras el contenido de tu package.json verás que se ha añadido algo como esto:</p>

<pre><code>"devDependencies": {
    "gulp": "^3.8.6"
}
</code></pre>

<p>Básicamente no solo hemos instalado gulp en el proyecto sino que se ha quedado registrado para que la próxima vez que tengas que hacer una instalación del proyecto baste con un simple:</p>

<pre><code>npm install
</code></pre>

<p>Eso instalará nuestro proyecto con todas sus devDependencies en el futuro.</p>

<h6 id="creandonuestrastareas">Creando nuestras tareas</h6>

<p>Ha llegado el momento de crear nuestras primeras tareas basadas en gulp, para ello creamos un fichero en el directorio de nuestro proyecto llamado gulpfile.js. Este script será quien contenga todas las instrucciones de las tareas que queremos ejecutar en nuestro proyecto. Pero antes deberemos de instalar los modulos que nos hacen falta.</p>

<p>Por ejemplo, queremos unificar y comprimir dos ficheros javascript, para este caso podríamos usar el modulo gulp-uglifyjs:</p>

<pre><code>npm install --save-dev gulp-uglifyjs
</code></pre>

<p>Ahora vamos a editar el fichero gulpfile.js, primero que nada, llamamos a los modulos gulp y gulp-uglifiyjs:</p>

<pre><code>var gulp = require('gulp'), 
uglify = require('gulp-uglify');
</code></pre>

<p>Ahora, definimos una tarea:</p>

<pre><code>gulp.task('scripts', function(){ 
    console.log('it works!'); 
});
</code></pre>

<p>Guardamos el script y nos dirigimos nuevamente a la terminal para poner:</p>

<pre><code>gulp scripts
</code></pre>

<p>Que nos mostrará algo como esto:</p>

<pre><code>[15:45:14] Using gulpfile ~/demo/gulpfile.js
[15:45:14] Starting 'scripts'...
it's works!
[15:45:14] Finished 'scripts' after 78 μs
</code></pre>

<p>Fácil ¿verdad?, vamos entonces a hacer algo productivo con el modulo uglifyjs que hemos instalado, volvemos a la definición de nuestra tarea a indicarle que ficheros ha de usar, para ello usaremos <em>gulp.src()</em>, al cual le podemos pasar un string o un array con varios strings en su interior, en nuestro caso vamos a pasarle un string simple con un directorio:</p>

<pre><code>var myScripts = 'src/**/*.js'; //Directorio que contiene nuestros scripts 
gulp.task('scripts', function(){ 
    return gulp.src(myScripts); 
});
</code></pre>

<p>Pero esto por si solo no hace nada, debemos encadenarle las acciones que ha de realizar con estos ficheros:</p>

<pre><code>var myScripts = 'src/**/*.js'; 
gulp.task('scripts', function(){ 
    return gulp.src(myScripts) 
        .pipe(uglify('main.min.js')) //comprime a main.min.js
        .pipe(gulp.dest('./dist')); //Destino del nuevo fichero en el directorio ./dist 
});
</code></pre>

<p>Con esto le estamos indicando a gulp que coja cualquier fichero javascript que se encuentre bajo el directorio src y lo comprima en un solo fichero llamado main.min.js en el directorio ./dist de nuestra aplicación.</p>

<p>Pero, ¿que pasa si necesitamos comprimirlos en orden?, puede darse el caso de que debamos incluir nuestros módulos javascript en cierto orden debido a las dependencias que tienen, para ese caso simplemente tenemos que cambiar en <em>gulp.src()</em> el string que contiene el directorio, a un array con todos los scripts ordenados:</p>

<pre><code>var myScripts = [ 'src/uno.js', 'src/dos.js' ];
</code></pre>

<p>Volvemos a la terminal, ejecutamos gulp scripts y aparecerá nuestro script listo para producción en el directorio ./dist.</p>

<p>Muy bien, con esto tenemos definida una tarea simple, pero se nos puede hacer pesado estar ejecutando gulp scripts a cada cambio que realizamos, así que vamos a crear una tarea que monitorize nuestras scripts y automáticamente ejecute la tarea scripts.</p>

<p>Creamos una nueva tarea llamada watch (o como quieras llamarla), le pasamos los ficheros o directorio que ha de monitorizar, y un array con las tareas que ha de llevar a cabo cuando ocurra algún cambio:</p>

<pre><code>gulp.task('watch', function(){ 
    gulp.watch(myScripts, ['scripts']); 
});
</code></pre>

<p>Ahora desde terminal, en vez de ejecutar <em>gulp scripts</em>, ejecutaríamos <em>gulp watch</em>, y así cada vez que hiciéramos una modificación a uno de nuestros ficheros javascript se ejecutaría de manera transparente para nosotros la tarea scripts. Si tuvieras más tareas definidas que quisieras ejecutar cuando se detecta un cambio simplemente tendrías que añadirlas al array que le pasamos como segundo parámetros a <em>gulp.watch</em> en el orden que quieras que se ejecuten. También puede darse el caso de que quieras hacer watch de diferentes directorios y que ejecuten diferentes tareas, entonces simplemente añade otro gulp.watch a la tarea:</p>

<pre><code>gulp.task('watch', function(){ 
    gulp.watch(myScripts, ['scripts']);
    gulp.watch('miOtroDirectorio',['miOtraTarea']); 
});
</code></pre>

<p>Como ya dije hay muchos módulos de diversas funcionalidades, cualquier cosa que se pueda automatizar seguro que tiene su modulo correspondiente, pero normalmente los módulos o librerías de gulp suelen ser bastante específicos en su función, esto quiere decir que un modulo que comprime quizás no haga renombrado de ficheros, y en ese caso tendrás que encadenar diferentes módulos dentro de la misma tarea, pongamos como ejemplo un compilador LESS, cumple su función compilando, pero no nos permite cambiar el nombre al css resultante, así que vamos a instalar en esta ocasión dos dependencias para hacer esta tarea, gulp-less y gulp-rename:</p>

<pre><code>npm install --save-dev gulp-less gulp-rename
</code></pre>

<p>Como de costumbre los añadimos a nuestro fichero gulpfile:</p>

<pre><code>var gulp = require('gulp'), 
    uglify = require('gulp-uglifyjs'), 
    less = require('gulp-less'), 
    rename = require('gulp-rename');
</code></pre>

<p>Y creamos la tarea correspondiente, encadenando una detrás de otras las acciones que ha de hacer nuestra tarea:</p>

<pre><code>gulp.task('css', function(){ 
    return gulp.src('src/main.less') 
        .pipe(less()) //Compilamos 
        .pipe(rename('compiled-style.css')) //Renombramos
        .pipe(gulp.dest('./dist')); //Indicamos destino 
});
</code></pre>

<p>Imaginando que tenemos un archivo llamado main.less en el directorio ./src, al ejecutar en la terminal <em>gulp css</em> compilaría este less a css, lo renombraría a compiled-style.css y lo ubicaría en ./dist, si elimináramos la linea que incluye el rename el fichero resultante se llamaría main.css. Como ves puedes encadenar todas las acciones que te hagan falta, por ejemplo en este caso podríamos añadir también una modulo que minificara el fichero resultante, pero a estas alturas seguro que ya sabrás hacerlo tu mismo.</p>

<p>Todo esto está muy bien, pero se hace algo pesado ir ejecutando las tareas una a una mediante <em>gulp nombreTarea</em>, así que lo vamos a definir dentro de una tarea llamada default, así tan solo debemos ejecutar <em>gulp</em> en la terminal y se ejecutarán todas las tareas y si una de las tareas es watch pues se quedará observando:</p>

<pre><code>gulp.task('default', ['scripts', 'css', 'watch']);
</code></pre>

<p>Con esto hacemos que al poner simplemente <em>gulp</em> en la terminal se ejecute primero la tarea scripts, luego css y por ultimo watch, y de esta forma nos despreocupemos por estar ejecutando nosotros todo por separado.</p>

<p>Espero que esta pequeña introducción sea de utilidad, he dejado disponible el código en <a href="https://github.com/Nazariglez/GulpJS-Demo">Github</a> por si alguien quiere echarle un ojo. Investigad en la <a href="http://gulpjs.com/plugins/" title="Plugins para gulpjs">pagina de plugins</a> que funcionalidades existen, seguro que alguna os sorprende, y si queréis dejar en los comentarios que usos le das tu a gulp o cualquier duda o sugerencia, será bien recibida!.</p>]]></description><link>http://www.nazariglez.com/2014/07/21/primeros-pasos-con-gulp-js/</link><guid isPermaLink="false">0a962246-23f9-47a0-8a6b-e5601536743e</guid><category><![CDATA[grunt]]></category><category><![CDATA[gulp]]></category><category><![CDATA[Javascript]]></category><category><![CDATA[nodejs]]></category><category><![CDATA[Programación]]></category><category><![CDATA[Tutoriales]]></category><dc:creator><![CDATA[Nazarí Glez]]></dc:creator><pubDate>Mon, 21 Jul 2014 06:45:49 GMT</pubDate></item><item><title><![CDATA[Retomando el blog tras un intenso año]]></title><description><![CDATA[<p>Durante el ultimo año he dejado bastante abandonado el blog, el <a href="http://www.nazariglez.com/2013/12/30/ld28-post-morten-spee-the-sperm/" title="LD28 Post Morten: Spee The Sperm">ultimo post habla de la ludum dare</a> de finales del 2013, pero es que <a href="http://www.nazariglez.com/2013/08/27/un-mes-sin-escribir-pero-con-una-buena-excusa/" title="Un mes sin escribir, pero con una buena excusa">el anterior</a> data de agosto de ese mismo año, casi 1 año en el que solo han habido dos post, vamos, que he perdido las buenas costumbres de escribir frecuentemente.</p>

<p>Aún así, para mi sorpresa la gente sigue visitando el blog, no como cuando publicaba casi a diario, pero eso tiene remedio :).</p>

<p>El ultimo año para mi ha sido realmente intenso, he aprendido muchísimas cosas nuevas, y he vivido muchísimos cambios, uno de los más grandes ha sido dejar un trabajo en el que llevaba muchos años y me sentía estancado, para entrar a trabajar en <a href="http://ludei.com/" title="Ludei">Ludei</a> como Javascript/Game Developer, donde en pocos meses he aprendido más que en toda mi vida, el estar rodeado de tanta buena gente y tanto crack es simplemente impresionante, os podéis hacer una idea leyendo este post de mi amigo <a href="https://twitter.com/k4rliky">Carlos</a> -> <a href="http://nogg-aholic.es/como-es-trabajar-rodeado-de-programadores-con-talento/">http://nogg-aholic.es/como-es-trabajar-rodeado-de-programadores-con-talento/</a>.</p>

<p>Mi idea es coger un ritmo adecuado de publicación en el blog, a diario… no. A diario requiere demasiada dedicación y te deja poco tiempo para side projects o simplemente experimentar, por lo que de momento no lo volveré a hacer. También añadiré videotutoriales que seguro son un buen complemento para entender algunos post, o directamente el video, sin el post, depende del tema.</p>

<p>Sin más, tengo una larga lista de cosas de las que quiero hablar, ahora solo me queda encontrar algo de tiempo, las ganas, y retomar esta sana costumbre.</p>]]></description><link>http://www.nazariglez.com/2014/07/16/retomando-el-blog-tras-un-intenso-ano/</link><guid isPermaLink="false">e8fa2a96-5c60-454a-b7a6-094990bd97ca</guid><category><![CDATA[Off Topic]]></category><dc:creator><![CDATA[Nazarí Glez]]></dc:creator><pubDate>Wed, 16 Jul 2014 07:06:53 GMT</pubDate></item><item><title><![CDATA[LD28 Post Morten: Spee The Sperm]]></title><description><![CDATA[<p>Llevo tiempo sin escribir y eso hay que remediarlo, así que romperé el hielo con mi experiencia en mi primera <strong><a href="http://www.ludumdare.com/compo/" title="Ludum Dare 28">Ludum Dare</a></strong>.</p>

<p>Llevaba tiempo queriendo presentarme a una Ludum Dare, todo el mundo comentaba lo maravilloso que era participar y yo no podía hacer que otra cosa que no fuera verlo desde fuera.</p>

<p>Al principio no me presentaba porque no me veía capaz/preparado para afrontar el desarrollo de un juego en tan solo 48 horas, y cuando me empezaba a ver “algo” capacitado no tenía tiempo, pero por fin en ésta última ocasión me vi capaz y motivado, y por suerte la fecha era un fin de semana en el que no tenía ningún compromiso, llegó el momento.</p>

<p>Unas horas antes de la Ludum Dare hablé con mi amigo <a href="http://www.rcdsign.es/" title="Rubén del Castillo">Rubén Del Castillo</a> para ver si quería participar, y no dudo ni un instante en unirse, quedamos a las dos de la mañana para ver que tema salía elegido y así los hicimos, a las dos estábamos despiertos y mirando como dos tontos en blanco el tema “<em>You Only Get One</em>”, pero que demonios…</p>

<p>Divagamos entre muchas ideas, tratando de ajustarnos todo lo posible al tema, estuvimos dando palos de ciegos al menos hasta las 4 o 5 de la mañana, donde desistimos y decidimos ir a dormir, dejándolo pendiente para la mañana de ese mismo día, cuando estuviéramos más despejados. Curiosamente mientras dormía se me ocurrieron unas mecánicas que cuadraban con el tema, y al contárselo a Rubén se le ocurrió una temática para el juego que también encajaba, un espermatozoide que debe llegar al óvulo, toma ya, toda una absurda genialidad ajajaja.</p>

<p>Esa misma mañana nos pusimos manos a la obra, el a diseñar y dibujar y yo a programar. Desde un comienzo tenía claro que el juego debía de ser html5, ya que, cuantas más facilidades tengan los usuarios para jugar más votos puedes conseguir, no es lo mismo entrar en un enlace y jugar que tener que descargar un archivo, instalar un plugin, o similares.</p>

<p>Como motor usé <a href="http://www.yoyogames.com/" title="Yoyo Games">Game Maker Studio</a>, llevaba ya unos meses usandolo y sabía que me permitiría programar rápidamente sin pararme demasiado en cosas como los assets, gestionar sprites, etcétera. Por lo general no uso sus herramientas “drag&amp;drop”, no me gustan, prefiero programar directamente, en este caso en <a href="http://es.wikipedia.org/wiki/Game_Maker_Language" title="Game Maker Language">GML</a> un lenguaje propio del motor, pero he de reconocer que la interfaz y la forma en la que está diseñado el motor te permite prototipar y desarrollar muy rápido. No tuve problemas significativos durante el desarrollo exceptuando las colisiones con los límites de la escena, que no funcionaban como debían, y de hecho no lo hacen, perdí mucho tiempo con este tema, ya que “los controles” del personaje y el sistema de colisiones no eran del todo compatibles, así que hice un apaño que funciona pero que no quedó bonito porque genera un efecto de “rebote” del personaje al tocar un limite, pero bueno, el tiempo corría y no podía pararme demasiado a probar.</p>

<p>Durante el desarrollo lo que más nos costó desde mi punto de vista fue comunicarnos correctamente. Al trabajar separados y ser la primera vez que trabajamos juntos se hacía complicado hacer entender al otro el concepto que teníamos en la cabeza, en ambos sentidos, tanto de arte como de diseño y mecánicas, algunas veces cuando veíamos algo hecho se oía la frase “pensé que decías…, te había entendido…”. Al final todo cuadraba como debía y creo que hemos aprendido a comunicarnos de manera más eficiente, estoy seguro de que en el futuro seremos capaces de desarrollar juntos juegos más trabajados y gestionado el tiempo de manera más eficiente.</p>

<p>Durante el desarrollo probamos y debatimos varios modos de controlar al personaje, y curiosamente elegimos el “peor”. Una vez terminamos el juego parece que a la gente le gustó bastante, pero la mayoría se quejan de los controles que elegimos, en un principio son “complicados de coger” pero una vez que te acostumbras te olvidas, y creo que ese fue nuestro problema, nos acostumbramos a usarlo así y no luego no volvimos a pensar en ellos, pero tomamos nota para el futuro.</p>

<p>Terminamos casi en el último momento, a menos de media hora para el final subimos el juego, y en pocos minutos ya teníamos nuestros dos primeros comentarios. Hasta el momento la experiencia ha sido genial, hemos desarrollado un juego “curioso” en pocas horas, y yo me quedo con que trabajar con Rubén ha sido una “gozada”, su imaginación y la calidad de su trabajo es lo mejor que me llevo de esta LD.</p>

<p>Parece que este no será el último proyecto que desarrolle con Rubén, más bien es el primero de muchos que vendrán. Es más ya estamos pensando en un rediseño total de este juego, y planes con más gente, pero eso es otra historia, ya tendré tiempo de contarla, de momento si quieres puedes jugar un rato a Spee The Sperm!</p>

<p><strong>Spee en la LD:</strong><a href="http://www.ludumdare.com/compo/ludum-dare-28/?action=preview&amp;uid=19585">http://www.ludumdare.com/compo/ludum-dare-28/?action=preview&amp;uid=19585 <br>
</a><strong>Enlace directo:</strong><a href="http://www.nazariglez.com/ld28/" title="Spee The Sperm">http://www.nazariglez.com/ld28/</a></p>]]></description><link>http://www.nazariglez.com/2013/12/30/ld28-post-morten-spee-the-sperm/</link><guid isPermaLink="false">dc708421-c58d-48eb-ac3d-ae6550539a5f</guid><category><![CDATA[Game Maker]]></category><category><![CDATA[HTML5]]></category><category><![CDATA[Juegos]]></category><category><![CDATA[ludum dare]]></category><category><![CDATA[Programación]]></category><category><![CDATA[videojuegos]]></category><category><![CDATA[webgl]]></category><dc:creator><![CDATA[Nazarí Glez]]></dc:creator><pubDate>Mon, 30 Dec 2013 22:53:20 GMT</pubDate></item><item><title><![CDATA[Un mes sin escribir, pero con una buena excusa]]></title><description><![CDATA[<p>Como se puede ver llevo un mes sin escribir un solo post, pero esto no quiere decir que no esté haciendo nada, sino todo lo contrario. Creo que en los últimos tres años he estado dando palos de ciego, sabiendo que quiero trabajar como programador pero sin definir en que, desarrollando herramientas en php, aplicaciones webs, aplicaciones en node, juegos html5, pequeños juegos móviles, y un largo etcétera. Esto me ha servido para aprender muchísimas cosas, conocer gente genial y para no terminar nada de lo que comienzo.</p>

<p>Pero desde hace unos tres meses estoy más centrado, voy sintiéndome cómodo con diferentes herramientas y tecnologías a la hora de trabajar y creo que estas forman mi abanico de trabajo. Tengo muchas cosas que contar en el blog, y espero que pronto se vean los resultados de esta etapa, tengo planes para el año próximo y aún unos meses por delante para trabajar en mis ideas.</p>

<p>En los próximos dias trataré de actualizar el blog con algunas cosas interesantes que he descubierto, hasta entonces! Un Saludo</p>]]></description><link>http://www.nazariglez.com/2013/08/27/un-mes-sin-escribir-pero-con-una-buena-excusa/</link><guid isPermaLink="false">aa1fe267-0f09-426e-b8c1-69372ee9129c</guid><category><![CDATA[delirios]]></category><category><![CDATA[Off Topic]]></category><dc:creator><![CDATA[Nazarí Glez]]></dc:creator><pubDate>Tue, 27 Aug 2013 13:35:46 GMT</pubDate></item><item><title><![CDATA[Crear un chat y un tres en raya con Node.js y Socket.io]]></title><description><![CDATA[<p>No es la <a href="http://www.nazariglez.com/tag/node-js/" title="NodeJS en Nazarí González">primera vez que hablo de <strong>Node.js</strong> o de <strong>Socket.io</strong></a> en el blog, ni creo que sea la ultima, en esta ocasión he realizado una pequeña <a href="http://www.estoycreando.com/3enraya" title="Tres en raya con NodeJS y SocketIO">aplicación para jugar al tres en raya</a> mientras hablamos con el resto de jugadores mediante un chat.</p>

<p>Su funcionalidad en sí en bastante sencilla, solo se permite una partida a la vez ya que no hago uso de “<em>rooms</em>” (<em>salas</em>), cosa que me gustaría tocar en el blog pronto. Para empezar introducimos nuestro nombre y ingresamos al chat, el tablero de juego es visible desde el comienzo, si hay jugadores en plena partida podemos observar como evoluciona ésta, si no hay jugadores podemos unirnos y esperar un contrincante. El chat nos indica quien entra o sale de la aplicación y quien gana y pierde la partida en curso.</p>

<p>Vamos a lo interesante, la tecnología que hay detrás de la aplicación, he tratado de comentar todo lo posible el codigo así que explicaré ligeramente solo algunos detalles.</p>

<p>Primero el cliente; Como verás en el código no he usado ningún sistema de plantillas, simplemente sirvo un fichero html que se encuentra en el directorio “<em>/public</em>”. En esta ocasión tampoco he usado el elemento canvas, sino que uso divs y los altero mediante Javascript (<a href="http://jquery.com/" title="Pagina de Jquery"><em>Jquery</em></a>), mostrando así lo que el servidor le indica a través de los websockets. He usado <a href="http://lesscss.org/" title="Web de LessCSS"><strong>LessCSS</strong></a> para el estilo, pero es todo muy minimalista, lo uso por comodidad realmente.</p>

<p>La aplicación no usa base de datos, por lo que para almacenar los nombres de usuarios online y no repetirlos uso un array, que se comprueba cada vez que ingresa un nuevo jugador, sobra decir que al cerrar y abrir la app perdemos todos los usuarios, además para evitar inyección de código he usado el modulo “<a href="https://github.com/theSmaw/Caja-HTML-Sanitizer" title="Modulo para limpiar codigo en nodejs">sanitizer</a>”.</p>

<p>Lo mejor de Socket.io es que la información referente al socket está en formato <strong>JSON</strong> por lo que aprovecho para guardar el nombre del usuario como parte de el, en <em>socket.nick</em>, y así poder identificar al usuario fácilmente. Por ejemplo es útil cuando se desconecta un usuario compruebo el nick y lo elimino del array de usuarios y anuncio su desconexión al resto de jugadores.</p>

<p>Otro punto que me gustaría comentar es el uso de callbacks al emitir información mediante socket.io, yo lo he usado por ejemplo para medir la latencia, pero es realmente útil. Normalmente vemos ejemplos en los que emitimos un evento mediante socket.emit y recibimos respuesta mediante socket.on, algo así:</p>

<p><em>Cliente:</em></p>

<pre><code>socket.emit('hola', true); socket.on('hola', function(){});
</code></pre>

<p><em>Server:</em></p>

<pre><code>socket.on('hola', function(data){ 
    if(data)socket.emit('hola', true); 
});
</code></pre>

<p>Pero si nuestro propósito es enviar una información y dependiendo de la respuesta realizar una determinada acción siendo siempre el mismo usuario, ¿Por que no usar un callback?, sería mucho más eficiente:</p>

<p><em>Cliente:</em></p>

<pre><code>socket.emit('hola', true, function(data){});
</code></pre>

<p><em>Server:</em></p>

<pre><code>socket.on('hola', function(data, callback){ 
    if(data){ 
        if(callback &amp;&amp; typeof callback == 'function'){
            callback(data); 
        } 
    }
});
</code></pre>

<p>No me quiero enredar demasiado ni explicar cosas que ya estén explicadas en el código, así que os dejo un enlace a la demostración y al código alojado en github.</p>

<p><strong>Github:</strong><a href="https://github.com/Nazariglez/3enraya-nodejs-socketio" title="Tres en raya con NodeJS y SocketIO en Github">https://github.com/Nazariglez/3enraya-nodejs-socketio</a> <br>
<strong>Demo:</strong><a href="http://www.estoycreando.com/3enraya/" title="Tres en raya más chat con NodeJS y SocketIO">http://www.estoycreando.com/3enraya/</a></p>]]></description><link>http://www.nazariglez.com/2013/07/23/crear-un-chat-y-un-tres-en-raya-con-node-js-y-socket-io/</link><guid isPermaLink="false">99908439-ecab-49b5-a9cd-33be97ce7c36</guid><category><![CDATA[html5]]></category><category><![CDATA[Javascript]]></category><category><![CDATA[node]]></category><category><![CDATA[node.js]]></category><category><![CDATA[nodejs]]></category><category><![CDATA[Programación]]></category><category><![CDATA[socket.io]]></category><category><![CDATA[socketio]]></category><dc:creator><![CDATA[Nazarí Glez]]></dc:creator><pubDate>Tue, 23 Jul 2013 20:47:46 GMT</pubDate></item><item><title><![CDATA[Como usar varias aplicaciones NodeJS bajo un mismo dominio sin mostrar los puertos de acceso gracias a nginx]]></title><description><![CDATA[<p>Los que alguna vez hayáis trasteado con <a href="http://nodejs.org/" title="Web de Node.js"><strong>NodeJS</strong></a> para realizar una aplicación web os habréis fijado en que hay que declarar un puerto de escucha y que para acceder a nuestra aplicación hay que usar el nombre de dominio o IP más el puerto como url en el navegador, algo así: <em><a href="http://127.0.0.1:3000/">http://127.0.0.1:3000</a></em>. <br>
 Esto no pasa solo con NodeJS, sino también con otros frameworks de desarrollo web, pero como me siento cómodo usando node y no he trabajado con otros frameworks webs que no sean basados en javascript o php no puedo generalizar, así que usaré node como ejemplo, dejando claro que <strong>estas pautas pueden servir para cualquier aplicación web que nos permita manejar el puerto de escucha.</strong></p>

<p>Por norma general el puerto por defecto para las aplicaciones web suele ser el puerto 80, supongamos entonces que tenemos una aplicación ocupando el puerto 80 bajo el dominio localhost, al entrar en <em><a href="http://localhost/">http://localhost/</a></em> nos mostraría nuestra aplicación, pero si queremos usar el mismo servidor con otra aplicación simultáneamente deberemos de elegir otro puerto de escucha, el 3000 por ejemplo, en ese caso al entrar en <em><a href="http://localhost/">http://localhost/</a></em> veremos la aplicación en el puerto 80, y al entrar en* <a href="http://localhost:3000/*">http://localhost:3000/*</a> veremos la otra.</p>

<p>No es muy bonito ¿no?, no me veo a una empresa dando su web en plan “<em><a href="http://pincelesybrochasmanolo.com:3000/">http://pincelesybrochasmanolo.com:3000</a></em>”. Entonces, ¿que hacemos?. Necesitamos un servidor que gestione las redirecciones de manera interna, de forma que al facilitarle una ruta en concreto el nos muestre la aplicación que definamos de una manera limpia para el usuario final dando igual el puerto que sea. Así podríamos tener un “<em>hola mundo</em>” en el puerto 3000, un chat en el 4000, y un blog en el 4500 de forma que usando rutas tipo <em><a href="http://localhost/chat/">http://localhost/chat/</a></em>, <em><a href="http://localhost/hola/">http://localhost/hola/</a></em> o <em><a href="http://localhost/blog/">http://localhost/blog/</a></em> nos mostrara las aplicaciones correspondientes.</p>

<p>Tomando como sistema operativo ubuntu, voy a ir realizando los pasos necesarios para lograr esto, para ello solo necesitamos 4 cosas, <strong>NodeJS</strong>, <a href="https://npmjs.org/" title="Web del gestor de paquetes NPM"><strong>NPM</strong></a>, <a href="http://nginx.org/" title="Web de NGINX"><strong>Nginx</strong></a> y <strong>Screen</strong>.</p>

<p>Lo primero es instalar la ultima versión de NodeJS y NPM; abrimos un terminal y tecleamos:</p>

<pre><code>sudo apt-get install python-software-properties 
sudo add-apt-repository ppa:chris-lea/node.js 
sudo apt-get update 
sudo apt-get install nodejs
</code></pre>

<p>Este repositorio nos facilita la ultima versión de node y de npm solo instalando el paquete nodejs, si estás exceptico y quieres comprobar que npm también se ha instalado solo tienes que realizar un <em>npm -v</em> en la terminal.</p>

<p>Si ahora creáramos dos aplicaciones que nos mostrara Hola mundo en la pantalla bajo diferentes puertos, y quisiéramos abrir ambas nos encontraríamos en que hemos de cerrar una para poder abrir otra, o abrir varias terminales, por lo que no es muy útil si tengo que tener abierta indefinidamente una sesión ssh con cada una de las aplicaciones. Para solucionar esto usaremos Screen.</p>

<pre><code>sudo apt-get install screen
</code></pre>

<p><strong>Screen es un emulador de terminales virtuales</strong>, viene a ser la soluciones perfecta a nuestro problema, puesto que nos permite abrir terminales para ejecutar nuestras aplicaciones y abandonar la sesión sin cerrar la terminal (<em>virtual</em>), dejándola en un segundo plano trabajando. <br>
 Su uso es realmente muy sencillo, con el comando “<em>screen</em>” en una terminal abriremos una nueva terminal virtual, trabajamos con ella de manera normal y cuando queramos dejarla en segundo plano pulsaremos la combinación de teclas <em>control + A</em>, y a continuación la tecla <em>D</em> en solitario, esto nos devolverá a la terminal inicial relegando la virtual a un segundo plano. Ahora podemos abandonar la sesión ssh sin miedo a cerrar la aplicación que tenemos en funcionamiento. Para recuperar está terminal virtual basta con teclear <em>screen -r</em>, si queremos cerrarla totalmente simplemente tecleamos <em>exit</em> en ésta y se cerrará. Si tenemos más de una terminal virtual abierta y usamos el comando <em>screen -r</em> nos informará de que hay varias terminales en segundo plano, y facilitándonos el numero de identificación de cada una, debemos usar <em>screen -r [numero]</em> para ver una en concreto. Podéis encontrar más información sobre los comandos de screen aquí <a href="http://www.guia-ubuntu.com/index.php?title=Screen" title="Guia sobre Screen">http://www.guia-ubuntu.com/index.php?title=Screen</a>.</p>

<p>Ahora que tenemos NodeJS, NPM, y Screen instalado queda el tema de redireccionar las rutas a puertos concretos de nuestro servidor.</p>

<p><strong>Nginx</strong> será el encargado de ésta tarea. En resumen se trata de un servidor web/proxy, lo mejor para entender su potencial es dirigirnos a la información que nos facilita la wikipedia sobre el: <a href="http://es.wikipedia.org/wiki/Nginx" title="Nginx en Wikipedia">http://es.wikipedia.org/wiki/Nginx</a>.</p>

<p>Para instalarlo en nuestro Ubuntu introducimos lo siguiente en una terminal:</p>

<pre><code>sudo add-apt-repository ppa:nginx/stable 
sudo apt-get update 
sudo apt-get install nginx
</code></pre>

<p>Una vez se ha instalado en nuestro sistema procedemos a configurarlo. Una buena idea es redireccionar los acceso al dominio sin www al que si las tiene, o viceversa, podemos hacerlo desde su fichero de configuración, para acceder a el:</p>

<pre><code>sudo nano /etc/ngnix/ngnix.conf
</code></pre>

<p>Como verás al abrirlo la configuración esta organizada en un formato similar a <a href="http://es.wikipedia.org/wiki/JSON" title="Json en wikipedia">JSON</a>, buscamos en este <em>http {}</em> y añadimos lo siguiente:</p>

<pre><code>server { 
    listen 80; 
    server_name midominiosinwww.com;
    return 301 $scheme://www.midominioconwww.com$uri; 
}
</code></pre>

<p>De está forma estamos indicando a los navegadores y bots que accedan a nuestro dominio (<em>puerto 80 por defecto</em>) que se ha redirigido de manera permanente al indicado en la linea return. Esto es cuestión de gustos, quizás no quieras la redirección, o quizás te guste más sin www o al revés, personaliza las lineas de forma que se adapten a lo que buscas.</p>

<p>Lo siguiente es indicar el fichero por defecto que se ha de mostrar al entrar a la raíz del dominio, para eso añadimos esto a nuesta configuración dentro de <em>http {}</em>:</p>

<pre><code>server { 
    listen 80; 
    server_name www.midominioconwww.com;
    location / { 
        root /home/midominio;
        index index.html;
    }
}
</code></pre>

<p>Le estamos indicando que al entrar un usuario le sirva el fichero <em>index.html</em> que se encuentra en el directorio <em>/home/midominio/</em> de nuestro servidor, esta podría ser nuestra <a href="https://es.wikipedia.org/wiki/P%C3%A1gina_de_aterrizaje" title="Landing Page en wikipedia">Landing Page</a>, seguimos con la redirección a nuestras aplicaciones NodeJS que están funcionando en segundo plano gracias a screen.</p>

<p>Añadimos dentro de esta configuración de server lo siguiente:</p>

<pre><code>location /hola/ { 
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host; 
    proxy_set_header X-NginX-Proxy true; 
    proxy_pass http://localhost:3000/; 
    proxy_redirect off; 
}
</code></pre>

<p>Así por cada ruta que necesitemos, cambiando ésta en la linea location e indicando la dirección de la aplicación que ha de servir en la linea proxy_pass, la configuración final podría ser algo parecida a esto:</p>

<pre><code>server { 
    listen 80; 
    server_name www.midominioconwww.com; 
    location /hola/ { 
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true; 
        proxy_pass http://localhost:3000/;
        proxy_redirect off;
    } 
    location /chat/ { 
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true; 
        proxy_pass http://localhost:4000/;
        proxy_redirect off; 
    } 
    location /blog/ { 
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true; 
        proxy_pass http://localhost:4050/;
        proxy_redirect off; 
    } 
    location / { 
        root /home/midominio index index.html; 
    } 
} 
server { 
    listen 80; 
    server_name midominiosinwww.com; 
    return 301 $scheme://www.midominioconwww.com$uri; 
}
</code></pre>

<p>Guardamos el documento y reinciamos nginx mediante:</p>

<pre><code>sudo service nginx restart
</code></pre>

<p>Ya podemos acceder mediante las urls que tengamos definidas a nuestras aplicaciones Node (u otras) de una manera limpia de cara al usuario.</p>

<p>No busco profundizar mucho en nginx porque de momento no se mucho más de lo que he puesto aquí, si quieres seguir profundizando en su configuración (que es muy versatil) puedes echarle un ojo aquí: <a href="http://wiki.nginx.org/Configuration" title="Ayuda de configuración de nginx">http://wiki.nginx.org/Configuration</a></p>]]></description><link>http://www.nazariglez.com/2013/07/10/como-usar-varias-aplicaciones-nodejs-bajo-un-mismo-dominio-sin-mostrar-los-puertos-de-acceso-gracias-a-ngnix/</link><guid isPermaLink="false">4cbf562c-5065-4296-939d-2409ccc83e43</guid><category><![CDATA[Linux]]></category><category><![CDATA[nginx]]></category><category><![CDATA[node.js]]></category><category><![CDATA[nodejs]]></category><category><![CDATA[npm]]></category><category><![CDATA[Programación]]></category><category><![CDATA[screen]]></category><category><![CDATA[ubuntu]]></category><dc:creator><![CDATA[Nazarí Glez]]></dc:creator><pubDate>Wed, 10 Jul 2013 07:45:21 GMT</pubDate></item></channel></rss>