Tutorial de Puzzle de Piezas Deslizantes en AS3 (Parte 1)

Este es el primer post de un mini tutorial que quise hacer sobre como crear un pequeño juego tipo puzzle de piezas deslizantes (tremendo nombre, pero no tengo idea de si hay otra forma de llamarlo, a pesar de que creo que todos hemos jugado esto alguna vez). En fin, el objetivo es llegar a tener algo como esto:

Para llegar a esto se partirá de un código básico y se le irá agregando cosas a cada paso; he tratado de comentar casi todo para que sea totalmente entendible, tal vez hay algunos comentarios que pueden ser muy obvios pero espero sean útiles.
Definitivamente no es la forma más orientada a objetos de hacer este jueguito, pero creo que así es más fácil de entender, además que es más práctico para mí. Espero que les guste =D
Bueno, manos al teclado:

Conociendo a Bitmap y BitmapData

Como primer paso necesitamos una imagen, para ello la importamos a la librería y la enlazamos con una clase.


En la línea de tiempo presionar F9 y escribir el siguiente código:
El nombre del archivo es: Parte 1 A

//Crea un BitmapData usando una imagen de la biblioteca
//la cual está ligada a la clase IFX
var imagenBmd:BitmapData = new IFX(0,0);

//Usa el BitmapData anterior para crear un Bitmap
var imagenBm:Bitmap = new Bitmap(imagenBmd);

//Imprime el alto y ancho de la imagen
trace("Alto: "+imagenBmd.height);
trace("Ancho: "+imagenBmd.width);

//Crea un Sprite y le agrega el Bitmap
var miSprite:Sprite=new Sprite();
miSprite.addChild(imagenBm);

//Finalmente se agrega el Sprite al stage
addChild(miSprite);

Como dice Jack, vamos por partes
Ahora que ya sabemos como obtener una imagen de la biblioteca y mostrarla, lo que vamos a hacer es cortar un pedazo de esa imagen y mostrar sólo ese pedazo. Para eso usaremos la función copyPixels, con la que obtenemos un objeto tipo BitmapData.
Sólo hay que modificar el código anterior por este:
El nombre del archivo es: Parte 1 B

var imagenBmd:BitmapData = new IFX(0,0);
trace("Alto: "+imagenBmd.height);
trace("Ancho: "+imagenBmd.width);

//Crea un BitmapData vació de tamaño 80x80
var imagenCopyBmd:BitmapData = new BitmapData(80, 80);
//Crea un Rectangle con parámetros: x=80, y=80, ancho=80, alto=80
var rect:Rectangle = new Rectangle(80, 80, 80, 80);
//Se usa la función copyPixels para copiar de imageBmd los pixeles
//marcados por el Rectangle anterior
imagenCopyBmd.copyPixels(imagenBmd, rect, new Point());
//Crea el Bitmap con el BitmapData obtenido
var imagenCopy:Bitmap = new Bitmap(imagenCopyBmd);

//Crea un Sprite y le agrega el Bitmap
var miSprite:Sprite=new Sprite();
miSprite.addChild(imagenCopy);
//Establece la posición X y Y del Sprite
miSprite.x=20;
miSprite.y=30;
addChild(miSprite);

Un puzzle tiene varias piezas
El siguiente paso es cortar la imagen en un determinado número de piezas tanto horizontales como verticales (yo he elegido tener un puzzle de 4×4) y alinearlas de forma que parezca realmente una imagen cortada puesta en orden. Para determinar el tamaño de piezas se toma en cuenta el número de piezas que se desea y el tamaño de la imagen. Necesitamos almacenar los Sprites en un arreglo para utilizarlos más adelante.
El nombre del archivo es: Parte 1 C

var imagenBmd:BitmapData = new IFX(0,0);

//Define el número de piezas que tendrá la imagen
var numPartesX:Number=4;
var numPartesY:Number=4;

//Define el ancho y alto de cada pieza
var anchoPartes:Number;
var altoPartes:Number;

//Se divide el tamaño de la imagen entre el
//número de piezas que se quiere
anchoPartes=imagenBmd.width/numPartesX;
altoPartes=imagenBmd.height/numPartesY;
//Se redondea usando floor para que si el tamaño
//no es exacto se pierda una parte a final de la imagen
anchoPartes=Math.floor(anchoPartes);
altoPartes=Math.floor(altoPartes);

//Arreglo bidimensional donde se guardan las piezas
var piezas:Array = new Array(numPartesY);

//Fors anidados para formar las piezas
for (var i:Number=0;i<numPartesY;i++){
	//Para que sea bidimensional se pone un arreglo dentro de otro
	var tmp:Array = new Array(numPartesX);
	for (var j:Number=0;j<numPartesX;j++){
		//La condición evita obtener la última pieza en la esquina
		//inferior derecha
		if ((i!=(numPartesY-1)) || (j!=(numPartesX-1))){
			var imagenCopyBmd:BitmapData = new BitmapData(anchoPartes, altoPartes);

			// j * anchoPartes , i*altoPartes : parámetros para extraer la parte
			// de la imagen que corresponde al número de la pieza actual
			var rect:Rectangle = new Rectangle(j*anchoPartes, i*altoPartes, anchoPartes, altoPartes);

			imagenCopyBmd.copyPixels(imagenBmd, rect, new Point());
			var imagenCopy:Bitmap = new Bitmap(imagenCopyBmd);
			var sp2:Sprite = new Sprite();
			sp2.addChild(imagenCopy);

			//Posiciona el Sprite en la posición correspondiente
			// j*1: deja un espacio entre piezas
			sp2.x=j*anchoPartes + (j*1);
			sp2.y=i*altoPartes + (i*1);

			//Nombre de la pieza
			sp2.name=i+"-"+j;

			tmp[j]=sp2;
			addChild(sp2);
		}

	}

	//Agrega un arreglo al otro
	piezas[i]=tmp;
}

Espero les haya gustado esta primera parte de este pequeño tutorial, próximamente estaré posteando las siguientes. Saludos.

Mientras tanto, pueden descargar el código fuente.