El Chigüire Literario Desarrollo de videojuegos con denominación de origen

Un anuncio importante

Hoy tengo algo importante qué decir. Creo que es importante compartirlo con todos los que siguen mi trabajo.

Acepté una oferta para estudiar un máster en programación de videojuegos en Reino Unido, con la duración de un año. Al momento que ustedes están leyendo esta nota, ya habremos cruzado el charco y habré iniciado el curso. El curso lo haré en Goldsmiths College, una universidad que tiene una fuerte tradición en las artes, algo que me atrae inmensamente. El propio master está fuertemente orientado a programación. De hecho, uno de los profesores del curso ha trabajado por más de 30 años en el área, y en su currículum más reciente trabaja con los compiladores que utiliza Sony para el PlayStation.

Estos últimos meses para mí han sido de una terrible presión. Emigrar no es solamente una prueba que consiste en recoger todos los requisitos y estás listo. Es un test psicológico que evalúa la fortaleza de tu espíritu y de los que te rodean. Gracias de verdad a toda la familia y amigos que nos acompañaron y nos apoyaron en este duro proceso.

En el momento que tu mente se establece en la idea de que te vas a establecer a un lugar desconocido, el sólido piso que pensabas que tenías desaparece y entras en una caída libre, donde lo que conocías deja de tener sentido y se deben cumplir una serie de pasos secuenciales para que la vida continúe. Y en el tiempo que toma cumplir cada paso la sanidad mental peligra por la espera.

Pienso que en Venezuela se cultiva un talento impresionante en el desarrollo de videojuegos. Se cultiva a pesar de tantas cosas que ocurren alrededor que afectan o minimizan su importancia. Como saben, el Caracas Game Jam 2014 se hará y será más grande que el anterior. El Chigüire Literario continuará publicando artículos y tutoriales en español. Mi página, www.ciroduran.com, tendrá artículos en ambos idiomas. Es necesario que ustedes como desarrolladores se sigan destacando con su trabajo, y sigan conversando entre ustedes.

En algún momento varios de ustedes se hicieron la pregunta: “¿soy el único programador de videojuegos en Venezuela?”. Creo que ya esta es una etapa superada para muchos de ustedes, y la siguiente pregunta debería ser: “¿qué podemos hacer juntos?”. Los resultados ya los han visto todos los que han participado en el jam, y otras iniciativas que he visto por allí. Desde este lado de la pantalla, ofrezco todo el apoyo que necesiten para difundir sus trabajos.

Muchas gracias por leerme, seguirme y apoyarme. Espero que siga siendo así.

gracias

Desarrollando videojuegos con cocos2d-html5 (6): Entre escenas se entienden

cocos2d-tutorial-6

Entre escenas se entienden

En esta parte veremos cómo manejar las funciones de schedule de una escena para llamar a funciones con intervalos regulares de tiempo, cómo hacer varias escenas para agrupar funcionalidades y cómo hacer una transición entre una escena y otra.

Las escenas en cocos2d encapsulan el comportamiento de un juego. De esta manera, puedes tener una escena para el menú inicial, otra escena para el juego como tal, otra escena para los créditos, y así. En proyectos más complejos podrías incluso tener más de una escena para tu juego, por ejemplo, una escena de inventario.

Qué son las escenas

Las escenas en cocos2d ayudan a separar las funcionalidades que puedes tener en un juego. Por ejemplo, en un proyecto sencillo, tendrías una escena para mostrar un menú inicial, tendrías otra escena para implementar el juego, y tendrías otra para mostrar las mejores puntuaciones.

Una de las ventajas que ofrece cocos2d es el manejo automático de memoria, por lo que las escenas de cocos2d no solamente ayudan a organizar el código, también facilitan la utilización de recursos de la computadora.

El manejo de la memoria funciona así: cuando creas una escena es necesario tener que crear todos sus componentes: sprites, nodos, textos, etc. y agregarlos a la misma. Cuando cambias de escena, no necesitas tener que destruir esos componentes explícitamente porque las referencias que hace esa escena saliente también son eliminadas.

Ya en pasadas entregas hemos creados escenas a partir de los componentes básicos de cocos2d, por lo que vamos a ver a continuación cómo cambiar de una escena a otra.

Vamos a escribir dos escenas, una de un título, y otra con “el juego”. Esta parte utiliza los elementos prestados de la sección 4 de este tutorial.

