In this introductory tutorial, we use only a few basic 3D features supported by Flash Player 10. Yet, we are able to accomplish effects that before required a lot of work. In the expanded AS3 that targets Player 10, every Display Object is embeded in the 3D space. Besides the old x and y axes, we have now the z axis perpendicular to the screen. Each Display Object can be assigned the z coordinate as well as x and y coordinates. Moreover, each Display Object can be rotated in 3D about each of the axes with perspective distortion created automatically.
On page 4, we explain the new 3D coordinate system and perspective distortion. Let's begin by looking at a few examples and the code behind them. On this page, we rotate an image in 3D; on the next page, we flip a playing card; that is, we manipulate a two-sided bitmap.
Download
- A zip file t1player10.zip
The zip file linked above contains all the 'as' and 'jpg' files related to examples in this tutorial.
To open the appplet, click on the appropriate link below the picture. If you have Flash Player 10 Beta 1 (relased May 15), click on the first link. If you have Flash Player 10 Beta 2 (released July 2), click on the second link.
Flash Player 10 Beta 1 version of the applet. Flash Player 10 Beta 2 version of the applet.
Note: The 'as' file in the zip file corresponding to the applet above is 'RotateBitmap.as'. We used Flex 3 SDK to compile 'RotateBitmap.as' into 'RotateBitmap.swf' file. We created the html 'wrapper', 'RotateBitmap.html' using Flash CS3. Namely, we created and published an empty movie 'RotateBitmap.fla' with the Stage dimensions and the background color corresponding to those specified in 'RotateBitmap.as'. Then we deleted the empty 'swf' file and substituted it by the 'swf' compiled by the Flex compiler. We also used Flash CS3 ActionScript editor to type the code in all 'as' files in this tutorial. You can use any generic text editor.
Here is the code behind the applet. We keep our comments in the form of comments within the code to keep the flow intact.
package {
import flash.display.*;
import flash.text.*;
import flash.events.*;
/*
We need the mata tag below that sets the properties of our movie because we are using the Flex compiler.
If we had the Flash IDE, we would set these properties in the 'fla' file as usual.
*/
// SWF Metadata
[SWF(width="450", height="450", backgroundColor="#CCCCCC", framerate="30")]
public class RotateBitmap extends MovieClip {
/*
We are using the 'embed' tag supported by Flex to embed our image into the 'swf' file.
In the Flash IDE, we would import the image to the Library and Link it to AS3.
*/
[Embed(source="Redjack.jpg", mimeType="image/jpeg")]
public var Img1:Class;
//Nothing new here. We are declaring our variables.
private var bdFirst:BitmapData;
private var bmFirst:Bitmap;
private var card:Sprite;
private var spBoard:Sprite;
private var tfTitle:TextField;
private var tfAuthor:TextField;
private var shBack:Shape;
private var doRotate:Boolean;
private var prevX:Number;
private var prevY:Number;
/*
In the class constructor below, we define a Sprite, 'spBoard', that will hold
the image and the black background. We need it it as a separate entity
as we want it to respond to the MOUSE_MOVE event. We define a Sprite, 'card',
that holds the Bitmap, 'bmFirst' corresponding to our 120px by 172px image. The reason we need 'card' is to
position the image in it in such a way that the registration point of 'card' in in its center.
Why? Because the new and simple 'rotationX' and 'rotationY' properties that we are going to use
to rotate 'card' rotate a Display Object about its registration point.
*/
//The class constructor.
public function RotateBitmap(){
spBoard=new Sprite();
addChild(spBoard);
shBack=new Shape();
spBoard.addChild(shBack);
card=new Sprite();
spBoard.addChild(card);
//Note we are setting the x and y coordinates only even though 'card' has
//the z coordinate as well. The value is automatically set to the default 0.
card.x=225;
card.y=200;
bdFirst=new Img1().bitmapData;
bmFirst=new Bitmap(bdFirst);
card.addChild(bmFirst);
bmFirst.x=-60;
bmFirst.y=-86;
this.transform.perspectiveProjection.fieldOfView = 70;
doRotate=false;
drawBack();
setUpListeners();
setUpText();
}
//End of the class constructor.
/*
In the constructor, we used the new AS3 class 'perspectiveProjection' and its property 'fieldOfView'.
The values of this property that range from 0 to 180 determine the angle, in degrees, of our 'view frustrum'.
(See page 4.) In short, the value determines how much distortion for perspective we have: a higher
value corresponds to more distortion.
*/
//We are drawing the black background. Nothing new here.
private function drawBack():void {
shBack.graphics.lineStyle(1,0x666666);
shBack.graphics.beginFill(0x000000);
shBack.graphics.drawRect(40,40,370,320);
shBack.graphics.endFill();
}
//We are assigning listeners to 'spBoard'. Nothing new here.
private function setUpListeners():void {
spBoard.addEventListener(MouseEvent.ROLL_OUT,boardOut);
spBoard.addEventListener(MouseEvent.MOUSE_MOVE,boardMove);
spBoard.addEventListener(MouseEvent.MOUSE_DOWN,boardDown);
spBoard.addEventListener(MouseEvent.MOUSE_UP,boardUp);
}
private function boardOut(e:MouseEvent):void {
doRotate=false;
}
private function boardDown(e:MouseEvent):void {
prevX=spBoard.mouseX;
prevY=spBoard.mouseY;
doRotate=true;
}
private function boardUp(e:MouseEvent):void {
doRotate=false;
}
/*
In the listener 'boardMove' is where we use the new properties available in Player 10
to rotate the card. Namely, we use the properties 'rotationX' and 'rotationY'
that now every Display Object has. Those read-write properties represent
the rotation of the object in 3D about the x and the y axis, repectively.
(Relative to the object's registration point.)
The values are in degrees, thus we take everything modulo 360 degrees.
Note that we read the properties and store them in local variables 'picRotX'
and 'picRotY'. Then we assign new values of rotations based on the current positon of the mouse.
All of that happens provided the user is moving the image; that is, when our 'doRotate' Boolean variable
equals 'true'. Each object has 'rotationZ' property as well but we are not
using it in this applet.
*/
private function boardMove(e:MouseEvent):void {
var locX:Number=prevX;
var locY:Number=prevY;
if(doRotate){
var picRotX:Number=card.rotationX;
var picRotY:Number=card.rotationY;
prevX=spBoard.mouseX;
prevY=spBoard.mouseY;
card.rotationY=(picRotY+(prevX-locX))%360;
card.rotationX=(picRotX+1.5*(prevY-locY))%360;
e.updateAfterEvent();
}
}
//We are formatting and positioning text fields. Nothing new here.
//If we had Flash IDE, we would create them as static fields on the Stage.
private function setUpText():void {
...........................
}
Note how easy it is now to obtain basic texture mapping by simply manipulating the 'rotationX' and 'rotationY' properties. No more slicing, dicing, or triangulating. Much more sophisticated rotation effects and texture mappings can be obtained using the new 'Matrix3D' class and the new 'drawTriangles' method of the Graphics object. We will discuss those methods in our upcoming tutorials.
On next page, we use the same technique to flip a playing card; that is, to rotate a two-sided bitmap. Again, all we use are the rotationX and rotationY properties.











