Introducción a FlashPunk: Videojuegos 2D en Flash

danii . viernes 7 de septiembre de 2012. a las 10:58

Demo Subflash FlashPunk

Durante el taller de Desarrollo de Videojuegos en Flash del Subflash hicimos una pequeña introducción al framework Flash de creación de videojuegos en 2D FlashPunk. Este framework es perfecto para la creación de videojuegos estilo retro (plataformers, RPGs) para ejecutar en web ya que, por desgracia, no está demasiado optimizado para mobile. Sin embargo, resulta tan ágil y cómodo de trabajar en él que se está utilizando mucho para prototipado rápido de videojuegos para testear la jugabilidad antes de comenzar la producción.



Los propios creadores de FlashPunk han dejado de trabajar en este framework al considerarlo un proyecto cerrado y acabado, pero esto no significa que el framework esté muerto ni mucho menos. La comunidad de usuarios sigue siendo enorme y muy activa; no hay más que echarle un vistazo a los foros de FlashPunk, donde prácticamente a diario se presentan juegos creados con este framework!

Demo Minijuego

La potencia FlashPunk para agilizar el proceso de desarrollo de un videojuego se demuestra con esta demo que está programada de principio a fin en poco más de un par de horas (no teníamos mucho más tiempo disponible) en apenas unas 400 líneas de código repartidas en 5 clases.

Flashpunk Console

ver demo   

El código fuente está en formato FlashBuilder 4.6 project (si no me equivoco es compatible también con FB 4.5) y está listo para ser ejecutado, tan sólo vais a necesitar el propio framework FlashPunk (descargar aquí) e incluirlo en el Build Path del proyecto (properties -> ActionScript Build Path -> Source Path -> Add Folder) para que compile sin problemas.

Alguna de las cosas que nos ofrece FlashPunk para hacernos la vida más fácil y que comentamos durante la charla del Subflash (y que por supuesto vais a encontrar en el código fuente de este ejemplo) son:

Consola de FlashPunk

Nos ofrece información sobre la memoria que está ocupando el juego, así como los FPS (Frames Per Second) a los que se está ejecutando y otra información adicional relativa al framework, por ejemplo el número de entidades que el motor está manejando.

Al pulsar ENTER en este ejemplo activamos el Visor de Colisiones, donde podemos ver los hitbox de cada una de las entidades en pantalla. Además, utilizando los controles de la consola, podemos pausar en cualquier momento el ENTER_FRAME principal del juego y después continuar con la ejecución, o incluso hacer una ejecución step by step, realmente útil para debugging!

Colisiones

En FlashPunk todo elemento que se encuentra en pantalla es una entidad (hereda de la clase base Entity). Todas las entidades que pueden ser colisionables deben definir un hitbox para el cálculo de dichas colisiones (o una máscara si queremos Pixel Perfect Collision). Además, podemos «agrupar» entidades al definirnos tipos de entidades, utilizando la propiedad type, de esta forma el framework checkeará las colisiones sin necesidad de que nosotros hagamos explícitamente un bucle y vayamos comprobando elemento a elemento. Por ejemplo en nuestro caso:

//objeto gráfico ipad extiende de la clase Entity
public class EntityIPad extends Entity	
{

  //embeds y variables
  //...
 