//myApp.js
var MyLayer = cc.Layer.extend({
    init:function () {
        //////////////////////////////
        // 1. super init first
        this._super();
        var size = cc.Director.getInstance().getWinSize();
        var closeItem = cc.MenuItemImage.create(
            s_buttonNormal,
            s_buttonSelected,
            function () {
                cc.Director.getInstance().replaceScene(new GameScene());
            }, this);
        closeItem.setAnchorPoint(cc.p(0.5, 0.5));
        closeItem.setPosition(cc.p(size.width/2, 40));
        var menu = cc.Menu.create(closeItem, null);
        menu.setPosition(cc.PointZero());
        this.addChild(menu, 1);
        // create new label
        this.helloLabel = cc.LabelTTF.create("El Titulo", "Arial", 38);
        // position the label on the center of the screen
        this.helloLabel.setPosition(cc.p(size.width / 2, size.height - 40));
        // add the label as a child to this layer
        this.addChild(this.helloLabel, 5);
        return true;
    },
});
var MyScene = cc.Scene.extend({
    onEnter:function () {
        this._super();
        var layer = new MyLayer();
        this.addChild(layer);
        layer.init();
    }
});
//GameScene.js
//Recordemos que debemos incluir 'src/GameScene.js' en cocos2d.js
var GameLayer = cc.Layer.extend({
    init:function () {
        this._super();
        var size = cc.Director.getInstance().getWinSize();
        var closeItem = cc.MenuItemImage.create(
            s_buttonNormal,
            s_buttonSelected,
            function () {
                cc.Director.getInstance().replaceScene(new MyScene());
            }, this);
        closeItem.setAnchorPoint(cc.p(0.5, 0.5));
        closeItem.setPosition(cc.p(size.width/2, 40));
        var menu = cc.Menu.create(closeItem, null);
        menu.setPosition(cc.PointZero());
        this.addChild(menu, 1);
        // create new label
        this.helloLabel = cc.LabelTTF.create("El Juego", "Arial", 38);
        // position the label on the center of the screen
        this.helloLabel.setPosition(cc.p(size.width / 2, size.height - 40));
        // add the label as a child to this layer
        this.addChild(this.helloLabel, 5);
        return true;
    },
});
var GameScene = cc.Scene.extend({
    onEnter:function () {
        this._super();
        var layer = new GameLayer();
        this.addChild(layer);
        layer.init();
    }
});

Veamos las líneas que corresponden exactamente a la transición entre una escena y otra.

Estas líneas podemos agregarles algo más para que hayan transiciones suaves entre escenas. Antes de pasar a las transiciones veamos cómo podemos agregar funcionalidad extra a la escena que corra mientras esté activa.

Mientras tanto, al correr este código comprobaremos que se puede hacer un cambio entre una escena y otra.

escenas Funciones schedule Las funciones schedule permiten ejecutar código cada cierto tiempo dentro de una escena. El caso general es en cada etapa de redibujo de la escena, pero es perfectamente posible hacerlo para intervalos arbitrarios.

Veamos cómo hacer una función que imprima algo en consola:

//myApp.js
var MyLayer = cc.Layer.extend({
    init:function () {
        this._super();
        var size = cc.Director.getInstance().getWinSize();
        // create and initialize a label
        this.helloLabel = cc.LabelTTF.create("El Titulo", "Arial", 38);
        // position the label on the center of the screen
        this.helloLabel.setPosition(cc.p(size.width / 2, size.height - 40));
        // add the label as a child to this layer
        this.addChild(this.helloLabel, 5);
        this.scheduleUpdate();
        return true;
    },
    update:function (dt) {
        cc.log("Hola");
    },
});
var MyScene = cc.Scene.extend({
    onEnter:function () {
        this._super();
        var layer = new MyLayer();
        this.addChild(layer);
        layer.init();
    }
});

Fijémonos que en la función init() llamamos a this.scheduleUpdate(), que instruye a cocos2d a que llame en cada frame a la función update que definimos a continuación. La función update tiene un parámetro llamado dt, que es un número real que indica la diferencia de tiempo desde la última llamada a update.

Veamos cómo hacer una función que mueva un objeto en el centro de la pantalla en círculos:

