Comunidad de diseño web y desarrollo en internet

Manejar profundidad de MovieClips de Flash con DepthHandler

A Flash le falta un buen manejador de profundidad, es decir, algo que nos ordene los objetos en base a un criterio dado, de manera tal que se de cuenta solo cuando un objeto debe "tapar" a otro debido a que se encuentra mas cerca del ojo del espectador. Si bien contamos con la propiedad "Depth" del objeto MovieClip(accedido a través del método getDepth), a muchos no les queda claro como utilizarlos. En este tutorial explico como implementar un DepthHandler muy sencillo y efectivo.

Para comenzar dibujamos cinco objetos en un lienzo en blanco, todos deben estar en la misma capa. Les llamaremos por sus colores, para que sean fáciles de ubicar crearemos un circulo llamado héroe, el cual será el objeto que controlaremos mediante el teclado. Todos deben ser MovieClips. El resultado debe quedarnos tal cual muestra la sicuiente imagen.

Depth Handler

A continuación, agregaremos el siguiente código en el frame:

//Creo el array que contiene los objetos a ordenar
var arrDepthObjects:Array = new Array();
arrDepthObjects.push(this.blue);
arrDepthObjects.push(this.green);
arrDepthObjects.push(this.red);
arrDepthObjects.push(this.orange);
arrDepthObjects.push(this.heroe);
//La siguiente función solo se ejecutará una vez
this.onEnterFrame = function() {
    rearrangeDepths(arrDepthObjects);
    this.onEnterFrame = null;
};
//Esta función reordena los depths, intercambiando los objetos en base a su posición en el eje y
function rearrangeDepths(pArrObjects:Array) {
    var i:Number;
    var pArrObjects:Array;
    var mc:MovieClip;
    for (i=0; i<pArrObjects.length; i++) {
        trace(pArrObjects[i]._name);
    }
    //para apreciar el ordenamiento, imprimimos esta linea en la consola, para poder diferenciar el antes del despues
    trace("-----------------------");
    /*recurrimos al método "sort" de la clase array, para no complicarnos con el algoritmo de ordenamiento.
    Noten que paso una función como parámetro, esto es para indicarle al método sort
    cuando dos objetos deben intercambiarse.*/
    pArrObjects.sort(compare);
    //mostramos el nuevo orden
    for (i=0; i<pArrObjects.length; i++) {
        trace(pArrObjects[i]._name);
    }
    this.onEnterFrame = null;
}
/*Esta función devuelve un número:
<0, Si A debería aparecer antes que B en el array ordenado
0, Si A = B
>0, Si A debería aparecer después que B en el array ordenado*/
function compare(a:MovieClip, b:MovieClip):Number {
    return a._y-b._y;
}

Ejecutamos la función y obtenemos lo siguiente:

blue
green
red
orange
heroe
-----------------------
blue
green
red
heroe
orange

Como podemos ver, el héroe ha pasado de estar en la ultima posición a la penúltima. Esto se debe a que el valor de su propiedad _y era menor que el objeto orange. Con esto hemos conseguido tener un array ordenado según la posición vertical de los MovieClips. Esto es útil ya que, en la perspectiva, mientras más alto está el objeto(más cerca del horizonte) más lejos esta del observador. Bien, ahora incorporaremos código para intercambiar las profundidades según el orden del Array. Eliminaremos el código para mostrar y agregaremos código para controlar al héroe(circulo negro) mediante el teclado. El código terminado es el siguiente:

//Creamos el array
var arrDepthObjects:Array = new Array();
arrDepthObjects.push(this.blue);
arrDepthObjects.push(this.green);
arrDepthObjects.push(this.red);
arrDepthObjects.push(this.orange);
arrDepthObjects.push(this.heroe);
this.onEnterFrame = function() {
    //Código para controlar el teclado, el bucle ahora se ejecuta infinitamente.
    switch (Key.getCode()) {
    case (Key.Up) :
        heroe._y -= 10;
        break;
    case (Key.DOWN) :
        heroe._y += 10;
        break;
    case (Key.LEFT) :
        heroe._x -= 10;
        break;
    case (Key.RIGHT) :
        Heroe._x += 10;
        break;
    }
    //Llamamos a la función que reordena los objetos segun sus profundidades.
    rearrangeDepths(arrDepthObjects);
};
//Función para reordenar los objetos segun su posición orizontal
//y, a partir de ellas, modificar sus profundidades
function rearrangeDepths(pArrObjects:Array) {
    var i:Number, j:Number;
    //Llamamos al método sort, pasandole la función de comparación como parámetro
    pArrObjects.sort(compare);
    /*Ahora reordenamos los depths implementando un bouble Sort, lo siento, leí sobre el
	algoritmo quick sort pero no lo entendí, asi que lo implemento de esta manera.*/
    for (i=0; i<pArrObjects.length; i++) {
        for (j=i+1; j<pArrObjects.length; j++) {
            if (pArrObjects[i].getDepth()>pArrObjects[j].getDepth()) {
                //intercambio los indicadores de profundidad de los objetos.
                pArrObjects[i].swapDepths(pArrObjects[j]);
            }
        }
    }
}
/*Esta función devuelve un número:
< 0, Si A deberá aparecer antes que B en el array ordenado
0, Si A = B
>0, Si A deberá aparecer después que B en el array ordenado
*/
function compare(a:MovieClip, b:MovieClip):Number {
    return a._y-b._y;
}

Y eso es todo, a continuación les muestro ejemplo donde se aprecia el funcionamiento del algoritmo.

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Descargar Archivo

Publica tu comentario

El autor de este artículo ha cerrado los comentarios. Si tienes preguntas o comentarios, puedes hacerlos en el foro

Entra al foro y participa en la discusión

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate