22 de junio de 2009

Chris DeLeon es un desarrollador independiente e instructor con bastante experiencia. En los últimos tres meses ha publicado 3 entregas de su newsletter llamado GameDevLessons: una serie de tips orientados a todos los niveles: desarrolladores básicos, intermedios y avanzados. Esta es la entrega de abril, mayo y junio. Cada entrega toca temas muy variados, y sirve para material de conversación. Si te interesa recibir este newsletter en tu correo suscríbete.
UPDATE: La primera carta fue traducida al español, además de la bio de Chris.
18 de junio de 2009

En el artículo anterior estuvimos revisando la carga de imágenes externas a nuestra aplicación. Este método es útil y fácil para cargar estos recursos, pero en algunos casos es necesario tener a mano los recursos inmediatamente disponibles. Para ello se hace necesario incluir estas imágenes y recursos adentro del SWF compilado para agilizar el acceso a ellos. En este artículo aprenderemos cómo se hace embed, embedding o embebido de estos recursos. (Foto por storker)
En particular vamos a incluir imágenes vectoriales en formato SWF, e imágenes bitmap como JPGs, GIFs (no animados) o PNGs. También podemos incluir sonidos en formato MP3. Es posible incluir GIFs animados dentro del juego, pero se requiere de una librería externa, y requiere cierto conocimiento. Esta técnica se tratará al finalizar este artículo.
Embed, embeber, incluir
Para incluir un recurso dentro del código utilizaremos las anotaciones del compilador de Flex. Las anotaciones son líneas especiales de código que no es ActionScript 3 propiamente. Estas líneas son leídas por el compilador de Flex para indicar propiedades especiales de la variable que modifica a continuación.
Cuando embebemos un recurso en el código, ese recurso va a tener un tipo específico que solamente es reconocido cuando utilizamos la librería completa de Flex. Nosotros no queremos incluir toda la librería Flex porque representaría una sobrecarga de código que no vamos a utilizar. Afortunadamente, tanto los bitmaps como los dibujos vectoriales heredan de una clase que sí podemos utilizar: DisplayObject.
Los recursos que utilizaremos son los mismos del anterior artículo: la imagen del gato (cortesía de PDX Sasquatch), la ilustración vectorial de la computadora y el sonido del trueno (cortesía del proyecto RHumphries).
Cómo nos organizamos
Al igual que la vez pasada, crearemos un proyecto en FlashDevelop para Actionscript 3, pero los 3 recursos los colocaremos en la carpeta de fuente src/.
Incluyendo un bitmap
Este es el código que utilizaremos para embeber una imagen. La explicación después del bloque de código:
package {
import flash.display.MovieClip;
import flash.display.DisplayObject;
import flash.events.Event;
public class HolaMundo extends MovieClip {
[Embed(source="kitten.jpg")]
public var imagenClass:Class;
public function HolaMundo() {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
public function init(e:Event = null) : void {
removeEventListener(Event.ADDED_TO_STAGE, init);
var imagen : DisplayObject = new imagenClass();
addChild(imagen);
}
}
}
La película resultante será totalmente similar a la de cargar una imagen. La diferencia está en que si vemos el tamaño en bytes del SWF ha crecido un poco hasta 17Kb. La imagen ahora está adentro del SWF, por lo que no hace falta cargarla de Internet, sino que al terminar de cargar el SWF la imagen estará disponible inmediatamente. La imagen ahora es una clase que instanciamos como DisplayObject y agregamos dentro de la película, por eso el embed va directamente encima de una variable de tipo Class, y usamos el nombre de la variable para instanciar la clase.
Así es como funciona el Embed: la etiqueta de metadatos encima de la variable imagenClass convierte esa variable en una referencia a la clase que representa la imagen. Así que para usar la imagen tenemos que crear un objeto del tipo que apunta la variable, y luego la agregamos al stage. Probablemente si hyas usado otro lenguaje esto te parezca extraño, pero así funciona.

Incluyendo un dibujo vectorial
A diferencia de la carga desde Internet, uno no embebe el SWF completo, sino que embebe un símbolo del SWF. Para asignar nombres a las películas en Flash es tan sencillo como hacer que las ilustraciones sean MovieClips y asignarles un nombre dentro de las propiedades. También podemos incluir un SWF, para lo cual requeriremos el nombre del símbolo, además de la ubicación del SWF. Como verán, el SWF puede ser exportado por Flash, o por cualquier otro programa que exporte a SWF (como Illustrator, por ejemplo). El método es el mismo que la imagen:
package {
import flash.display.MovieClip;
import flash.display.DisplayObject;
import flash.events.Event;
public class HolaMundo extends MovieClip {
[Embed(source="computer.swf", )]
public var imagenClass:Class;
public function HolaMundo() {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
public function init(e:Event = null) : void {
removeEventListener(Event.ADDED_TO_STAGE, init);
var imagen : DisplayObject = new imagenClass();
addChild(imagen);
}
}
}
Incluyendo un sonido
Para incluir un sonido utilizaremos un código similar. Haremos el embed encima de una variable de tipo Class, y luego utilizaremos esa variable para instanciar el sonido de ese tipo, convirtiéndolo a Sound.
package {
import flash.display.Sprite;
import flash.media.Sound;
import flash.media.SoundChannel;
public class HolaMundo extends MovieClip {
[Embed(source="thunder.mp3")]
public var soundClass:Class;
public function HolaMundo() {
var thunder:Sound = new soundClass() as Sound;
thunder.play();
}
}
}
Incluyendo un GIF animado en Actionscript 3
Por defecto la clase Loader no reproduce GIFs animados. Si uno pone un GIF animado en el Loader, la clase solamente muestra el primer fotograma. Sin embargo, gracias a los buenos oficios de Thibault Imbert tenemos la librería AS3 GIF Player Class, disponible en http://www.bytearray.org/?p=95.
Esta librería lee el formato de un GIF animado y lo reconstruye fielmente dentro de una película SWF. Es capaz de leer un URLRequest, para cargarlo externamente como en el artículo anterior, o cargar un ByteArray, que no es más que un objeto que tiene el contenido de cualquier archivo binario.
Para instalar la librería se descarga la versión más reciente, a la fecha la versión 0.4, y se copia el directorio org al directorio de fuentes de nuestro proyecto (src/). Para este ejemplo utilizaremos el GIF animado que trae esta versión, el archivo diego.gif.
Si queremos embeber un GIF animado en el código tendremos que hacerlo a pie: tendremos que embeber el archivo asignándole un MIME type de “octet-stream” de tal manera de forzar que su tipo sea un ByteArray; si no se especifica esto, el compilador hará que la clase sea un DisplayObject, dando error a la hora de instanciar. Luego haremos una instancia de ese embed y con el GIF Player cargaremos los bytes correspondientes. Notemos que el GIFPlayer es un DisplayObject, así que lo agregaremos de la misma manera que hemos hecho con todos los elementos gráficos anteriores.
package {
import org.gif.player.GIFPlayer;
public class HolaMundo extends MovieClip {
[Embed(source="mygif.gif", mimeType="application/octet-stream")]
private var gifStream:Class;
public function HolaMundo() {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
public function init(e:Event = null) : void {
removeEventListener(Event.ADDED_TO_STAGE, init);
var gif:ByteArray = new gifStream() as ByteArray;
var gifPlayer:GIFPlayer = new GIFPlayer();
gifPlayer.loadBytes(gif);
addChild(gifPlayer);
}
}
}
¡El código resultante es muy grande!
El problema de embeber muchos recursos gráficos es que todos ellos serán anexados dentro del SWF final, por lo que no serían posible mostrar algo mientras se carga toda la película. Para evitar ello podemos mantener el código en un SWF y mandar todos los recursos a otro SWF. De esta manera, cargamos el primero (que suele ser más pequeño y por ende carga rápidamente), y a partir del primero cargamos el segundo.
Esto es una técnica avanzada que aprenderás en el siguiente artículo. Hasta entonces.
9 de junio de 2009

Andres Cavallin vuelve al frente de la computadora para dar un webcast sobre Shaders en XNA, este jueves 11 de junio a las 3:30PM hora de Venezuela (GMT-04:30). Aunque la documentación y tutoriales para shaders es relativamente avanzada y requiere soltura con C# y XNA, Andrés trabajó el material para hacerlo accesible. Eso sí, sigue siendo preferible que ya hayas hecho algo en C# para poder sacar lo mejor de la charla. El material está basado en el libro Shaders for Game Programmers and Artists (Sebastien St-Laurent, 2004) y XNA Game Programming Recipes: A Problem-Solution Approach (Riemer Grootjans). La descripción del evento a continuación: (Screenshot cortesía de Spatial Horizons)
En este WebCast estudiaremos el uso de Shaders en HLSL desde XNA, lo que nos permitirá entender cómo aprovechar al máximo el poder de la GPU, creando un océano con olas y reflexión del cielo. Es necesario tener conocimientos báscicos de C# y Trigonometría, pero no es necesario tener conocimientos previos de Shaders ni de XNA.
Para ingresar, tienes que entrar al sitio de Microsoft Events correspondiente al evento, registrarse e instalar previamente el software Microsoft Office Live Meeting, que es gratuito.
Por otro lado, el primer webcast de Andres, una introducción a XNA, está disponible en láminas en la sección de archivos de INVENTAD, y la grabación del evento en la página de MSDN. Una vez hayas ingresado con tu Live ID, haz click sobre registrar y adentro tendrás las instrucciones para descargar la grabación.
8 de junio de 2009
Después de 5 semanas, ayer cerró la primera competición de videojuegos y tenemos resultados :-) . A continuación una pequeña descripción de los juegos entregados y el enlace en el título al thread correspondiente en el foro.
El tema escogido para esta primera competición fueron las arepas. El objetivo era poner a prueba la creatividad de los participantes utilizando un elemento conocido por todos y que al mismo tiempo no se hubiese tocado mucho en un videojuego.

Arepa Defense: por antikhaoz. Lamentablemente un proyecto que no alcanzó ser interactivo. El objetivo era prevenir el avance de hordas de enemigos a la base. Puedes ver el progreso de este juego en este enlace: http://www.ldc.usb.ve/~02-34826.
Arepero: por max y nCor. Este juego tiene un montón de acciones. Hay que prender la moledora de maíz, para luego apuntarla hacia el bol, para luego mezclar la harina con los otros ingrediente y finalmente se redondea la masa. El juego se puede jugar por aquí, aunque las instrucciones más detalladas están dentro del thread.
El Comearepa: por edmundito. Un juego un tanto más abstracto que el resto, en el que hay que apuntar una arepa que se deshace en trozos a la boca de la persona. Las instrucciones y el juego en esta dirección.
AutoArepa: por chiguire. En este juego, inspirado en un mini-juego de Space Quest IV, hay que armar unas arepas que pasean por una banda tal como lo piden las recetas. Al final de la banda hay un detector que dice si la arepa está bien hecha o no. Las instrucciones en el thread, y el juego está en esta dirección.
Así que allí están los resultados. Pueden registrarse en el foro y comentarles a todos los participantes por separado, o utilizar los comentarios de este post. Para mi fue bien divertido participar, y espero que se una más gente en la próxima competición, muy pronto.
7 de junio de 2009
`
He aquí las láminas de la charla “Comienza un Videojuego y Termínalo”, dada ayer en las 2das. JOINCIC en la UCAB. Descargalas aquí (PDF, 1.3MB) Gracias a todos los asistentes, aquí les dejo los enlaces a los sitios que mencioné:
-
INVENTAD - Sitio del asociación Industria Nacional del Videojuego, Entretenimiento, y Artes Digitales que estamos armando en el país para convocar a los desarrolladores de videojuegos locales.
-
TIGSource - Excelente sitio de noticias sobre juegos independientes.
-
TIGSource Forums - El otro lado de este sitio. Una excelente comunidad que organiza competiciones de videojuegos con cierta regularidad.
-
Foros de El Chigüire Literario - Donde también estamos comenzando a armar competiciones :-)