//# package package { import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; //@ class public class animation_ch18_RotateXY extends Sprite { private var balls:Array; private var numBalls:uint = 50; private var fl:Number = 250; private var vpX:Number = stage.stageWidth / 2; private var vpY:Number = stage.stageHeight / 2; //@ constructor public function animation_ch18_RotateXY() { init(); } //@ init(s) private function init():void { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; balls = new Array(); //@ initialize ball(s) / enterFrame for(var i:uint = 0; i < numBalls; i++) { var ball:animation_ch18_Ball3D = new animation_ch18_Ball3D(15); balls.push(ball); ball.xpos = Math.random() * 200 - 100; ball.ypos = Math.random() * 200 - 100; ball.zpos = Math.random() * 200 - 100; addChild(ball); } addEventListener(Event.ENTER_FRAME, onEnterFrame); } //@ animation handler / frame(s) private function onEnterFrame(event:Event):void { var angleX:Number = (mouseY - vpY) * .001; var angleY:Number = (mouseX - vpX) * .001; for(var i:uint = 0; i < numBalls; i++) { var ball:animation_ch18_Ball3D = balls[i]; rotateX(ball, angleX); rotateY(ball, angleY); doPerspective(ball); } sortZ(); } //@ rotate X private function rotateX(ball:animation_ch18_Ball3D, angleX:Number):void { var position:Array = [ball.xpos, ball.ypos, ball.zpos]; var sin:Number = Math.sin(angleX); var cos:Number = Math.cos(angleX); var xRotMatrix:Array = new Array(); xRotMatrix[0] = [1, 0, 0]; xRotMatrix[1] = [0, cos, sin]; xRotMatrix[2] = [0, -sin, cos] var result:Array = matrixMultiply(position, xRotMatrix); ball.xpos = result[0]; ball.ypos = result[1]; ball.zpos = result[2]; } //@ rotate Y private function rotateY(ball:animation_ch18_Ball3D, angleY:Number):void { var position:Array = [ball.xpos, ball.ypos, ball.zpos]; var sin:Number = Math.sin(angleY); var cos:Number = Math.cos(angleY); var yRotMatrix:Array = new Array(); yRotMatrix[0] = [ cos, 0, sin]; yRotMatrix[1] = [ 0, 1, 0]; yRotMatrix[2] = [-sin, 0, cos] var result:Array = matrixMultiply(position, yRotMatrix); ball.xpos = result[0]; ball.ypos = result[1]; ball.zpos = result[2]; } //@ matrix multiplication private function matrixMultiply(matrixA:Array, matrixB:Array):Array { var result:Array = new Array(); result[0] = matrixA[0] * matrixB[0][0] + matrixA[1] * matrixB[1][0] + matrixA[2] * matrixB[2][0]; result[1] = matrixA[0] * matrixB[0][1] + matrixA[1] * matrixB[1][1] + matrixA[2] * matrixB[2][1]; result[2] = matrixA[0] * matrixB[0][2] + matrixA[1] * matrixB[1][2] + matrixA[2] * matrixB[2][2]; return result; } //@ perspective / trick(s) = scaling private function doPerspective(ball:animation_ch18_Ball3D):void { if(ball.zpos > -fl) { var scale:Number = fl / (fl + ball.zpos); ball.scaleX = ball.scaleY = scale; ball.x = vpX + ball.xpos * scale; ball.y = vpY + ball.ypos * scale; ball.visible = true; } else { ball.visible = false; } } //@ do not forget to sort-Z private function sortZ():void { balls.sortOn("zpos", Array.DESCENDING | Array.NUMERIC); for(var i:uint = 0; i < numBalls; i++) { var ball:animation_ch18_Ball3D = balls[i]; setChildIndex(ball, i); } } } }