//myApp.js
var MyLayer = cc.Layer.extend({
    init:function () {
        this._super();
        var size = cc.Director.getInstance().getWinSize();
        this.elObjeto = cc.Sprite.create(s_buttonNormal);
        this.elObjeto.setAnchorPoint(cc.p(0.5, 0.5));
        this.elObjeto.setPosition(cc.p(size.width / 2.0 + 60, size.height / 2.0));
        this.addChild(this.elObjeto);
        this.rotacion = 0;
        // create new label
        this.helloLabel = cc.LabelTTF.create("El Titulo", "Arial", 38);
        // position the label on the center of the screen
        this.helloLabel.setPosition(cc.p(size.width / 2, size.height - 40));
        // add the label as a child to this layer
        this.addChild(this.helloLabel, 5);
        this.scheduleUpdate();
        return true;
    },
    update:function (dt) {
        var size = cc.Director.getInstance().getWinSize();
        //posicionar nuevamente elObjeto de acuerdo a una simple regla de trigonometría
        this.elObjeto.setPosition(cc.p(size.width / 2.0 + 60*Math.cos(this.rotacion), size.height / 2.0 - 60*Math.sin(this.rotacion)));
        this.rotacion += 5*Math.PI/180;
    },
});
var MyScene = cc.Scene.extend({
    onEnter:function () {
        this._super();
        var layer = new MyLayer();
        this.addChild(layer);
        layer.init();
    }
});

Transiciones

Para cerrar esta parte del tutorial, veremos cómo hacer esas transiciones suaves entre una escena y otra.

Para lograr esto, simplemente tenemos que crear la transición que necesitemos, pasándole la escena final a la que queramos llegar. Veamos un ejemplo revisando la función que llama al botón que definimos al inicio de la sección:

        var closeItem = cc.MenuItemImage.create(
            s_buttonNormal,
            s_buttonSelected,
            function () {
                var scene = cc.TransitionFade.create(1.2, new GameScene(), cc.c3b(0,0,0));
                cc.Director.getInstance().replaceScene(scene);
            }, this);

En este caso, estamos definiendo una transición que dura 1.2 segundos, que llega a GameScene, y que hace primero un fade al color negro y luego a la escena. Todas las transiciones se construyen de manera similar, especificando como mínimo el tiempo que toma la transición y a dónde lleva la escena. El resultado de esa llamada se la pasamos al director.

Todas las transiciones se exploran en la suite de pruebas de cocos2d-html5, por lo prefiero referirlos a ese código para saber cómo se hacen. Los tipos de transiciones que existen a la fecha son:

  • JumpZoom: la escena se aleja y salta fuera de la pantalla.
  • TransitionProgressRadial: su versión horaria (TransitionProgressRadialCW) y antihoraria (TransitionProgressCCW) que definen el sentido del barrido rotatorio a la nueva escena.
  • TransitionProgressHorizontal, TransitionProgressVertical
  • TransitionProgressInOut, TransitionProgressOutIn
  • FadeTransition, FadeWhiteTransition
  • ShrinkGrowTransition
  • RotoZoomTransition
  • MoveIn*Transition - L, R, T, B definen la dirección desde donde entra la escena.
  • SlideIn*Transition - L, R, T, B definen la dirección desde donde entra la escena, empujando a la anterior.

En la siguiente parte

En la siguiente parte de este tutorial veremos más a fondo los sprites, los layers, las partículas y los tiles, que son componentes básicos en la construcción de juegos. Nos veremos hasta entonces.

Rebotando ideas: Tiny David Tower

davidtower

Les presento un mockup de una idea que me ha venido dando vueltas desde hace mucho tiempo. Como a muchos, el tema de la Torre de David me causa muchísimo interés como sistema de vivienda. Así que aquí dibujé una idea de un posible juego que represente una invasión a un edificio abandonado.

El juego sería una parodia de Tiny Tower (mas no de la Torre de David real). El objetivo sería obtener la mayor felicidad posible de los habitantes, mejorando las condiciones de habitación dentro de lo posible.

El Futuro de la Programación, una charla de Bret Victor

Bret Victor es uno de mis héroes en el campo de la programación. Les recomiendo que vean esta charla, The Future of Programming, en la que habla sobre los dogmas de la programación que tenemos actualmente.

Previas cosas geniales de él: The Ladder of Abstraction, una mirada a cómo abstraer modelos, y también Inventing on Principle, una hermosa charla sobre cómo interactuar directamente con tus creaciones.

Tutorial sobre grillas hexagonales

lakeponca1

Amit Patel hizo este super compendio de información acerca de las grillas hexagonales. Si tu juego emplea este tipo de grillas (más precisas que las cuadriculadas debido a sus propiedades geométricas), entonces deberías leer este artículo acerca de qué estructuras de datos puedes emplear para implementarlas - http://www.redblobgames.com/grids/hexagons/