lunes, 20 de octubre de 2008

Sobre Flash CS4. ActionScript 3 y la tercera dimensión

Este fin de semana he tenido la oportunidad de probar el nuevo Flash CS4 y la verdad es que me ha sorprendido gratamente la velocidad. La integración con las gráficas es magnifica porque proporciona una suavidad nunca vista antes en una película Flash.
Ayer estuve intentando implementar un sencillo efecto en el que había un carrusel de objetos rotando alrededor del eje Y, mi sorpresa fue que Flash no maneja la profundidad como lo hace un entorno 3D normal, sino que respeta el orden de dibujado de los objetos en la manera en la que fueron añadidos a su contenedor. Es por esto que tuve que implementar el algoritmo del pintor para que los objetos pudieran dibujarse en el orden correcto (antes de esto había objetos que se pintaban delante de otros cuando debían hacerlo detras).
El algoritmo del pintor consiste sencillamente en pintar de atrás hacia adelante, para ello debemos añadir nuestros Sprites a un vector y posteriormente implementar una función que compara los valores Z de cada Sprite devolviendo el vector ordenado para después mediante un simple pop añadir los objetos al contenedor. El problema viene a la hora de aplicar Tweeners, ya que debido al movimiento puede que en determinadas circunstancias sea necesario intercambiar los objetos de orden en su contenedor (porque ahora estén delante cuando antes estaban detrás), obligando al tweener a llevar un control de sorting constante y administrando el contenedor de tal forma que el dibujado siempre sea correcto.


var sprites:Vector.<Sprite>=new Vector.<Sprite>();
var radio:Number=900;

public function creaSprites():void{

// Creamos los sprites y los metemos en el vector

for (i=0;i<360;i+=45){
var sp:Sprite=new Sprite();
sp.graphics.beginFill(Math.random()*0xFFFFFF);
sp.graphics.drawRect(0,0,300,300);
sp.x=150-(radio*Math.cos(i*Math.PI/180)); // multiplicamos por PI/180 para pasar a grados
sp.y=0;
sp.z=20000-(radio*Math.sin(i*Math.PI/180));
sprites.push(sp);
}

// Ordenamos el vector e insertamos los sprites en el contenedor

sprites.sort(compare);

while (sprites.length!=0){
addChild(sprites.pop());
}
}

// Aqui viene la función de comparación utilizada por el sort del vector.
// Dados dos Sprites devuelve la diferencia de z.

private function compare(a:Sprite, b:Sprite):Number{
return a.z-b.z;
}


Como puede verse el proceso es sencillo (siempre y cuando no se realice ningún tween en el eje z), aunque a medida que investigue un poco más iré completando este artículo.

No hay comentarios: