3D Boxes via ActionScript 3 – Part 2
February 6, 2009 by: smonteThis is the second part of the “Flash 3D Boxes via ActionScript 3″ tutorial. In this part, I will take the 3D animation one step further. In this tutorial, we’ll create a sine wave of boxes and learn how to animate them.
I am assuming that you have already completed the “Flash 3D Boxes via ActionScript 3″. Therefore, I will mainly concentrate on ActionScript in this tutorial.
Setting up the environment
1. First, create three sliders on the top left corner. Give them instance names that are seen in the picture below.
Moving into ActionScript 3
2. In the first frame of your main timeline, type the following code.
//First let's configure the sliders. angleSpeedSlider.value = 10; angleSpeedSlider.minimum = 1; angleSpeedSlider.maximum = 30; zSpeedSlider.value = 7; zSpeedSlider.minimum = 1; zSpeedSlider.maximum = 20; radiusSlider.value = 7; radiusSlider.minimum = 1; radiusSlider.maximum = 20; //The maximum depth const MAXIMUM_Z:Number = 450; //The number of the boxes const NUMBER_OF_BOXES:Number = 14; //Create an array that will contain all the boxes var boxes:Array = new Array(); //Set the focal length var focalLength:Number = 300; //Set the vanishing point var vanishingPointX:Number = stage.stageWidth / 2; var vanishingPointY:Number = 20; //The 3D floor for the boxes var floor:Number = 80; //The starting depth var startingDepth:Number = MAXIMUM_Z; //The z distance between two boxes var zDistance:Number = 50; //The depth speed (how fast the boxes are moving towards you) var zSpeed:Number = -(zSpeedSlider.value); //We assign a different starting angle for each box (we increment this later on) var angle:Number = 0; //Angle difference between the boxes var angleDifference:Number = 0.3; //How fast the angle changes var angleSpeed:Number = angleSpeedSlider.value * 0.01; //The radius for the boxes var radius:Number = radiusSlider.value * 10; //This loop creates and positions the boxes (starting from the box furthest away) for (var i=0; i < NUMBER_OF_BOXES; i++) { //Create a new box var box:MyBox = new MyBox(); //Calculate the 3D x position (we will do a sine wave) box.xpos3D = Math.sin(angle) * radius; //Save the angle information for the box box.currentAngle = angle; //Increase the starting angle for the next box angle += angleDifference; //3D y position is the same for all the boxes box.ypos3D=floor; //Assign a z value for the box (the greater the z, the further away the box is) box.zpos3D=startingDepth; //Update the starting depth for the next box startingDepth-=zDistance; //Calculate the scale ratio for the box var scaleRatio = focalLength/(focalLength + box.zpos3D); //Scale the box according to the scale ratio box.scaleX=box.scaleY=scaleRatio; //Position the box on to the stage (from 3D to 2D coordinates) box.x=vanishingPointX+box.xpos3D*scaleRatio; box.y=vanishingPointY+box.ypos3D*scaleRatio; //Push the box to the array boxes.push(box); //Add the box on to the stage addChild(box); } //We use ENTER_FRAME for the animation addEventListener(Event.ENTER_FRAME, enterFrameHandler); //This function is called in each frame function enterFrameHandler(e:Event):void { //First, let's get the dynamic speeds from our sliders angleSpeed=angleSpeedSlider.value*0.01; zSpeed = -(zSpeedSlider.value); radius = radiusSlider.value * 10; //Loop through the array of boxes for (var i=0; i < NUMBER_OF_BOXES; i++) { //Save the box to a local variable var box:MyBox = (MyBox)(boxes[i]); //Update the z position of the box box.zpos3D+=zSpeed; //Update the current angle of the box box.currentAngle+=angleSpeed; //If zpos3D <= -focalLength, we end up with a negative scaleRatio (or we are dividing by zero). //At this point, we know that the object has already passed "us". //Therefore, we put the box behind the last box of the line. if (box.zpos3D<=- focalLength) { //Save the last box to a local variable //The last box of the line is always first in the array, //because of the sortZ() function. var lastBox:MyBox = (MyBox)(boxes[0]); //Position the box behind the last box box.zpos3D=lastBox.zpos3D+zDistance; //Get the new angle for the box (same as the last box's, minus the angle difference). //This way the box wave stays uniform. box.currentAngle=lastBox.currentAngle-angleDifference; } //Calculate the new 3D x position box.xpos3D=Math.sin(box.currentAngle)*radius; //Calculate a scale ratio for the box var scaleRatio = focalLength/(focalLength + box.zpos3D); //Scale the box according to the scale ratio box.scaleX=box.scaleY=scaleRatio; //Set an alpha according to the scale ratio box.alpha=scaleRatio-0.5; //Position the box on to the stage (from 3D to 2D coordinates) box.x=vanishingPointX+box.xpos3D*scaleRatio; box.y=vanishingPointY+box.ypos3D*scaleRatio; } //Sort the boxes according to depth sortZ(); } //This function sorts the boxes so they overlap correctly function sortZ():void { //Sort the array so that the box which has the highest //z position (= furthest away) is first in the array boxes.sortOn("zpos3D", Array.NUMERIC | Array.DESCENDING); //Set new child indexes for the boxes for (var i:uint = 0; i < NUMBER_OF_BOXES; i++) { setChildIndex(boxes[i], i); } }
You are done, test your movie The code should be commented well enough, so I will not go over that. As you can see, 3D animation is not that much harder than 2D. We just position the objects to an imaginery 3D environment and then convert the 3D coordinates in to 2D coordinates. If have any questions, please post them in the forum.
Related tutorials:
Comments
4 Responses to “3D Boxes via ActionScript 3 – Part 2”Leave a Reply
You must be logged in to post a comment.
Any chance of the same tutorial with the new flash 10 z property.
Thanks, I updated the code!
Very nice set of tutorials – I appreciate the math. Just one quick thing – the second tutorial won’t quite compile, because the MyBox.as class from the first tutorial is missing a variable which the second tutorial needs (the currentAngle attribute). Easily fixed with the addition of
public var currentAngle:Number = 0;
to the MyBox class and all is well.
Thanks again!