  public function EntityIPad()
  {
    super();

    //definimos esta entidad como tipo "ipad"
    //para agrupar colisiones
    type = "ipad";

    //hitbox para colisiones (width y height)
    setHitbox(20,24);

    //rest of stuff
    //...

Una vez hemos definido estos tipos de entidades, podemos utilizar los métodos de la clase base Entity collide (que devuelve true si se ha producido una colisión con un tipo de entidades especificado como parámetro) o collideInto (para colisiones múltiples, ver ejemplo de código).


//colisiones con entidades "block"
//un pixel debajo de los pies
if(collide("block", x, y+1))
{
  //..
}

//colisiones múltiples
//almacena en el array list 
//todas las entidades del tipo "ipad"
//con las que colisionamos
var list:Array = [];
collideInto("ipad", x, y, list);

//si ha habido colisiones
if (list.length > 0)
{
  //...
  //do stuff here
}

Como comentamos durante la charla, la dificultad del manejo de colisiones radica en que no sólo hay que detectarlas, sino que hay que responder adecuadamente. Pues bien, FlashPunk nos ayuda también en esto gracias al método moveBy, que moverá una entidad pero atendiendo en todo momento a las colisiones con las entidades que le especifiquemos:

//nos movemos, comprobando colisiones con pared, suelo:	
moveBy(xSpeed, ySpeed, "block");

Y, en caso de producirse colisión, le especificamos qué hacer haciendo un override de los métodos moveCollideX y moveCollideY, en este caso simplemente anularemos el resto del movimiento una vez se produza una colisión:

override public function moveCollideX(e:Entity):Boolean
{
  xSpeed = 0;
  return true;
}
		
override public function moveCollideY(e:Entity):Boolean
{
  ySpeed = 0;
  return true;
}

Object Pooling indoloro y fácil

Es realmente importante que seamos conscientes que la creación y destrucción de objetos es una de las cosas que más pueden afectar al rendimiento en ejecución de nuestro juego. Por ello, es recomendable utilizar siempre algún tipo de técnica de Object Pooling en objetos que se van a ir creando y destruyendo continuamente, como suelen ser los enemigos recurrentes o los items que va a recoger el prota del juego.

Por suerte para nosotros, FlashPunk viene con un gestor propio de Object Pooling para entidades listo para que lo utilicemos si lo necesitamos, sin más quebraderos de cabeza. Es tan sencillo como, al eliminar una entidad, marcarla para reciclaje, y al crear una en vez de hacer new accederemos al pool de entidades listas para ser recicladas:

//object pooling
//en vez de FP.world.remove(this);
FP.world.recycle(this);

//accedemos al pool de iPads
//en vez de new EntityIPad();
create(EntityIPad,false) as EntityIPad; 

User Input

Quién haya sufrido alguna vez las carencias de los KeyboardEvent de Flash apreciará lo sencillo y potente que es la gestión de User Input mediante teclado en FlashPunk, gracias a las clases helper estáticas Key y sobretodo Input de las que dispone el framework. Creo que en este caso el ejemplo ilustra mejor que cualquier explicación que yo pueda hacer la pequeña maravilla que son estas clases:


//definimos controles
Input.define("Shoot", Key.SPACE, Key.C);

if (Input.pressed(Key.SPACE))
{
  //Barra espaciadora presionada ESTE frame
  //shoot_sound.play();
  //do stuff...				
}

if (Input.released(Key.SPACE))
{
  //barra espaciadora soltada (release) ESTE frame.
  //do stuff		
}
	
if (Input.check("Shoot"))
{
  //una o varias teclas definidas como "Shoot" están presionadas
  //en nuestro caso, SPACE y/o C
}
			

Blitting

Otra de las máximas a la hora de programar videojuegos en Flash es que hay que evitar las animaciones por MovieClips ya que consumen muchos recursos. En lugar de ellas, utilizaremos sprite sheets en PNG, donde en un único archivo irán agrupadas todas las «fases» de la animación de cada personaje. Por ejemplo, en nuestra demo éste es el sprite sheet que hemos utilizado, donde además he destacado en diferentes colores las diferentes animaciones:

Spritesheet junto con los estados utilizados en la demo

Y posteriormente es realmente intuitivo como definimos en una Entity de FlashPunk las distintas animaciones y cómo hacemos que se reproduzcan:


//embebemos el asset (PNG sprite sheet)
[Embed(source = 'assets/robot-flashpunk3.png')] private const ROBOT_PLAYER:Class;

//variable spritemap
public var robotSprites:Spritemap = new Spritemap(ROBOT_PLAYER, 31, 44);

//definimos las diferentes animaciones presentes en el spritemap
robotSprites.add("stand", [0, 1, 2, 3, 4], 10, true);
robotSprites.add("run", [5, 6, 7, 8, 9], 10, true);
robotSprites.add("jump", [10, 11, 12, 13, 14], 10, false);
robotSprites.add("land", [15, 16, 17, 18, 19], 10, false);
robotSprites.add("airborne", [20, 21, 22, 23, 24], 10, true);

//animacion inicial
robotSprites.play("stand");

El parámetro final booleano lo que hace es indicar si la animación será un loop (es decir, cuando llegue al final volverá al principio) o al llegar al final de la animación debe entrar otra. En ese caso, podemos indicar una función callback que será llamada al finalizar la animación y que utilizaremos lógicamente para indicar el siguiente estado.

Para aprender más

Además en el código fuente de la demo podréis ver otras características del framework que por falta de tiempo (u omisión flagrante) no comentamos durante la charla, por ejemplo:

  • Emisores de partículas
  • Manejo de efectos de sonido
  • Temporizadores independientes del framerate

Bueno, esta es la pequeña introducción al mundo de FlashPunk que ofrecimos en la charla del Subflash. Además, no puedo dejar de recomendaros los tutoriales oficiales de FlashPunk, en particular los videotutoriales, donde podemos aprender de todo, desde cómo configurar correctamente FlashBuilder (¡y conseguir que nuestro proyecto se ejecute en Flash Player Debugger!) a una sesión maratoniana en la que se crea un videojuego de principio a fin, empezando desde cero, en vivo y en directo.



Etiquetas: , , , , ,

5 Comentarios
» Feed RSS de los Comentarios

  1. P dice:

    Hola,
    Imagino que lo sabréis, pero hay otro motor de juegos creado sobre «starling» y basado en flashpunk, que se llama «starlingpunk».

    Lo comento porque creo que éste si puede tener un futuro real y además está creado sobre un framework moderno (starling) con acceso a la gpu.

    http://www.andysaia.com/radicalpropositions/

    Un saludo!

  2. danii dice:

    Buenas y gracias por el aporte!

    Sí que conocemos StarlingPunk, es un proyecto muy muy reciente y cuyo desarrollo seguimos bastante de cerca ya que la idea de unir lo mejor de ambos mundos (FlashPunk+Starling) nos parece genial, ya que en mi opinión las fortalezas de uno complementan perfectamente las debilidades del otro. Durante la charla de Desarrollo de Videojuegos del Subflash comentamos además de StarlingPunk otro proyecto similar, la v3 de Citrus Engine:

    http://www.aymericlamboley.fr/blog/citrusengine-goes-stage3d-with-starling/

    En futuros posts hablaremos más sobre Starling, y quizás sobre StarlingPunk 😉

  3. cmacias dice:

    Empiezo a arrepentirme de haber dejado flash justo cuando salió AS3 xD

  4. joanra dice:

    Magnífico post. Una pregunta, entre Flashpunk, Starling o Flixel, ¿con cuál te quedas? ¿Hay algún otro motor potente para 2d que nos recomiendes?

  5. danii dice:

    Buenas joanra! Entre FlashPunk y Flixel es difícil escoger, los dos son proyectos bastante similares y ambos nos ayudarán MUCHO a la hora de desarrollar un videojuego en 2D en Flash con el browser como plataforma. Me parece que ambos ofrecen más o menos lo mismo, así que es básicamente cuestión de gustos. Yo he trabajado más con FlashPunk así que mis preferencias personales van por ese lado…

    En cuanto a Starling, como comento en nuestro post sobre el framework:

    http://www.lostiemposcambian.com/blog/as3/introduccion-a-starling-videojuegos-mobile-en-flash/

    nos ofrece una cosa realmente INDISPENSABLE si queremos exportar nuestro juego para mobile: Aceleración por GPU de los gráficos y soporte para el uso de SpriteAtlas.

    Aunque Starling por otro lado no tiene otras muchas cosas específicas para desarrollo de videojuegos que FlashPunk o Flixel sí que nos aportan. Por eso están empezando a aparecer motores de más alto nivel construidos sobre la base de Starling, como por ejemplo los ya comentados en otros comentarios StarlingPunk o Citrus Engine… aunque en mi impresión todavía están en fase «embrionaria».

    ¿He conseguido ya liarte más? 😉

Enviar comentario