ActionScript.org Flash, Flex and ActionScript Resources - http://www.actionscript.org/resources
3D Menu in Flash CS3/CS4 using Flash Player 10 3D API
http://www.actionscript.org/resources/articles/833/1/3D-Menu-in-Flash-CS3CS4-using-Flash-Player-10-3D-API/Page1.html
Jesse Nicholson
I'm a flash developer in Ontario Canada, I run my own business and I love pushing the limits of flash and exploring the latest developments from Adobe. I have developed a way to author flash 10 in the flash CS3 IDE and would like to begin posting articles on working with the new features (specifically 3d). 
By Jesse Nicholson
Published on November 14, 2008
 
In this tutorial I'm going to explain how to create a 3D menu using the Flash Player 10 3D API. People with CS3 can do this too!

Setup
Before getting started, if you are interested, drop your email address in at my tutorials page and I will notify you by email whenever I add a new tutorial to Actionscript.org. You can do this at http://www.ascensionsystems.ca/tutorials/.

The first thing you'll need to do is set up your stage and library for this tutorial. First, set your stage width to 1000 and height to 400. Create 6 buttons and place them on the stage and give them instance names of b1, b2, b3, b4, b5, and b6.

Create 6 unique items/images you would like to be in the menu. Below is the example you're going to be recreating.



( You need flash player 10 installed to view it correctly. See it in a new window here).

Anyway moving along.

The last thing that you need to do for setup is; -Go into the library -Set the class names for each of the 6 unique menu items you create to s1, s2, s3, s4, s5 and s6.

A note to people using CS3: Go to http://www.ascensionsystems.ca/tutorials/watch/fp10authoring/fp10flashcs3.html to view a video tutorial on how to configure flash CS3 to publish flash player 10 content. This will enable you to follow along with this tutorial. If you can, go to Adobe's website and download the CS4 trial.

You can download the source files for this project at http://www.ascensionsystems.ca/3DMenu.rar

ALSO FOR THIS TUTORIAL you are going to need two custom classes. Tweener and SimpleZSorter. The links are:

SimpleZSorter: http://code.google.com/p/leebrimelow/
Tweener: http://code.google.com/p/tweener/downloads/list (Make sure you get the AS3 one)

If you don't know how to use custom classes in Flash check out http://gotoandlearn.com/play?id=30 for a video tutorial by Lee Brimelow.

That's it for setup, now it's all code from here, YAY... not.

Code Part 1

Once you have your project all set up, all there is left to do is code. I'm just basically going to copy and paste in blocks of code and explain if/where necessary. It's all pretty straight forward. Please be advised that everything I reference as a "placement value" are values you're going to most likely need to change to suit your specific version of this project, so keep them in mind! Here we go.


[as]import caurina.transitions.*;
import com.theflashblog.fp10.SimpleZSorter;
import flash.filters.BlurFilter;
var myFilter1:BlurFilter = new BlurFilter(0,0,1);
var myFilter2:BlurFilter = new BlurFilter(0,0,1);
var myFilter3:BlurFilter = new BlurFilter(0,0,1);
var myFilter4:BlurFilter = new BlurFilter(0,0,1);
var myFilter5:BlurFilter = new BlurFilter(0,0,1);
var myFilter6:BlurFilter = new BlurFilter(0,0,1);
var mySpace:Sprite = new Sprite();
addChild(mySpace);
mySpace.x = 450;//Code tag this value it's a placement value
mySpace.y = 200;//Code tag this value it's a placement value[/as]



Okay so we start by importing Tweener, SimpleZSorter and the BlurFilter class. We then create 6 blur filters with values of 0,0,1 (blurX/blurY/Quality) and then create a sprite called mySpace.

***NOTE*** if you are using the CS3 workaround from my website you must type-class mySpace as a MovieClip and not a Sprite

You add the new sprite to the display list and then set it's x and y coordinates according to the code example. These coordinates are one of the "placement values" I mentioned before and will most likely need to be adjusted for your movie put a code tag beside these.

The next thing we're going to do is call in the six menu items you created from the library, instantiate them and then add some event listeners and set the button mode. I'm going to paste the code in the next page.


Code Part 2 - Instnatiating the clips in the library

Okay so it goes a little something like this:

