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

Mi ponencia y mesa de trabajo en las 6tas JOINCIC

Las 6tas Jornadas Interuniversitarias de Ciencias de la Computación se harán del 29 de mayo al 1ro de junio de 2013 en el Aula Magna de la Universidad Católica Andrés Bello, en Caracas. Los invito a estar presentes en la ponencia que haré sobre newsgames, llamada “Videojuegos con agenda”, en el que además relataré mi experiencia haciendo tres juegos. Esta ponencia se hará el jueves 30 de mayo, a las 11:00AM. El mismo día a las 4:00PM haré la mesa de trabajo “Usando cocos2d-html5 para juegos en el navegador”. Durante dos horas estaremos explorando esta librería escrita en Javascript para hacer videojuegos que se pueden jugar en el navegador de una computadora de escritorio o de dispositivo móvil. Los invito a compartir las imágenes promocionales de las charlas, y a que vengan a ver el resto de las ponencias y mesas de trabajo de estas jornadas organizadas por estudiantes de la UCAB, USB, UCV y UNEFA.

Videojuegos con agenda: el desarrollo de videojuegos orientado a expresarse sobre temas cotidianos

*Videojuegos con agenda: el desarrollo de videojuegos orientado a expresarse sobre temas cotidianos*

Usando cocos2d-html5 para juegos en el navegador. Una mesa de trabajo.

*Usando cocos2d-html5 para juegos en el navegador. Una mesa de trabajo.*

Desarrollando videojuegos con cocos2d-html5 (4): Comenzando un proyecto

cocos2d-tutorial-4Comenzando un proyecto

El resultado final de esta sección

*El resultado final de esta sección*

En esta parte del tutorial comenzaremos un proyecto de cocos2d-html5 a partir de la plantilla que la librería provee. Vamos a agregar una imagen, un texto y un botón a la escena y vamos a hacer que la imagen y el texto ejecuten unas acciones a partir de presionar el botón.

Copiemos el template

Para iniciar un proyecto con cocos2d-html5 basta con copiar el directorio template que se encuentra en el directorio que descomprimimos en la parte 2 del tutorial.

cocos2d-html5-4-1

¿Qué haremos ahora?

A partir de ahora iremos haciendo cambios sobre este proyecto para agregar algunos de los nodos que conocimos en la parte anterior. De ahora en adelante conoceremos de primera mano los pasos que hay que dar para crear los diferentes tipos de nodos.

El directorio template contiene prácticamente todos los elementos que vimos en la parte anterior, en el directorio HelloWorldHTML5, sin el Sprite de ejemplo. De esta manera, sólo hace falta quitar unos pocos elementos para comenzar a poner los de nuestro juego.

Si accedemos a nuestro juego, con la dirección http://localhost/a/leGame veremos nuestros inicios en ejecución:

helloworld1

Elaborando la primera escena

Cambiando un sprite

Vamos nuevamente a myApp.js. Observemos el código que se encarga de crear la imagen y colocarla sobre la capa.

//myApp.js
// add "Helloworld" splash screen"
this.sprite = cc.Sprite.create("res/HelloWorld.png");
this.sprite.setAnchorPoint(cc.p(0.5, 0.5));
this.sprite.setPosition(cc.p(size.width / 2, size.height / 2));

Casi todos los nodos en cocos2d se crean con su propia función create(). En el caso de cc.Sprite, puedes no pasar ningún parámetro para crear un sprite vacío, o un parámetro con el nombre de un archivo, o el nombre de un archivo junto con un rectángulo que determina las coordenadas dentro de ese archivo. Después de hacer este tutorial, cuando te encuentres dudando de cuáles son los parámetros que debes pasar a un nodo, revisa la función create respectiva para consultar.

Son muy específicos los casos donde debes hacer new de un objeto. La razón de esto es porque las funciones create se encargan también de manejar los objetos en memoria, por lo que cocos2d se encarga de liberar el objeto cuando tengas que destruir la escena, evitando memory leaks, algo doblemente importante cuando trabajas con los bindings en Javascript. En cocos2d este concepto se conoce como objetos autorelease.

