Implementando un DepthHandler(Manejador de profundidad)
28 10 2006A 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 "Depht" del objeto MovieClip(accedido a travez 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 5 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, al circulo lo llamaremos heroe, el cual será el objeto que controlaremos por teclado. Todos deben ser MovieClips. El resultado debe quedarnos tal cual muestra la sicuiente imagen.

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 heroe a 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) mas 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 heroe(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 dephts implementando un boble 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ía aparecer antes que B en el array ordenado
-
0, Si A = B
-
>0, Si A debería aparecer despues 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 la "Live Preview" donde se aprecia el funcionamiento del algoritmo.
Descarga de los fuentes
Fuentes del tutorial.








hola, buen dia, he intentado hacer que se mueva el circulo a cualquier sitio del escenario dando click con el mouse en lugar de utilizar los cursores, pero no lo logro, me podrias ayudar con el codigo?
Muchas gracias y que tengas un excelente dia
Si, te cuento, es “casi fácil”. Ahora mismo no dispongo de tiempo para una respuesta extensa, pero te voy a dar algunas palabras para que busques en google. Si a la noche no lo resolviste posteo código que no tengo en este momento.
Resulta que tenés que obtener el versor del vector definido por la posición actual del círculo y el punto donde hiciste click con el mouse. Una vez hecho esto, lo multiplicas por la velocidad que deseás que se mueva el círculo.
Un método más fácil es usando easyng.
Recuerdo que era algo parecido a eso.
Saludos!