[as]var f1:s1 = new s1();//Instantiate your first menu item
var f2:s2 = new s2();//Instantiate your second menu item
var f3:s3 = new s3();//Instantiate your third menu item
var f4:s4 = new s4();//Instantiate your fourth menu item
var f5:s5 = new s5();//Instantiate your fifth menu item
var f6:s6 = new s6();//Instantiate your sixth menu item
//
f1.z = 1000;//This item is a placement value and will need adjustment - this sets the depth (in space) of the clip)
f2.z = 3000;//This item is a placement value and will need adjustment - this sets the depth (in space) of the clip)
f3.z = 5000;//This item is a placement value and will need adjustment - this sets the depth (in space) of the clip)
f4.z = 7000;//This item is a placement value and will need adjustment - this sets the depth (in space) of the clip)
f5.z = 9000;//This item is a placement value and will need adjustment - this sets the depth (in space) of the clip)
f6.z = 11000;//This item is a placement value and will need adjustment - this sets the depth (in space) of the clip)
//
f1.x = 450;//This is a placment value and will need adjustement
f2.x = 450;//This is a placment value and will need adjustement
f3.x = 450;//This is a placment value and will need adjustement
f4.x = 450;//This is a placment value and will need adjustement
f5.x = 450;//This is a placment value and will need adjustement
f6.x = 450;//This is a placment value and will need adjustement
//
f1.y = 460;//This is a placment value and will need adjustement
f2.y = 450;//This is a placment value and will need adjustement
f3.y = 450;//This is a placment value and will need adjustement
f4.y = 450;//This is a placment value and will need adjustement
f5.y = 450;//This is a placment value and will need adjustement
f6.y = 450;//This is a placment value and will need adjustement
//
//Set the button modes for the menu items
f1.buttonMode = true;
f2.buttonMode = true;
f3.buttonMode = true;
f4.buttonMode = true;
f5.buttonMode = true;
f6.buttonMode = true;
//
//Set the button modes for the buttons
b1.buttonMode = true;
b2.buttonMode = true;
b3.buttonMode = true;
b4.buttonMode = true;
b5.buttonMode = true;
b6.buttonMode = true;
//
//Set the event listeners for the menu buttons
f1.addEventListener(MouseEvent.CLICK, moveCam);
f2.addEventListener(MouseEvent.CLICK, moveCam);
f3.addEventListener(MouseEvent.CLICK, moveCam);
f4.addEventListener(MouseEvent.CLICK, moveCam);
f5.addEventListener(MouseEvent.CLICK, moveCam);
f6.addEventListener(MouseEvent.CLICK, moveCam);
//
//add the menu items to the display list as a child of the mySpace Sprite/MovieClip
mySpace.addChild(f1);
mySpace.addChild(f2);
mySpace.addChild(f3);
mySpace.addChild(f4);
mySpace.addChild(f5);
mySpace.addChild(f6);[/as]



Okay so that code is pretty self-explanitory. You instiated all of your menu items and then added a click event listener for a function we're going to write in a bit and then added it to the display list. Moving right along...


Code Part 3 - Event Listeners

Okay basically this part is all event listeners. We're going to add event listeners to all of the bottons for a roll over event, a roll out event, and a click event. The rollover/rollout events are to just kind of jitter or slightly animate the menu to add to the interactivity of the whole scene. Also we're going to add an event listener to the stage to listen for the mouse wheel, as well as add an ENTER_FRAME event to the mySpace Sprite/MovieClip. All functions referenced in these event handlers are not yet written. That part is next. Pretty straight forward code here.