La segunda función establece el ancla del objeto, o su origen en su sistema de coordenadas locales. En este caso el ancla está puesto en la mitad del sprite. Recuerda que estamos empleando el sistema de coordenadas de OpenGL, aquí una guía visual de lo que representa el anchor point en varios puntos:

cocos2d-html5-4-2

Observa que este sprite, que tiene de tamaño 42x40, tiene su centro en un punto que no corresponde a un único pixel.

La función cc.p es la misma función que cc.PointMake, y cc.Point, que retornan un objeto tipo punto. Estos nombres tienen más sentido cuando nos vamos a sus homólogos en C++.

La tercera función establece la posición del sprite. Recordemos que estamos en el sistema de coordenadas de OpenGL. El origen está en la esquina inferior izquierda, el eje x incrementa hacia la derecha, y el eje y incrementa hacia arriba. El objeto size que se encuentra en el código se obtiene de la función cc.Director.getInstance().getWinSize(), y es la que nos permite posicionar los objetos con respecto al tamaño de la ventana. En el caso de este código, el sprite se colocará exactamente en la mitad de la ventana.

Vamos entonces a descargar este sprite. Colócalo en el directorio ‘res’ del proyecto. Ahora cambia el nombre del archivo del sprite en el código

//myApp.js
// add "Helloworld" splash screen"
this.sprite = cc.Sprite.create(s_foobar);
this.sprite.setAnchorPoint(cc.p(0.5, 0.5));
this.sprite.setPosition(cc.p(size.width / 2, size.height / 2));

Hace falta tener que agregar también la definición de la variable s_foobar, y en consecuencia, la dirección de este archivo en resource.js. Así que vamos a este archivo, agreguemos una variable que contenga la dirección y agreguemos una entrada al arreglo g_ressources.

//resource.js
var s_foobar = "res/avatar_0.png";
var g_ressources = [
//...
{type:”image”, src:s_foobar},
//..
];

Por convención, iniciamos todos los nombres de los sprites con el prefijo s_, de tal manera que los podamos referenciar en los demás archivos sin tener que repetir el string con la dirección. Así, si tenemos que cambiar el nombre de un sprite, no tenemos que ir pasando sobre cada archivo cambiando el nombre, sino solamente cambiar la dirección en resource.js.

Es importante que incluyas todos los recursos que vayas a emplear para la carga, incluyendo las imágenes que son cargadas por otros archivos de texto, como los archivos .plist, o los archivos .fnt.

Ejecutemos nuevamente el juego y ahora obtendremos el siguiente resultado:

helloworld2

El Director y otros singletons

Habremos visto en el pedazo de código anterior de myApp.js esta llamada para obtener las dimensiones de la ventana:

var size = cc.Director.getInstance().getWinSize();

El objeto cc.Director es un objeto que cocos2d crea al inicializar toda la aplicación, y al igual que otros objetos, durante la ejecución de tu aplicación existe sólo una instancia a la que vas a acceder a través de la función getInstance(). Acostúmbrate a conseguir estas llamadas en varias partes del código.

Veremos también que con el director podremos cambiar de escenas y hacer otras cosas de interés. Pero esto lo dejaremos para otra parte del tutorial.

Controles rápidos con botones

Los botones encapsulan un comportamiento muy usual con los juegos: un elemento que presente un sprite cuando no hay un dedo tocándolo, presenta otro cuando lo toca, y una función que se va a llamar cuando lo presionas.

Tenemos varios tipos de botones, y todos parten del objeto MenuItem. Todos estos objetos deben ir en una capa especial de tipo Menu. El MenuItem de este código es un MenuItemImage, el cual se crea pasándole directamente las ubicaciones de las imágenes.

Otros tipos de MenuItem son:

  • MenuItemLabel: se crea pasándole un label (texto). Sobre los Labels hablaremos al final de esta sección.
  • MenuItemSprite: se crea pasándole dos sprites que hayas creado. Es útil para cuando las imágenes las extraes de un spritesheet.
  • MenuItemToggle: acepta dos MenuItems. Sirve para implementar botones “toggle”, que tienen dos estados, “encendido” y “apagado”, dependiendo de cuando los tocas.

