First impressions are very important on a Flash game portal; if your game doesn't grab the player in the first few seconds, they've got plenty of other games to choose from. As the menu is the first point of interface, anything you can do to make it less dull will help. In this tutorial we will create a menu that incorporates swapping depth, smooth roll over effects, and two different transition designs.
Final Result Preview
These are the two designs we will be working towards:
The first design will have the next screens transitioning in from different directions, depending on which option is clicked.
The second design transitions all screens in from the bottom: a more flexible choice if you have more than four options.
Introduction: What Makes It "Active"?
There are two main things that make this menu "active". The first is the roll over effects on the buttons: regardless of how much they have scaled when you roll out ,they scale down from that particular size (unlike a tween created on the timeline). The second is that the code of the second style is designed to be flexible and easy to extend for your own needs.
Step 1: Setting Up
The first thing we are going to need to create is a new Flash File (ActionScript 3.0). Set its width to 600px, its height to 300px, and the frames per second to 30. The background color can be left as white.
Now save the file; you can name it whatever you please, but I named mine menuBounce.fla
.
In the next section we will create the eight MovieClips used in the menu. For reference, here is a list of all the colors used throughout the tutorial:
- White – #FFFFFF (
0xffffff
) - Gold – #E8A317 (
0xe8a317
) - Light Gold – #FBB917 (
0xfbb917
) - Blue – #1569C7 (
0x1569c7
) - Light Blue – #1389FF (
0x1389ff
) - Green – #347235 (
0x347235
) - Light Green – #3E8F1B (
0x3e8f1b
) - Red – #990000 (
0x990000
) - Light Red – #C10202 (
0xc10202
) - Matte Grey – #222222 (
0x222222
)
Step 2: Creating the MovieClips
To begin with we'll create the "backs" (the movie clips that will stand in for actual screens), but before we begin let’s turn on some very useful Flash features.
Right-click the stage and select Grid > Show Grid. By default it will create a 10px by 10px grid across the stage. Next, right-click the stage again and this time select Snapping > Snap to Grid.
Now we can start drawing! Select the Rectangle Tool and draw a 600x300px light gold rectangle. Then select this fill, right-click and choose Convert to Symbol. Name the MovieClip goldBack
, set the type to MovieClip and the registration to top-left.
Next right-click the MovieClip and select Duplicate three times to make three more copies of it. Now recolor them with light blue, light green and light red. Then name them blueBack
, greenBack
and redBack
, respectively.
To finish off the backs we should add some sort of text inside each MovieClip: on goldBack write "PLAY", on blueBack write "INSTRUCTIONS", on greenBack write "OPTIONS", and on redBack write "CREDITS". Once you have written the text I would recommend breaking it apart until it becomes a fill (this removes the need to embed fonts and makes the transition look smoother). Your backs should look similar to the one below:
Now let's start on the clickable squares! Select the Rectangle Tool and draw a 100x100px light gold square. Select the fill, right-click and Convert to Symbol. Name the MovieClip goldSquare
, set the type to MovieClip and the registration to top-left. Now is the time to write text on the square, except this time instead of breaking the text apart leave it for now. Insert a keyframe and change the fill color to gold. Now break apart the text on both frames until they become fills.
Now right-click the MovieClip and choose Duplicate Symbol three times. Then repeat the same process from before for the other three colors, naming the MovieClips blueSquare
, greenSquare
and redSquare
, respectively. Your squares should look similar to the one below:
Step 3: Positioning the MovieClips
Begin by deleting everything off the stage. Then go to Insert > New Symbol. Name it menuBounceMC
, set the type to MovieClip, the registration to the top-left and export it as MenuBounceMC
.
Now drag all the backs from the library into it and position them in the following way:
- goldBack: (-600,0)
- blueBack: (0,-300)
- greenBack: (0,300)
- redBack: (600, 0)
If you are going to use the one direction design then position all four of the backs at one of those positions. I used (0, 300).
Now drag all of the squares from the library into the MovieClip and positon them in the following way:
- goldSquare: (120,150)
- blueSquare: (240,150)
- greenSquare: (360,150)
- redSquare: (480, 150)
The last thing we have to do before we begin coding is assign the instance names. Set the instance names for the squares as square0
, square1
, square2
, square3
, starting from the left. Next set the instance names for the backs according to the corresponding with the square of the same color. So goldBack
would get the instance name back0
because the goldSquare
has the instance name square0
.
Step 4: Setting Up the Classes
Now that we are finished creating and positioning the MovieClips we can begin to set up the two classes that we will use.
First go to your Flash file’s Properties and set its class to MenuBounce; then, create a new ActionScript 3.0 file and save it as MenuBounce.as
.
Now copy the following code into it; I will explain it after:
package{ import flash.display.MovieClip; import flash.events.Event; public class MenuBounce extends MovieClip{ public var menuBounceMC:MenuBounceMC = new MenuBounceMC(); public function MenuBounce(){ addChild(menuBounceMC); } } }
This is a basic document class to which we've added a little extra code that creates an instance of MenuBounceMC and adds it to the stage.
Now create a new ActionScript 3.0 file and save it as MenuBounceMC.as
. Now copy the following code into it so we can set it up.
package{ import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; public class MenuBounceMC extends MovieClip{ public var activeSquare:MovieClip; public var activeBack:MovieClip; public var squaresArray:Array = new Array(); public var backsArray:Array = new Array(); public var speed:Number = 20; public function MenuBounceMC(){ } } }
Each variable has a specific purpose:
-
activeSquare
: Which square is being rolled over -
activeBack
: Which back has been selected to move -
squaresArray
: An array containing all of the square MovieClips -
backsArray
: An array containing all of the back MovieClips -
speed
: How many pixels the backs are moved by every frame
All of those variables have been set, with the exception of topSquare
(which is set in other functions) and the arrays. So we must push all of the MovieClips onto the array. Add the following lines inside the constructor:
squaresArray = [square0, square1, square2, square3]; backsArray = [back0, back1, back2, back3];
However this method can be a little bit tedious if you are going to use a high number of MovieClips in the menu - say 50. An alternative would be to create the MovieClips completely through code and push them when you add them to the menu. But for our purpose of using only eight MovieClips it works fine.
The last set of things we need to add to complete the setup is our event listeners, which will trigger all of the transitions and roll over effects. Add these lines below the push()
lines.
addEventListener(MouseEvent.MOUSE_OVER, bounceOver); addEventListener(MouseEvent.MOUSE_OUT, bounceOut); addEventListener(MouseEvent.CLICK, bounceClick); addEventListener(Event.ENTER_FRAME, bounceUpdate);
Step 5: Creating the MouseEvent Handlers
Let's start off by creating the three easier functions:
public function bounceOver(event:MouseEvent):void { } public function bounceOut(event:MouseEvent):void { } public function bounceClick(event:MouseEvent):void { }
Inside the bounceOver()
function start by adding an if-statement to make sure that no back is currently "active" - that is, transitioning in, transitioning out, or sitting on top:
if(activeBack == null){ }
The remainder of all the code in the bounceOver()
function will be written inside that if-statement. Now we figure out whether the object rolled over (the event.target
) is a square, by checking whether it's in the squaresArray[]
:
if(squaresArray.indexOf(event.target) != -1){ }
Assuming it is, we do real meat of the function:
activeSquare = event.target as MovieClip; activeSquare.gotoAndStop(2); setChildIndex(activeSquare, numChildren - 1);
First we set the variable activeSquare
to point to the square in question. After that, we pause this square's animation on the second frame, which displays its "rollover" image. Lastly we move the sprite to be on top of everything else, using setChildIndex().
We now move into the bounceOut()
function. This time, we start by checking whether the object from which the mouse is being rolled out is the currently active square:
if(event.target == activeSquare){ }
Inside the if-block add the following code; it pauses the square's animation on the first frame again, and then sets activeSquare back to null
so that we can roll over another:
activeSquare.gotoAndStop(1); activeSquare = null;
Then go to the bounceClick()
function. This function will be used to initiate all the transitions. Start off by checking whether there's already an active back:
if(activeBack == null){ }
This prevents the user from clicking another square during a transition. If there is an active back, then a click should undo this, so that we can click another square:
if(activeBack == null){ }else{ activeBack = null; }
Assuming there's no currently active back, once again add an if-block to check whether the object clicked was a square:
if(activeBack == null){ if(squaresArray.indexOf(event.target) != -1){ } }else{ activeBack = null; }
If the user did click a square, we must set the corresponding back as the "active" back. Since the index of each item in backsArray[]
matches the index of each item in squaresArray
, this is simple:
if(activeBack == null){ if(squaresArray.indexOf(event.target) != -1){ activeBack = backsArray[squaresArray.indexOf(event.target)] as MovieClip; } }else{ activeBack = null; }
Now we just need to move the currently active back so that it is on top of everything else:
if(activeBack == null){ if(squaresArray.indexOf(event.target) != -1){ activeBack = backsArray[squaresArray.indexOf(event.target)] as MovieClip; setChildIndex(activeBack, numChildren - 1); } }else{ activeBack = null; }
Step 6: Creating the Final Event Handler
This is the last function we are going to create. Let's begin by adding the scaling effect for when a square is rolled over or out:
public function bounceUpdate(event:Event):void { for each (var square in squaresArray) { if(square == activeSquare){ if(square.scaleX <= 1.5){ square.scaleX +=0.05; square.scaleY +=0.05; } }else{ if(square.scaleX >= 1){ square.scaleX -=0.05; square.scaleY -=0.05; } } } }
Here, we've created a for-each loop to cycle through every square in the array and check whether it's the currently active square. If it is, we scale it up until it is greater or equal to 1.5 times its regular size ; if it's not, we scale it down until it's back at its regular size. (Technically, this code could allow it to be very slightly smaller than its regular size, but this is unnoticeable in practice.)
Now this is where some of you will go your seperate ways; if you are creating Design 1 go to Step 7a, and if you are creating Design 2 go to Step 7b.
Step 7a: Finishing Design 1
Congratulations you have chosen design 1! This design is simple and easy to follow - assuming you have exactly four squares and backs. Any more, and it becomes a mess to maintain.
We're going to use a long series of nested if-else statements - very messy, I know. But let me tell you the reasoning behind this! Each back has a different starting position and transition direction. In a nutshell, you can't use a single for-loop to move all the MovieClips unless you have one if statement to check which back is moving, another to set the axis of movement (x or y), and a third to set the speed (positive or negative). Okay, we could store all this information in properties of the squares or something like that, but I think this is one approach where "Keep It Simple, Stupid" applies.
if(activeBack == back0){ if(back0.x < 0){ back0.x += speed; } }else{ if(back0.x > -600){ back0.x -= speed; } } if(activeBack == back1){ if(back1.y < 0){ back1.y += speed; } }else{ if(back1.y > -300){ back1.y -= speed; } } if(activeBack == back2){ if(back2.y > 0){ back2.y -= speed; } }else{ if(back2.y < 300){ back2.y += speed; } } if(activeBack == back3){ if(back3.x > 0){ back3.x -= speed; } }else{ if(back3.x < 600){ back3.x += speed; } }
The code's easy to understand; it looks at each back and moves it onto the stage or off the stage, in the correct direction, depending on whether or not it's active.
Step 7b: Finishing Design 2
Congratulations you have chosen Design 2! This design is far more flexibile and makes things a lot easier in terms of adding more backs and using less code. For this design we will use another for-each loop to examine each back in the backsArray
:
for each (var back in backsArray){ if(back == activeBack){ if(back.y > 0){ back.y -= speed; } }else{ if(back.y < 300){ back.y += speed; } } }
Now this should be pretty easy to understand. It cycles through the backs and checks each to see whether it's active. If it is, the code moves it upwards onto the stage, and stops moving it once it is completely on (i.e. once it's at y=0
or higher). If the back isn't active, the code moves it back down until it reaches its starting position.
Conclusion
Here's a challenge: given 16 squares (and 16 backs), can you make it so that Squares 1, 5, 9, and 13 make the corresponding backs transition in from the left, Squares 2, 6, 10, and 14 make them transition in from the top, and so on? You'll need to combine the two approaches, as well as check the position of the active square/back in its array.
Thanks for taking the time to read through this tutorial. I hope you enjoyed the finished product and learned something about making active, flexible menus!
Comments