[as]stage.addEventListener(MouseEvent.MOUSE_WHEEL, travelSpace);
mySpace.addEventListener(Event.ENTER_FRAME, updatePos);
//
b1.addEventListener(MouseEvent.MOUSE_OVER, bOver);
b1.addEventListener(MouseEvent.MOUSE_OUT, bOut);
b1.addEventListener(MouseEvent.CLICK, zipTo);
//
b2.addEventListener(MouseEvent.MOUSE_OVER, bOver);
b2.addEventListener(MouseEvent.MOUSE_OUT, bOut);
b2.addEventListener(MouseEvent.CLICK, zipTo);
//
b3.addEventListener(MouseEvent.MOUSE_OVER, bOver);
b3.addEventListener(MouseEvent.MOUSE_OUT, bOut);
b3.addEventListener(MouseEvent.CLICK, zipTo);
//
b4.addEventListener(MouseEvent.MOUSE_OVER, bOver);
b4.addEventListener(MouseEvent.MOUSE_OUT, bOut);
b4.addEventListener(MouseEvent.CLICK, zipTo);
//
b5.addEventListener(MouseEvent.MOUSE_OVER, bOver);
b5.addEventListener(MouseEvent.MOUSE_OUT, bOut);
b5.addEventListener(MouseEvent.CLICK, zipTo);
//
b6.addEventListener(MouseEvent.MOUSE_OVER, bOver);
b6.addEventListener(MouseEvent.MOUSE_OUT, bOut);
b6.addEventListener(MouseEvent.CLICK, zipTo);
//
//
Tweener.addTween(mySpace, {z:-f1.z, x:f1.x - 720, y:f1.y - 700, time:2});[/as]