Observemos entonces el código que crea el Menu y el botón actualmente:

// este código crea el MenuItemImage
var closeItem = cc.MenuItemImage.create(
    "res/CloseNormal.png",
    "res/CloseSelected.png",
    function () {
        history.go(-1);
    },this);
closeItem.setAnchorPoint(cc.p(0.5, 0.5));

//este código crea la capa de menu y agrega el MenuItemImage var menu = cc.Menu.create(closeItem, null); menu.setPosition(cc.PointZero()); this.addChild(menu, 1); closeItem.setPosition(cc.p(size.width - 20, 20)); Observemos que MenuItemImage acepta 4 parámetros, la imagen normal del botón, la imagen al ser presionada, la función que se va a llamar (que puede ser perfectamente una función anónima), y el “target” de la función (a qué se refiere el “this” dentro de la función). Esta función puede aceptar también 3 imágenes, la imagen normal, la seleccionada, y la que aparece cuando desactivas el botón con la función setEnabled(false). La función callback en este caso lo que hace es retroceder una página en el navegador. Si accedes al juego escribiendo el URL directamente no va a hacer nada.

Vamos a crear un nuevo botón descargando el estado normal y el estado seleccionado. Copiemos estas dos imágenes en el directorio res/. Vamos a escribir nuevo código debajo del bloque que acabamos de citar.

//myApp.js
closeItem = cc.MenuItemImage.create(
    s_buttonNormal,
    s_buttonSelected,
    function () {
        cc.log("Hola");
    }, this);
closeItem.setAnchorPoint(cc.p(0.5, 0.5));
closeItem.setPosition(cc.p(size.width/2, 40));

menu.addChild(closeItem); Veremos que la función que estamos pasando llama a la función cc.log(). Esto nos permite imprimir texto en la consola del navegador, bastante útil para depurar código cuando lo necesites. En el código hay nuevas variables, s_buttonNormal y s_buttonSelected, vamos a definirlas en resource.js:

//resource.js
var s_HelloWorld = "res/HelloWorld.png";
var s_CloseNormal = "res/CloseNormal.png";
var s_CloseSelected = "res/CloseSelected.png";

var s_foobar = “res/avatar_0.png”;

var s_buttonNormal = “res/button-normal.png”; var s_buttonSelected = “res/button-selected.png”;

var g_ressources = [ {type:”image”, src:s_HelloWorld}, {type:”image”, src:s_CloseNormal}, {type:”image”, src:s_CloseSelected}, {type:”image”, src:s_foobar}, {type:”image”, src:s_buttonNormal}, {type:”image”, src:s_buttonSelected}, ]; Volvamos a acceder a nuestro juego y veremos los cambios. En este ejemplo muestro la consola de Chrome con el texto “Hola” impreso.

helloworld3

Los botones tienen mucha flexibilidad para implementar lo que necesites de interfaces. Los utilizarás frecuentemente.

Cambiando textos

En cocos2d se manejan dos tipos de texto, los textos hechos con fuentes TrueType (cc.LabelTTF), y los textos hechos con fuentes bitmap (cc.LabelBMFont).

Las fuentes TrueType tienen la flexibilidad de cambiarles el tamaño, utilizar su versión Bold o itálica, pero dibujar fuentes TrueType es costoso en recursos de procesamiento (son curvas matemáticas que se deben convertir a imagen), amén de las problemas que podrían surgir de los requisitos de la licencia que emplee la fuente en cuestión (recuerda que algunas no permiten distribuirse libremente con el proyecto).

Las fuentes bitmap son imágenes con todas las letras de la fuente y un archivo que indica las coordenadas de cada letra. Se pueden fabricar a mano, o a partir de una fuente TrueType con un software. Como son imágenes como cualquier sprite, dibujarlas se hace muchísimo más rápido que su contraparte en TTF.

nombres_0

*Este es un ejemplo de una imagen que contiene una fuente bitmap*

