Flipping a two-sided card in 3D is one of the most popular Flash effects. Depth-sorting for such a card, that is, determining which side should be visible for a given rotation, is very easy if a card is near the projection center. (The projection center is usually located at the center of the Stage.) In that case, the angle of rotation is all we need to determine which side is visible. The issue becomes much more complicated if a card is located not near the projection center. Click the screen shot below to open an Flash movie in a new window:
- Download all source files corresponding to the applet above: rotator.zip
The Idea Behind Depth-Sorting of a Card
Since a card has no thickness, the postion of the front side and the back side are the same. Thus, sorting with respect to the z-coordinate (or the distance from the observer) of sides' midpoints will not work. Instead, in our custom CardRotator class, we use a normal vector to our card and the dot product of the normal vector with the vector pointing toward the observer. The dot product is non-negative for as long as the angle between these two vectors is less than 90 degrees. It is negative otherwise. So as long as the dot product is non-negative, the front side is visible. Here is the picture that illustrates the idea:
The dot product of two vectors v = (v.x,v.y,v.z) and w = (w.x,w.y,w.z), v*w, is very easy to calculate. Namely:
v*w = v.x*w.x + v.y*w.y + v.z*w.z
The biggest challenge is in translating local positions with respect to 'card' to global positions with respect to the Stage. We accomplish that by using the getRelativeMatrix3D method of the Transform class. See the CardRotator class in the zip package for details.
The CardRotator Class
What you see in the applet linked from the screen shot above, are three instances, card1, card2, card3, of CardRotator class, one for each card.
The CardRotator class extends Sprite. Its constructor, evoked with the keyword 'new', takes four parameters, two optional:
d:String = "vertical",r:String = "corner")
The first two parameters are the DisplayObjects that provide the front and the back of the instance of CardRotator created by the constructor; that is, the front and back of our 'card'.
The third parameter is a String, "vertical" or "horizontal", (default "vertical"). Based on the value of this parameter the back side of the card is initially rotated by 180 degrees about the y-axis or about the x-axis. That will give the correct orientation of the back of a card after vertical or, respectively, horizontal rotation. The last parameter is a String, "center" or "corner" (default "corner"). The parameter contains information about the registration points of the DisplayObjects passed to the contructor: "corner" if the registration points are in the upper left corner, and "center" if the registration points are in the center.
Both DisplayObjects passed to the constructor should have the same width and height.
var card:CardRotator = new CardRotator(somemovieclip1,somemovieclip2);
The CardRotator class has three public pseudo-properties: rotX,rotY,rotZ that give the rotations of an instance about the x-, y-, and z- axis, respectively:
In the applet, we manipulate card1.rotY,card2.rotX on ENTER_FRAME for the first two cards. We create a tween for card3.rotX for the third card. See rotator.fla in the zip package for simple, well-commented code demonstrating how to use the CardRotator class.
For Z-sorting of non-flat objects, see our tutorial: Z-Sorting and Perspective Projection in AS3 and Flash Player 10