The last part of the code is a tween using the tweener class. For those who don't know how to use tweener it's pretty simple. It goes like this Tweener.addTween(always) then bracket ( then the item you want to manipulate. from there you add in a comma, then a '{' bracket and define the properties you want to set. It's not like the flash Tween engine where you set the to and from values you just set the value you want Tweener to arrive at. For more information check out the tweener documentation at http://hosted.zeh.com.br/tweener/docs/en-us/.

***NOTE*** This tween is essential to proper display/appearance of the final product. IF YOU REMOVE THIS, you will need to significantly change the preset placement values I've been referencing the whole tutorial.


Code Part 4 - Functions (sub-part 1)

I've broken up the remainder of the code into two sections. I'll past in one part here and explain the three functions I list as necessary. The rest of the code will be on the final page. Of course I will also explain those functions as well. Lets get started.

[as]function moveCam(e:MouseEvent):void
{
 Tweener.addTween(mySpace, {z:-e.target.z, x:e.target.x - 720, y:e.target.y - 700, time:2});
}[/as]

This function is the function called when you click one of the menu items. The tweener event zooms the clicked object into focus by matching the parent clips Z property value to the child clips Z property value. The X and Y adjustments carry a pretty heavy offset. That's to have the menu move out to the left of the screen so it's zooming in/out in line and proportion to the rest of the items. You can certainly mess with the offset values to see what effect it has on your scene.

[as]function travelSpace(e:MouseEvent):void
{
 Tweener.addTween(mySpace, {z:mySpace.z - (e.delta * 400), time:2});
//
if(mySpace.z > -1000){
 Tweener.addTween(mySpace, {z:-1000, time:1});
}else if(mySpace.z < -11000){
 Tweener.addTween(mySpace, {z:-11000, time:1});
}
//
}[/as]


This function (travelSpace) is the one called when we roll the mouse wheel over the stage. It add's the value of the scroll, either positive or negative, to the Z property value of the parent mySpace clip by having tweener calculate the different between the parent clip's current Z position and that position PLUS the delta value multiplied by 400 (to give it a significant value).

[as]function zipTo(e:MouseEvent):void
{
 if(e.target == b1){
  Tweener.addTween(mySpace, {z:-f1.z, x:f1.x - 720, y:f1.y - 700, time:2});
 }else if(e.target == b2){
  Tweener.addTween(mySpace, {z:-f2.z, x:f2.x - 720, y:f2.y - 700, time:2});
 }else if(e.target == b3){
  Tweener.addTween(mySpace, {z:-f3.z, x:f3.x - 720, y:f3.y - 700, time:2});
 }else if(e.target == b4){
  Tweener.addTween(mySpace, {z:-f4.z, x:f4.x - 720, y:f4.y - 700, time:2});
 }else if(e.target == b5){
  Tweener.addTween(mySpace, {z:-f5.z, x:f5.x - 720, y:f5.y - 700, time:2});
 }else if(e.target == b6){
  Tweener.addTween(mySpace, {z:-f6.z, x:f6.x - 720, y:f6.y - 700, time:2});
 }
}[/as]

This last function (zipTo) is the function called when we click on one of the menu buttons. This function uses a compounded if statement to determine which item was clicked by comparing the event target (e.target) to the instance names of the buttons. Once the exact button is determined a tweener event is run to tween the selected menu item into focus. Again the offset in these tweens can be adjusted to your preference.


Code Part 5 - Functions (sub-part 2) FINAL PAGE YAY

The last three functions are the enter frame event to handle all of the filter updating for the depth of field simulation, and the rollover/rollout events for the menu buttons. Lets finish this;


[as]function updatePos(e:Event):void
{
 myFilter1.blurX = -(mySpace.z + f1.z) / 80;
 myFilter2.blurX = (mySpace.z + f2.z) / 80;
 myFilter3.blurX = (mySpace.z + f3.z) / 80;
 myFilter4.blurX = (mySpace.z + f4.z) / 80;
 myFilter5.blurX = (mySpace.z + f5.z) / 80;
 myFilter6.blurX = (mySpace.z + f6.z) / 80;
//
 myFilter1.blurY = myFilter1.blurX;
 myFilter2.blurY = myFilter2.blurX;
 myFilter3.blurY = myFilter3.blurX;
 myFilter4.blurY = myFilter4.blurX;
 myFilter5.blurY = myFilter5.blurX;
 myFilter6.blurY = myFilter6.blurX;
//
 f1.filters = [myFilter1];
 f2.filters = [myFilter2];
 f3.filters = [myFilter3];
 f4.filters = [myFilter4];
 f5.filters = [myFilter5];
 f6.filters = [myFilter6];
//
 SimpleZSorter.sortClips(mySpace);
}[/as]

The ENTER_FRAME function here uses some simple math to determine just how blurred each menu item should be. It works like this: it calculates the difference between where the parent clip is on the Z axis and where the children clips are on their Z axis. For the first item you put a '-' before the calculations so that the value returned is negative. That's because you're only ever going to see this item zoom in from behind the viewport, so you really only need to see it blur back in.

The SimpleZSorter class is great because it automatically sorts the depths of all items inside of the parent clip. That is, the depth as in the stage/display depth (child index), not the physical or Z depth. This keep items that are physically further away behind items that are physically closer (Z property). Great stuff.

[as]function bOver(e:MouseEvent):void
{
 if(e.target == b1){
  Tweener.addTween(b1, {x:753.1, time:1});
 }else if(e.target == b2){
  Tweener.addTween(b2, {x:808.8, time:1});
 }else if(e.target == b3){
  Tweener.addTween(b3, {x:881.2, time:1});
 }else if(e.target == b4){
  Tweener.addTween(b4, {x:925.9, time:1});
 }else if(e.target == b5){
  Tweener.addTween(b5, {x:796.7, time:1});
 }else if(e.target == b6){
  Tweener.addTween(b6, {x:845, time:1});
 }
}
//
function bOut(e:MouseEvent):void
{
 if(e.target == b1){
  Tweener.addTween(b1, {x:773.1, time:1});
 }else if(e.target == b2){
  Tweener.addTween(b2, {x:828.8, time:1});
 }else if(e.target == b3){
  Tweener.addTween(b3, {x:901.2, time:1});
 }else if(e.target == b4){
  Tweener.addTween(b4, {x:945.9, time:1});
 }else if(e.target == b5){
  Tweener.addTween(b5, {x:816.7, time:1});
 }else if(e.target == b6){
  Tweener.addTween(b6, {x:865, time:1});
 }
}[/as]



The bOver and bOut functions are pretty straight forward. Keep in mind that the values entered into the tweens in these functions are relative to your buttons exact positions on the stage. All you're doing here is determining which button you rolled over/off of and shifting it's X property by 20 pixels. So, for example in bOut if your b1's x property on the stage was 100, you would want that tween value to be x:100 because that tween is designed to return the button to it's original positions. Vise/versa for the bOver function.

Anyway once the code is done and you actually get to use this I hope you enjoy. All of my customers have loved it, it's quite a selling feature. I am chaging my website design in a couple of months so I don't care if people do something similar. I do encourage everyone to personalize this as much as possible. You can go really cookey and make the items kind of FLY/SWING in from the back right and into focus or even add a spin to the animations where the items rotate on their Y axis all kinds of stuff. This is just a kind of platform on which I suspect you'll improve and expand the functions. If you have any questions you can email me ascensionsystems@gmail.com and I'll be sure to bring the question back to the forum to address it in a post some place or another.