Ciro Durán
Echo código. Hago videojuegos. Impulsando a los demás a que hagan videojuegos.
Profile
Summary
Experience
- Dec 2011 - PresentFounder / MecaludensVideogame development. Entertainment software consulting. Software development to support marketing campaigns. Virtual training software. Platforms: Flash, ActionScript, Python. Desktop and mobile.
- Sept 2009 - PresentTeacher / Universidad Católica Andres BelloTeaching two courses at UCAB: Elective course about videogame design and production, and Required course on Computer Graphics.
- Jan 2009 - PresentFounder & Organizer / Caracas Game JamCaracas Game Jam is a thrilling videogame event, where participants gather during a full weekend to make videogames from scratch beginning with a theme. The Caracas Game Jam is part of the Global Game Jam, where hundreds of cities join in one weekend to make games. You can look at the results at http://www.caracasgamejam.com and at http://www.globalgamejam.org In Global Game Jam 2013, I am the coordinator of the jams for Latin America and Caribbean, except Mexico and Brazil.
- Apr 2006 - PresentCo-Founder, Content Writer & Delivery Manager / Open EnglishOpen English is an educational company dedicated to create the best experience in teaching English for non-native speakers. Its flagship product is an interactive online english tutorial. I am a founding member of the development team that created Open English, focusing on the design and programming of the learning platform, a Rich Interaction Application developed in Adobe Flash. I coordinated of a programming team to execute high-impact software projects in key areas: students’ learning platform and teacher management. I directed, designed and developed a great part of the interactive content of the course using ActionScript 2. I created and developed the initial design, programming and maintenance of the learning platform, using Adobe Flex and Actionscript 3. This platform communicates with a Java backend and a streaming server in Flash Media Server and Red5. I also maintained the backend, written in Java, with the help of the Spring Framework, Hibernate and BlazeDS for communication with the frontend.
- Jan 2002 - PresentNetwork administrator / LDC - Laboratorio Docente de ComputaciónLDC is the Computer Lab for the Computer Engineering career in this college. One of the first UNIX laboratories in South America, it has nearly 800 users under Windows, Linux and Solaris platforms. It is in charge of administering services inside the network (namely, HTTP, DNS, mail, databases, home directories), three computer rooms and provide technical support for students and teachers. My responsibilities included: administering "mission critical" services such as e-mail, ORACLE database server, DNS and HTTP. Interviewing and training new and current employees. Training is based on research they do to learn to administer new services, and hands-on installation and usage of these services in a controlled environment.
- Jan 2005 - PresentProgrammer / EOS DigitalBuilding a contact form in PERL + CGI for a company's client site.
Education
-
2000 - 2006Universidad Simón BolívarB.S. in Computer Engineering
Additional Information
Posts
En esta segunda entrega de Menos charla, más juegos, Saúl y Robert entrevistan al equipo de La Cosa Entertainment, ganadores del concurso Square-Enix con su juego Klaus, para Android. Les recomiendo escucharlo para conocer más de ellos y su proceso de desarrollo.
Nvidia ha publicado en su cuenta de Github un manual sobre programación con el GPU llamado Modern GPU. Una suerte de librería, libro de algoritmos, tutorial y guía de mejores prácticas para el uso de CUDA, el framework para trabajar programación de propósito general con el GPU.
Recordemos que Nvidia ha publicado gratuitamente el contenido de su libro GPU Gems 1 para aprender la clase de cosas que se pueden hacer con buena programación para la tarjeta gráfica.
Del Caracas Game Jam 2013 les mandamos a todos ustedes un saludo:
Los esperamos el próximo Global Game Jam 2014, en enero.
En el blog de Zynga revelan que han logrado portear cocos2d-x para que use emscripten. Hace unos días había mencionado unas láminas que hablaban de la posibilidad de correr código escrito con C++ sobre Javascript. Emscripten es el puente que hace este enlace, y que ahora haya la posibilidad de utilizar una librería tan eficiente como cocos2d le da mucho valor a esta plataforma. Ojalá salgo interesante de todo esto.
Sírvanse de pasar por el blog de Julián para más detalles acerca de esta mesa de trabajo. La entrada es libre. La cita es el 24 de mayo en el Aula Magna de la UCAB Caracas.
Una de las herramientas más útiles que tengo a la hora de comunicar eventos que ocurren en una clase a otros sitios es el patrón de Observador, que en ActionScript 3 se manifiesta con el sólido sistema de eventos que forma parte de la librería básica de este lenguaje.
Lamentablemente, el sistema de eventos es prácticamente único dentro de AS3. Portear código basado en eventos a otras plataformas que no tengan esto incorporado no es sencillo. Así que una manera que he encontrado de trabajar más naturalmente ha sido los AS3 Signals, de Robert Penner, o su homólogo en Javascript, por Miller Medeiros. Basado en el sistema de Signals and Slots de la librería QT, se definen los signals como miembros públicos que se colocan dentro de un objeto. Otros objetos se suscriben a estas señales con una función de llamada de vuelta, que es llamada cuando la señal se emite. A estas funciones se les conoce como slots.
Esto es muy parecido a como funciona el sistema de eventos, pero a diferencia del de ActionScript 3, no requiere un sistema central que maneje los eventos. Cada señal mantiene registro de las funciones a las que debe llamar.
En C++ he conseguido que la implementación de signals con Boost, llamada signals2, es igualmente de útil y flexible que sus símiles en AS3 y JavaScript. Además de esto, la librería es thread-safe y se comporta bien con muchas plataformas, por lo que el código resultante es bastante porteable.
Boost es un compendio de librerías extremadamente grande, y que apenas estoy comenzando a explorar. El objetivo de este artículo es simplemente explorar lo que se puede hacer con signals2 para facilitar la comunicación entre clases. No está de más decir que necesitas comprender medianamente bien C++ para entender el tutorial.
Presentemos el caso
Supongamos que tenemos un juego en el que un personaje se mueve constantemente de un punto a otro en línea recta. El juego debe reaccionar cuando el personaje llega a su destino. Dicho esto, implementaremos este comportamiento en una clase separada de la clase encargada de dibujar la pantalla.
Nuestro juego hipotético interpola linealmente la posición de un personaje de un punto a otro
En código podemos bocetear esto:
//Character.h
class Character {
public:
Character();
void update();
float position;
}
//Character.cpp
Character::Character()
: position(0.0f) { }
void Character::update() {
if (position
La clase principal del juego contiene el loop principal del juego, el cual ejecuta la función Character::update() para mover al personaje. El objetivo es que debemos ejecutar una función una vez que el personaje llegue al valor 1.0f de la posición. Notemos que la función no va a pertenecer a la clase Game (todavía). Un boceto de código sería algo como:
//Game.h
void playerLlegoAlFinal();
class Game {
public:
Game();
void update();
Character *player;
}
//Game.cpp
Game::Game() {
player = new Character();
}
void Game::update() {
player->update();
}
void playerLlegoAlFinal() {
//Función para llamar cuando el jugador llegue a la posición final
}
Vemos ahora que el problema es cuándo saber que el personaje llegó a la posición final. Podríamos comprobarlo con un if dentro del update, pero vemos que la posición es un float, ¿qué valor deberíamos comprobar para llamar a la función?, en la clase cuando Character llega al valor 1.0f reiniciar el valor. Podríamos también crear en Character un miembro que sea un apuntador a una función, de tal manera que Character la pueda llamar una vez que la posición sea 1.0f. Pero, ¿qué tal si pudiésemos llamar a una o más funciones cuando ocurra esto?
Entran las signals
Las signals son unas estructuras en Boost que agrego a una clase "A", generalmente de manera pública. Las clases que necesiten que se llame a una función desde esa clase "A" agregan esa función al signal. Estas funciones pasan a llamarse slots. Cuando la clase "A" despacha la señal, esta estructura en consecuencia llama a todos los slots que se han agregado hasta el momento.
Notemos que esto se parece al sistema de eventos de ActionScript 3, pero la diferencia radica en que las funciones que agrego a las señales están fuertemente tipadas. Las funciones que se agregan deben tener la firma que se declara junto a la señal.
Boost trae dos implementaciones de signals and slots, signals y signals2. La primera necesita hacer un trabajo de compilación previo a su utilización, mientras que la segunda emplea únicamente los headers que se incluyen en nuestro proyecto, además de que la segunda implementación es thread-safe.
Agreguemos una señal a nuestra clase Character:
//Character.h
#include
class Character {
public:
Character();
void update();
float position;
boost::signals2::signalcharacterLlegoAlFinal;
}
//Character.cpp
Character::Character()
: position(0.0f) { }
void Character::update() {
if (position
La señal se declara en el header de la clase, detallando también el tipo de funciones que acepta la señal. Para despachar la señal llamamos a la señal como una función cualquiera. En este ejemplo inicial llamaremos a funciones que no aceptan ningún parámetro. Veamos ahora cómo agregar una función desde Game.cpp.
//Game.cpp
Game::Game() {
player = new Character();
player->characterLlegoAlFinal.add(playerLlegoAlFinal);
}
Ahora cada vez que el personaje llegue a la posición 1.0f, se despachará la señal y en consecuencia se llamará a la función playerLLegoAlFinal(). Podría agregar otra función más tarde, y esta función se llamaría después de la primera.
Este es un caso suficientemente simple, casos en los que tengamos que llamar a funciones que no pertenecen a ninguna clase. Pero en la realidad solemos tener que pasar funciones miembro de una clase. Acá nos enfrentamos a otro problema. En lenguajes de alto nivel, las funciones son ciudadanos de primera clase, por lo que yo podría pasar directamente el nombre de la función, haciendo algo como "player.characterLLegoAlFinal.add(this.playerLLegoAlFinal)". Pero esto es C++, donde las funciones en realidad son direcciones en memoria que debo asociar a la dirección de un objeto.
Boost nos ofrece "bind", una herramienta muy poderosa que resuelve fácilmente este problema. A bind le pasamos la dirección del objeto, la dirección de la función, y nos devuelve un apuntador que asocia ambos datos. Cuando la señal se despacha, la función sabrá a que objeto se está refiriendo.
Veamos de nuevo el ejemplo anterior, pero la función playerLlegoAlFinal() será ahora un miembro de Game:
//Game.h
class Game {
public:
Game();
void update();
void playerLlegoAlFinal();
Character *player;
}
//Game.cpp
Game::Game() {
player = new Character();
player->characterLlegoAlFinal.add(boost::bind(&Game::playerLlegoAlFinal, this));
}
void Game::update() {
player->update();
}
void Game::playerLlegoAlFinal() {
//Función para llamar cuando el jugador llegue a la posición final
}
Ahora cuando la señal despache characterLlegoAlFinal, se llamará a la función playerLlegoAlFinal correspondiente a Game.
Agregando parámetros
¿Qué pasa si tenemos que pasar más datos con esa señal? Imaginemos ahora que el personaje cuenta las veces que ha llegado al final, y que eso es un parámetro que le pasaremos a los slots que llamemos. Veamos la nueva clase Character:
//Character.h
#include
class Character {
public:
Character();
void update();
float position;
int vecesLlegadas;
boost::signals2::signalcharacterLlegoAlFinal;
}
//Character.cpp
Character::Character()
: position(0.0f)
, vecesLlegadas(0) { }
void Character::update() {
if (position
Ahora que hemos cambiado la firma de los slots de la señal, tenemos que cambiar la función en Game a void playerLLegoAlFinal(int veces). Pero ¿cómo hacemos con la función que le vamos a pasar a bind? A bind hay que especificarle que la función que le estamos pasando tiene un parámetro que no se conocerá hasta que la señal sea despachada. Veremos que bind tiene una característica que la hace extremadamente útil en otros casos distintos a emplear la función como slot. Veamos qué debemos hacer en nuestra clase Game:
//Game.h
class Game {
public:
Game();
void update();
void playerLlegoAlFinal(int veces);
Character *player;
}
//Game.cpp
Game::Game() {
player = new Character();
player->characterLlegoAlFinal.add(boost::bind(&Game::playerLlegoAlFinal, this, _1));
}
void Game::update() {
player->update();
}
void Game::playerLlegoAlFinal(int veces) {
//Función para llamar cuando el jugador llegue a la posición final
}
Los nombres _1, _2, _3, _4... hasta el _9 son marcadores de posición (placeholders), indican que la nueva función que estamos creando en este caso se le pasará el parámetro del número correspondiente en la posición del argumento de bind. Es decir, en este ejemplo estamos creando una función con bind que tiene asociados la dirección del objeto, la dirección de la función, y que acepta un solo argumento. Este argumento es de tipo el primer argumento de la función que estamos pasando, es decir, int veces.
Con esto vemos que con signals2 y bind podemos crear señales que comunican datos entre clases elegantemente. Pero antes de cerrar este tutorial exploremos un poco más bind, y veamos lo que es capaz de hacer.
Explorando bind
Vemos que la función bind es capaz de pasar parámetros placeholder, pero bind no nos limita a esto. Supongamos que tenemos una función de dos parámetros que ahora queremos agregar como slot a la señal de Character.
void Game::playerLLegoAlFinalYEstaFeliz(int veces, bool estaFeliz);
La señal sigue siendo la misma, characterLlegoAlFinal, que llama a slots que aceptan un solo parámetro. Haremos entonces que se llame a esta señal, asumiendo que el player llega siempre feliz. Agreguemos la función con bind:
//Game.cpp
Game::Game() {
player = new Character();
player->characterLlegoAlFinal.add(boost::bind(&Game::playerLlegoAlFinal, this, _1));
player->characterLlegoAlFinal.add(boost::bind(&Game::playerLlegoAlFinalYEstaFeliz, this, _1, true));
}
Para fines de la señal, este segundo slot acepta un solo parámetro. La función playerLLegoAlFinalYEstaFeliz será llamada con el número de veces indicada por la señal despachada, y el segundo parámetro siempre con true. Con bind podríamos incluso cambiar de posición los parámetros, y muchas otras cosas más. Boost ofrece un montón de funcionalidades que serían propias de lenguajes de alto nivel, con la eficiencia de C++. Quedan muchísimas más por conocer.
Sony ha abierto un período para que los desarrolladores que quieran explorar el SDK del PlayStation Mobile lo puedan hacer gratuitamente, del 8 de mayo hasta (tentativamente) el 2 de septiembre. Para registrarse, deben darse de alta en https://psm.playstation.net/, y una vez que ingresan pueden descargar el SDK.
La idea de Sony es atraer a desarrolladores al mejor estilo AppStore o Google Play para que puedan hacer aplicaciones y probarlas directamente en los dispositivos de prueba. Al estilo Apple, debes pagar una cuota anual para probar las aplicaciones, y poderlas distribuir en la PlayStation Store, de ahí el “gratuito”. Pero no es mala idea poderse descargar el SDK y ver qué capacidades tiene.
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.
Comenzando un proyecto
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.
¿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:
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:
Observa que este sprite, que tiene de tamaño 42×40, 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:
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.
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.
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:
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
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?
Updates
-
Se queja de interoperabilidad entre mensajerías instantáneas. No implementa XMPP para Hangouts #douchebagGoogle http://t.co/Ay8MpOgzyB4 minutes ago from web | Reply, Retweet, Favorite
-
@Lavi_inita suerte y gaceta hípica14 minutes ago from web | Reply, Retweet, Favorite
-
@esaulgd una excelente conversación ;-)7 hours ago from web | Reply, Retweet, Favorite
-
Ustedes están locos si una grabación como la de hoy los impulsa a ver La Hojilla #niconeso7 hours ago from web | Reply, Retweet, Favorite
-
RT @RoccoPirillo: Refresca tu iPod con mis recomendaciones musicales de mayo http://t.co/EdhIlR9Szq #PelirrojoMutante7 hours ago from web | Reply, Retweet, Favorite
-
Mañana Mario Silva va a almorzar solo en la cafetería.8 hours ago from web | Reply, Retweet, Favorite
-
8 hours ago from web | Reply, Retweet, Favorite
-
RT @Naky: La purga de Caracas. El Hangout de esta noche http://t.co/eO0V5bW6NR8 hours ago from web | Reply, Retweet, Favorite
-
@LuisCarlos @gliendo sujto9 hours ago from web | Reply, Retweet, Favorite
-
Segundo episodio de Menos charla, más juegos, con el equipo de Klaus, @LaCosaEnt - http://t.co/t8NkdakdZ7
-
RT @Sosowski: This is a novel written by a simple (~30 lines) code: http://t.co/NfkJoO0JDV This is being made by humans: http://t.co/wa5aUE…9 hours ago from web | Reply, Retweet, Favorite
-
Disasterpiece es un genio musical - http://t.co/Geh6rlI8f29 hours ago from web | Reply, Retweet, Favorite
-
9 hours ago from web | Reply, Retweet, Favorite
-
9 hours ago from web | Reply, Retweet, Favorite
-
Modern GPU: Nvidia ha publicado en su cuenta de Github un manual sobre programación con el GPU llamado Modern G... http://t.co/g7vY96C83G
-
Pronto el PSUV caminará en dos patas y se relacionará con AD y COPEI10 hours ago from web | Reply, Retweet, Favorite
-
RT @ayshiamo: Es increíble cómo una docena de personas nos dice lo mismo y no prestamos atención hasta que *una* lo comunica diferente y en…10 hours ago from web | Reply, Retweet, Favorite
-
@LatinCosmicGirl no, no es fácil.10 hours ago from web | Reply, Retweet, Favorite
-
¿Cuándo hacen la changa de Mario Silva?11 hours ago from web | Reply, Retweet, Favorite
-
RT @odcastro: Hoy renunció el último PhD que pudo contratar el Dp de Electrónica de la USB en 10 años. No duró ni 3. Empezó la renuncia mas…11 hours ago from web | Reply, Retweet, Favorite
Posts
Art&Animation by Todd Lockwood
http://www.tolo.bizIt literally just occurred to me watching this that the head tracking thing birds do keeps their heads from bobbling around while they fly.
I could watch this forever @ o@
MODERN GAMES AS ATARI CARTRIDGES (Part 1)
Shortly after posting this first batch of modern games with an 8bit twist back in July the deviantART account that created them was deactivated and it seemed our days of modern/Atari art were over.
Now all that’s changed because the artist has created a new deviantART account and has uploaded a tonof new cartridges that they’ve designed. My favorite is the Fallout 3 one. That dog in the capsule has no idea what kind of trouble it’s in.
Visit StarRoivas on deviantART to see their complete collection of Atari art.
Twitter: The Comic is a collection of comics based on the greatest tweets of our generation. The source material is used verbatim, typos and all. Despite the seemingly random nature of the tweets, the comic has reoccurring characters and story arcs that aren’t fully understood unless experienced through a single reading. With explicit permission from the writers of each comic, Twitter: The Comic could be a pretty rad book.
@ChrisDoveton @colourmesam
These are so good! So good!
My father, Dave Robert Shepard Sr., died on either December 30th or December 31st, depending on what time zone you were in. I received the call on the 30th at 11:30PM in Los Angeles, but the caller, positioned in Detroit, was two hours deep into the 31st. He was dead at 62 years old. Small cell…
Lloré.
“You’re desperate, aren’t you?”
I have to admit I’m always a stranger to the debate about writing/creating convincing female characters in media. I do understand the point of the over sexualisation/objectification (by golly, those are big words) treatement women get in media (which is mostly par for the course considering all media is run and aimed to men who never got over puberty).
But what I don’t get is this fervorous debate on how to write women “properly” or “accurate”. It’s quite simple, just write them as people, as a human being, write them as you’d write any other character. Yeah, there’s emotional and fisical things that vary between men and women (more or less) that you might wanna keep in consideration, but we all part from the same basis. A personallity is not dependant on whether you’re a man or a woman. Wanna write a good character? Just write an individual, and everything will start flowing from there. Use logic, step into the shoes of the situation and figure out the bast way things should go according to your idea, and you can place any character in that role, male or female, it’ll sill be convincing.
Unless you are one of the previously mentioned marketing douchebags who want to keep that particular ball rolling because it “sells”, in that case, hurl yourself off a bridge.
Hear hear
An introspective journey of artistic self discovery, presented as a 6 page comic.
oh my god
this is the best thing ever
Reaction image goldmine.
This post deserves a thumbs-up.
- non-english speaker: I am awfully sorry at the terrible state of my English abilities, as for the English language is not my mother tongue. I hope you forgive me for every foolish mistake I make.
- english as first language: lol it okei
There’s people who draw women like a hungry man drawing food.
Audio
-
Peanut Vendor (El Manisero), original de Moises Simons, reinterpretado por Club Des Belugas.0 plays
-
delvivero: Masseratti 2lts - Di_Amantes_Brillantes (Featuring Nana Cadavieco)66 plays
-
Kokiriko Bushi (FAMI-MODE 2012), por Nubuwo, del FAMI-Pack (su Bandcamp)1 plays
-
La Salchicha, jingle original de la empresa Oscar Mayer, pasada por el filtro de Aldemaro Romero y su Onda Nueva.13 plays
-
El Negro José, por Aldemaro Romero.102 plays
-
Battle City (DJ Lexx Edition), por Stanley Guy. Link de descarga.0 plays
-
Tema principal de HeliTaxi, de su banda sonora.9 plays
-
Adios adios, por Popy.1 plays
-
Corazón Contento, por Palito Ortega2749 plays
-
Rompe Saraguey, compuesto por Virgilio González Solar, interpretado por El Arca.33 plays
-
music-expressions: Garbage - Stupid Girl71 plays
-
Ayer el vagón del Metro en el que me fui tenía este volumen de la música. Grabé con el celular en mis piernas sentado cerca de una corneta.134 plays
-
Péndulo, por Sentimiento Muerto, del disco Infecto de Afecto.0 plays
-
karlarious: benj4: arualiaa: pablets: Mi cara ha sido la de las imágenes. ya habia puesto el video, pero asi le da mucho mas misticismo :O Escuchareis y tripeareis!!! DALE VATIO YOFREN!937775 plays
-
Adele vs. Daft Punk - Something About the Fire, mezclado por Carlos Serrano. En SoundCloud.30 plays
-
notangenerico: logoside: Dale al play y mira el gif. No te arrepentirás. xD Para esto se inventó el internet.1043063 plays
-
Zorra, por Dermis Tatú.0 plays
-
Cambiar de Look, un cover de She’s Got the Look de Roxette, por Tropikal Forever.24 plays
-
fuckyeahbandasve: La Muy Bestia Pop - Dios Es Máquina0 plays
-
Economica, por Jim Guthrie, el mismo compositor de Sword&Sworcery y el documental Indie Game: The Movie. Su BandCamp.0 plays
Posts
¡Feliz año 2013 para todos!
“Es nuevamente esa época del año”, dicen los correos de tu registrador de dominios. En este caso, es nuevamente la ocasión de escoger tu videojuego gratiñán favorito de todo 2012.
Esta vez escogerás el juego o los juegos que más te gustaron (por si no te puedes decidir por el mejor). Las votaciones las cerraremos al finalizar el 18 de enero de 2013.
Si quieres volverlos a jugar todos, o si no estás seguro de cuál juego quieres escoger, después de la encuesta está el listado completo de los juegos de 2012 junto con un enlace para visitar el post correspondiente.
- Rubble Trouble Moscow (05-ene)
- Abobo’s Big Adventure (13-ene)
- Battle Block Defense (4-feb)
- Los juegos de navegador del Caracas Game Jam 2012
(10-feb) - Triple Town (/)
- Kissma (16-feb)
- Legend of the void (24-feb)
- Hambo 2 (2-mar)
- Super Pig (9-mar)
- This is the only level 3 (16-mar)
- MoneySeize (23-mar)
- Die in a Carpet Fire (15-jun)
- The Last Element (22-jun)
- Hot Air Jr. (29-jun)
- Simple Motions 2 (6-jul)
- Slender (13-jul)
- J-J-Jump (20-jul)
- RectRot (10-ago)
- light-Bot (17-ago)
- Will The Game (24-ago)
- Tiny Evolution Adventure (31-ago)
- Calamari (6-sep)
- Tiny Game (14-sep)
- Building Houses (21-sep)
- Hexagon (28-sep)
- Teenage Mutant Ninja Turtles: Ninja Turtle Tactics 3D (5-oct)
- Z-Rox (12-oct)
- Block Runner (19-oct)
- Flightless (26-oct)
- Frog Fractions (2-nov)
- Incredipede (9-nov)
- Apocalipseed (16-nov)
- Nación Motorizada (23-nov)
- Prison Bus Driver (30-nov)
- Old Spice Saves The World (7-dic)
- Skrillex Quest (14-dic)
- Missile Command (20-dic)
- Command and Conquer (HTML5) (28-dic)
Esta semana les dejo una reimplementación de Command and Conquer en HTML5 hecha por un desarrollador que posteriormente escribió un libro sobre esta tecnología (Pro HTML5 Games). Así que es un chance de volver a jugar un famoso RTS por el placer de hacerlo ;-) .
¿Quién dijo fin de mundo? Missile Command es el clásico de Atari en el que con tres estaciones de ataque (con misiles limitados), debemos defender a seis ciudades del ataque inminente al que están siendo sometidos. Compartan su puntaje si aún quedamos vivos :-) .
Skrillex Quest es un advergame hecho por Jason Oda (o JODA Design) para promocionar la música de Skrillex. En este juego estaremos controlando a un personaje de un título de RPG genérico, el cual le ha caído una mota de polvo, comenzando a generar toda clase de errores al mejor estilo Nintendo 8-bits. Excelente homenaje a los cartuchos de NES, y una buena mezcla de la música de Skrillex (que le queda al juego, debo decir).
La marca Old Spice de desodorantes, que ha estado dando qué hablar con sus curiosas campañas publicitarias, da clases de cómo hacer marketing con su videojuego “Old Spice Saves The World“, el cual protagoniza Dikembe Mutombo y se describe a sí mismo como “un videojuego hecho para parar un evento real que pudiese ocurrir si una civilización antigua era tan inteligente como pensamos”. El juego tiene demasiadas cosas extrañas para ser descritas aquí. Así que por favor, pasa adelante y juégalo.
Prison Bus Driver es un juego de arcade físico, en el que manejamos un autobús de prisioneros. En una primera etapa debemos manejarlo de la estación de policía a la prisión, y luego de vuelta con la carga de prisioneros. Es bueno hacer un recorrido irregular para que los prisioneros se mantengan calmados y tu trabajo sea más sencillo. Pero volteas el autobús y pierdes.
¡HOY y este fin de semana!
Gamexpo 2012 es la 3ra convención de videojuegos de Venezuela, y en esta edición regresa con las actividades que han marcado al evento:
- Torneos de PlayStation 3, Xbox 360 y Wii. Revisa los títulos y los horarios en la página. Todos los torneos tienen premios al primer, segundo y tercer lugar, cortesía de nuestros patrocinadores.
- Museo de los videojuegos, donde estarán destacados y categorizados los últimos 30 años de historia de las consolas.
- Conciertos donde habrán bandas tocando covers de temas famosos de videojuegos, contando esta vez con la presencia de La Vesper, O Rock y Los No Name. También habrás DJs tocando con sus instrumentos, ui, Monte y Culebra, y Radiosphere.
- Zona Wi-Fi para que los dueños de consolas portátiles puedan jugar y compartir. Esta zona también contará con sus propios torneos, revisa los títulos en la página. El evento cuenta con internet inalámbrico en todos sus espacios.
- Concurso de Cosplay especializado en videojuegos, organizado por la comunidad de Dangeru.net.
- Galería de arte, en el que destacados artistas han brindado su creatividad para elaborar piezas basadas en videojuegos. Una colección de mucho valor curada por Manuel Herrera y Daniel Garrido.
- Jornadas académicas, donde lo mejor del desarrollo de videojuegos estará compartiendo sus conocimientos. El horario y los resúmenes biográficos de los ponentes está disponible en la página.
Así que los invito cordialmente al Centro Comercial City Market, el viernes 30 de noviembre, sábado 1ro y domingo 2 de diciembre a este gran evento.
La entrada general de un solo día es de 100BsF, y la entrada VIP para los tres días es de 260BsF.
Nación motorizada es un prototipo que hice hace algún tiempo (un año), pero que no había publicado por varias razones. Debido a un suceso que me ocurrió esta semana tuve la necesidad de pulirlo un poco y publicarlo. El juego ha pegado en algunas personas, y hasta ha tenido una reseña en Últimas Noticias.
Asi que jueguen Nación motorizada en mi página.
Apocalipseed es un juego de estrategia en tiempo real, en el que controlas a un invasor extraterrestre con forma de planta y que se alimenta de carne humana. A medida que vas obteniendo más carne, podrás ir formando un ejército para acelerar tus planes. Importante: Deben arrastrar desde la planta hasta el punto donde se van a comer a la persona.
Incredipede es un juego de puzzles físicos, en el que controlas a un personaje llamado Quozzle, el cual maneja una serie de piernas controladas por músculos. El juego incluye un sistema para modificar el cuerpo del personaje en algunos niveles para poder pasarlos. El enlace de este post es para una demo del juego, ya que Colin Northway, su creador, está apuntando a que sea incluído en la tienda de Steam a través de Greenlight.
Frog Fractions es el mejor juego educativo que podrás jugar nunca jamás. Ideal para bebés, niños, adolescentes, adultos, viejos y no-muertos. Con este juego conocerás sobre fracciones y mucho más. Tan solo mantente jugando durante los primeros 3 o 4 niveles para que sepas de lo que hablo. Deja en los comentarios si llegaste al final :-D
Flightless es un juego demostración de Nitrome, quienes están buscando introducir el juego a Steam, la plataforma de distribución de PC de Valve. En Flightless manejamos a un pájaro incapaz de volar pero con ambiciones de recoger diamantes. El mecanismo que dispone entonces nuestro personaje es una escalera que sube a partir de él y llega hasta el techo de donde esté. Esta escalera también puede ser usada como arma.
Block Runner es otro juego más de correr y saltar obstáculos, con la variante de que algunos edificios se pueden destruir a tu paso. ¡A correr!
Teenage Mutant Ninja Turtles: Ninja Turtle Tactics 3D es uno de los juegos sobre esta serie de los ochentas que Nickelodeon ofrece en su página. En este juego debemos escoger entre las 4 conocidas tortugas: Leonardo, Rafael, Michelangelo o Donatello, y pasar de nivel en nivel enfrentándose entre todos para entrenar.
Hexagon es un juego hecho por Terry Cavanagh, un desarrollador independiente irlandés viviendo en Inglaterra. No voy a describirles cómo se juega Hexagon, pero sí les diré que es increíblemente difícil, así que disfruten :-). Terry sacó una versión de este juego para el Apple AppStore y se llama Super Hexagon. Así se juega aún mejor.
Mi record es de 26 segundos, por cierto.
Building Houseses un juego que creía que se había perdido cuando la página que originalmente lo hospedaba cerró hace algún tiempo. Requiere tener instalado Java en el navegador, pues es un Applet. Más que un juego, es un puzzle en el que debemos reconstruir una figura en 3 dimensiones a partir de sus proyecciones ortogonales en 2 dimensiones, con el mínimo de cubos que indica el juego. Para agregar cubos hacemos click en la cara sobre la que queremos poner el bloque, con click derecho eliminamos el cubo correspondiente. Pista: los cubos pueden flotar alegremente sobre el espacio. ¿Podrás completar todas las figuras? Déjalo en los comentarios.
Tiny Game es un pequeño juego para satisfacer esa necesidad compulsiva de colectar todos los puntos de un mapa con forma de laberinto :-P . Un juego rápido para el fin de semana.
Calamari está ahorita en el tope de juegos de Nitrome, uno de mis desarrolladores preferidos :-) . En Calamari el objetivo es sobrevivir la mayor cantidad de tiempo en una habitación cerrada. Calamari debe saltar a los bloques que van flotando, recoger monedas para puntaje. Algunos bloques se pueden destruir disparándoles, pero las balas que utilices debes recogerlas para usarlas nuevamente.
