4 December 2009
You should have a basic understanding of the Adobe Flash authoring interface, working with symbols, and mouse interaction. An awareness of 3D is useful too; you should be familiar with the topics discussed in Mariko Ogawa's article, Exploring the new 3D features in Flash. Links to more information about 3D in Flash are included at the end of this tutorial.
Beginning
This tutorial shows how to use the three-dimensional features of Adobe Flash Player 10 and Adobe Flash CS4 Professional using ActionScript 3, and how to apply them to make a user-controlled 3D animation.
The new 3D support in Flash Player 10 does a lot of the 3D work for you, and is integrated to work like the 2D properties. Since these 3D properties are similar to their 2D counterparts, adding 3D features and effects to games and animations may feel familiar to you, even if the mental and visual model is not.
In this 3D tutorial, I show you how to create a string of stars moving in 3D and how to get them to respond in 3D to user input, as shown in Figure 1 (click to play the animation; adjust the sliders to see the effect).
The 3D features in Flash Player 10 enable you to set 3D attributes and let Flash Player do the rest of the calculations for you. This allows you to add 3D to games or SWF content without the amount of math calculations previously needed. This tutorial will manipulate stars in ActionScript, but first you need to create the Stage and put the graphic assets into the Library:
Now that the assets are available in the Library, you will use ActionScript to place them on the Stage and then move them towards the viewer:
//The number of stars to show
const NUMBER_OF_STARS:int = 14;
//Visible distance up from the bottom for the top-most star
//(all have the same y value)
const ORIGINAL_YBORDER:Number = 35;
//The z distance between the stars (an arbitrary setting)
const ZDISTANCE:int = 215;
//The initial Z position of the first star, so the top star is at z=0
const INITIAL_STAR_DEPTH:Number = 2795;
//Z value for when a star goes out of view (found visually)
const MINIMUM_STAR_DEPTH:Number = -221;
//Timer delay in milliseconds. 30 ms equals about 33.3 frames per second.
const MYTIMERFREQUENCY:Number = 30;
// The speed of the stars toward the user
var zSpeed:Number = 15;
//Create an array that will contain all the stars
var stars:Array = new Array();
//These variables declared outside of loops for performance reasons:
//Star depth local variable
var starDepth:Number = INITIAL_STAR_DEPTH;
//Local variable for operating on stars
var currentStar:Star;
//The default vanishing point is set at the center of the stage. For
//this demo, we'll move it closer to the top, so we can "look down" on
//the stars.
root.transform.perspectiveProjection.projectionCenter =
new Point(stage.stageWidth / 2, stage.stageHeight / 8);
//Star creation loop
//Create and position the stars, starting with the farthest one
for (var i:int=0; i < NUMBER_OF_STARS; i++)
{
//Create a new star
currentStar = new Star();
//x and y coordinates are the same for all stars: middle of the
//stage, a little up from the bottom.
currentStar.x = (stage.stageWidth/2);
currentStar.y = stage.stageHeight - ORIGINAL_YBORDER;
//Set the depth, or z-value, representing how far away the box is
//from the viewer
currentStar.z = starDepth;
//Set the object alpha so that stars further away appear fainter
currentStar.alpha = Math.min(1.0, 0.25 +
((INITIAL_STAR_DEPTH - starDepth) /
(INITIAL_STAR_DEPTH - MINIMUM_STAR_DEPTH) * 0.8));
//Add star to the array
stars.push(currentStar);
//Add star to the stage
addChild(currentStar);
//Update the starting depth for the next star, which will be closer
starDepth -= ZDISTANCE;
}
You should have something showing a trail of stars leading off into the horizon, as shown in Figure 1 at the beginning of the article.
//Create a timer to go off every 30 ms, which equals about about 33.3 frames per second.
var actionTimer=new Timer(MYTIMERFREQUENCY);
actionTimer.addEventListener(TimerEvent.TIMER, timerHandler);
//This function is called each time the timer goes off "top"
function timerHandler(e:TimerEvent):void
{
//Loop through the array of stars
for (var i=0; i < NUMBER_OF_STARS; i++)
{
//Access the star via a local variable.
currentStar = stars[i];
//Bring the star closer by decreasing its y value
currentStar.z -= zSpeed;
//When the z value is less than the minimum star depth, we know the
//star has "passed" us, and can be placed at the end of the line
//by setting both the z order and putting it first in the display
//list (ff z is less than zero, then the star is "really close", but
//still may be on screen.)
if (currentStar.z < MINIMUM_STAR_DEPTH)
{
//Set to end of line, farthest from the viewer
currentStar.z = INITIAL_STAR_DEPTH;
//Move this star to the end (behind others in the display list)
setChildIndex(currentStar,0);
}
//Set the object alpha so that stars further away appear fainter
currentStar.alpha = Math.min(1.0, 0.25 + ((INITIAL_STAR_DEPTH - currentStar.z) /
(INITIAL_STAR_DEPTH - MINIMUM_STAR_DEPTH) * 0.8));
}
}
//Hook the play/pause button up to start and stop the timer
playpause.addEventListener(MouseEvent.CLICK, playButtonHandler);
function playButtonHandler(ev:MouseEvent):void
{
if (actionTimer.running)
{
actionTimer.stop();
playpause.play_mc.visible = true;
playpause.pause_mc.visible = false;
} else
{
actionTimer.start();
playpause.play_mc.visible = false;
playpause.pause_mc.visible = true;
}
}
Now hook up the user inputs to control the animated stars. The controls add a horizontal oscillation and speed control:
//Configure the sliders.
angleSpeedSlider.value = 10;
angleSpeedSlider.minimum = 1;
angleSpeedSlider.maximum = 30;
zSpeedSlider.value = zSpeed;
zSpeedSlider.minimum = 1;
zSpeedSlider.maximum = 30;
radiusSlider.value = 7;
radiusSlider.minimum = 1;
radiusSlider.maximum = 20;
//Assign a different starting angle for each star (incremented later)
var angle:Number = 0;
//Angle difference between the stars
const 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 * 20;
//Array to match the stars array to hold the corresponding star's angle.
var angles:Array = new Array();
currentStar.x = (stage.stageWidth / 2);
with this:
currentStar.x = (stage.stageWidth / 2) - Math.sin(angle)*radius;
//Store the angle of this star. Each star and it's angle can be
//referenced using the same array index
(stars[i] and angles[i]).angles.push(angle);
//Update the angle for the next star
angle += ANGLEDIFFERENCE;
The star creation loop should now look like the following:
//Star creation loop
//Create and position the stars, starting with the farthest one
for (var i:int=0; i < NUMBER_OF_STARS; i++)
{
//Create a new star
currentStar = new Star();
//x and y coordinates are the same for all stars: middle of the
//stage, a little up from the bottom.
currentStar.x = (stage.stageWidth / 2) - Math.sin(angle)*radius;
currentStar.y = stage.stageHeight - ORIGINAL_YBORDER;
//Set the depth, or z-value, representing how far away the box is
//from the viewer
currentStar.z = starDepth;
//Set the object alpha so that stars further away appear fainter
currentStar.alpha = Math.min(1.0, 0.25 + ((INITIAL_STAR_DEPTH - starDepth) /
(INITIAL_STAR_DEPTH - MINIMUM_STAR_DEPTH) * 0.8));
//Add star to the array
stars.push(currentStar);
//Add star to the stage
addChild(currentStar);
//Update the starting depth for the next star, which will be closer
starDepth -= ZDISTANCE;
//Store the angle of this star. Each star and it's angle can be
//referenced using the same array index (stars[i] and angles[i]).
angles.push(angle);
//Update the angle for the next star
angle += ANGLEDIFFERENCE;
}
//This function is called each time the timer goes off
function timerHandler(e:TimerEvent):void
{
//First get the dynamic speeds from the user interface sliders
angleSpeed =angleSpeedSlider.value*0.01;
zSpeed = zSpeedSlider.value;
radius = radiusSlider.value * 20;
//Loop through the array of stars
for (var i=0; i < NUMBER_OF_STARS; i++)
{
//Access the star via a local variable.
currentStar = stars[i];
//Get the Star's angle
angle = angles[i];
//Bring the star closer by decreasing its y value
currentStar.z -= zSpeed;
//When the z value is less than the minimum star depth, we know the
//star has "passed" us, and can be placed at the end of the line
//by setting both the z order and putting it first in the display
//list (if z is less than zero, then the star is "really close", but
//still may be on screen.)
if (currentStar.z < MINIMUM_STAR_DEPTH)
{
//Set to end of line, farthest from the viewer
currentStar.z = INITIAL_STAR_DEPTH;
// reset the angle to follow the previous star, by
// getting the angle of the previous star
if (i != NUMBER_OF_STARS - 1)
{
//Set behind the last star, by the angle difference
angle = angles[i+1] - ANGLEDIFFERENCE;
}
else
{
//Angles[0] has already been incremented,
//so also subtract the anglespeed we'll be adding
//after this if block, to maintain just the angledifference.
angle = angles[0] - ANGLEDIFFERENCE - angleSpeed;
}
//Move this star to the end (behind others in the display list)
setChildIndex(currentStar,0);
}
//Increment and save the star's new angle
angle += angleSpeed;
angles[i] = angle;
//Calculate the new x position for this star
currentStar.x = (stage.stageWidth/2) - Math.sin(angle) * radius;
//Set the object alpha so that stars further away appear fainter
currentStar.alpha = Math.min(1.0, 0.25 + ((INITIAL_STAR_DEPTH - currentStar.z) /
(INITIAL_STAR_DEPTH - MINIMUM_STAR_DEPTH) * 0.8));
}
}
You now have given the user the ability to control the speed and the amount of oscillation of the stream of stars. The sample file Moving-Stars-2.fla shows the star parade with user controls hooked up.
You can perform multiple movements at the same time, both 2D and 3D. Adding a z-axis rotation to the stars is the same as a 2D rotation. Add this line of code to the star creation loop (which assumes a five-pointed star):
//Set rotation, each star rotated a litle bit more than the other
currentStar.rotationZ = i*360/(NUMBER_OF_STARS*5);
The multiplication by the variable i subtlely rotates each star slightly more than the previous star. Add this in the timer function to start the slow clockwise rotation:
//Slow clockwise rotation
currentStar.rotationZ += 2;
You're done! The sample file Moving-Stars-3.fla contains this final version. For a bonus, you could hook up the rotation to be user-controlled by adding another slider and using the slider value instead of the "2" in the line above.
This tutorial used the z-property of display objects and animated objects with a timer-based function. For another tutorial about 3D in Flash and ActionScript 3, read my companion article, 3D view controller in Flash using ActionScript 3.
Also see the following sections in the online documentation which discuss 3D:

This work is licensed under a Creative Commons Attribution-Noncommercial 3.0 Unported License.
| 04/23/2012 | Auto-Save and Auto-Recovery |
|---|---|
| 04/23/2012 | Open hyperlinks in new window/tab/pop-up ? |
| 04/21/2012 | PNG transparencies glitched |
| 04/01/2010 | Workaround for JSFL shape selection bug? |
| 02/13/2012 | Randomize an array |
|---|---|
| 02/11/2012 | How to create a Facebook fan page with Flash |
| 02/08/2012 | Digital Clock |
| 01/18/2012 | Recording webcam video & audio in a flv file on local drive |