Para generar las fuentes en bitmap puedes emplear el programa BMFont de AngelCode.com (disponible gratuitamente). El uso de este programa se sale del alcance de esta sección, así que para usar una fuente bitmap de ejemplo descarga la imagen de ejemplo anterior y este archivo. Colócalos en el directorio res/ de tu proyecto, y agrega ambos archivos al registro de recursos en resource.js.

//resource.js
//...
var s_nombresText = "res/nombres.txt";
var s_nombresImage = "res/nombres_0.png";
//...
    {type:"image", src:s_nombresImage},
    {type:"fnt", src:s_nombresText},
//...

En myApp.js ya tenemos un ejemplo de cómo crear un label con fuentes TrueType:

//myApp.js
this.helloLabel = cc.LabelTTF.create("Hello World", "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);

En la función create pasamos tres parámetros, el texto inicial, el nombre de la fuente, y el tamaño inicial. Posteriormente le colocamos una posición y lo agregamos a la capa principal de la escena.

Si posteriormente queremos cambiar el texto del label, empleamos la función setString sobre el label. Agreguemos este código después del bloque que acabamos de ver:

this.helloLabel.setString("Hola mundo!");

Al recargar el juego veremos el cambio del label.

Para finalizar esta sección, agreguemos un label con bitmapfont, después del bloque que agregamos, escribamos este código:

this.helloBMLabel = cc.LabelBMFont.create("Chao", s_nombresText);
this.helloBMLabel.setAnchorPoint(cc.p(0, 0.5));
this.helloBMLabel.setPosition(cc.p(30, size.height/2));
this.addChild(this.helloBMLabel);

Al recargar el juego veremos estos cambios:

helloworld4

Las fuentes bitmap no son tan flexibles como las fuentes TrueType. Al escalar este tipo de fuentes se verán distorsionadas, por lo que hay que crear bitmaps para cada tamaño de la fuente. Además, se deben incluir todos los caracteres que vayamos a emplear, incluyendo el espacio, o de otra manera el juego no correrá bien al no poder ubicar el caracter que necesita.

Finalizando todo

Acabamos de ver algunos tipos básicos de nodos, textos, imágenes y botones, y cómo se agregan al escenario. En la próxima parte de este tutorial veremos con más detalle cómo puede el jugador controlar el juego, y más adelante cómo se trabaja el cambio entre escenas.

Avatar de la mujer cortesía de NatashaHaggard en OpenGameArt - http://opengameart.org/content/female-avatar

Contenido del botón cortesía de Buch en OpenGameArt - http://opengameart.org/content/horrific-button

Escribiendo C++ para la Web, una presentación por Andre Weissflog

slide-1-638

Les recomiendo leer este interesantísimo conjunto de láminas que hablan sobre la posibilidad de poder escribir aplicaciones en C++ que corren en diversos navegadores. La idea de poder compilar a través de LLVM para llegar a usar Javascript u otra tecnología parece algo más experimental que otra cosa, pero ¿qué es la web si no se puede experimentar con tecnologías?

Menos charla, más juegos: un podcast por Saúl González y Robert Valerio. Episodio 1 con el Caracas Game Jam

menoscharlamasjuegosSaúl González (@esaulgd) y Robert Valerio (@valeriorobert) lanzaron el primer episodio de su podcast “Menos charla, más juegos”, producido en conjunto con la Universidad Simón Bolívar y Artevisión-USB.

Este primer episodio está dedicado al pasado Caracas Game Jam 2013, hecho en los Espacios ACCEDE en Macaracuay. Incluye entrevistas a varios de los participantes, y a Yole a y mí como organizadores del evento. Los invito a descargarlo y escucharlo ;-)

Fuck Videogames: una charla por Darius Kazemi

Las láminas de la charla de Darius tienes que verlas si sientes que estás sufriendo demasiado a la hora de hacer un videojuego. La charla está dirigida precisamente a ese tipo de gente. Si te sientes feliz haciendo juegos, y es lo tuyo, pues buenísimo.

Fuck Videogames, por Darius Kazemi.