logo
468x60-2-495


  • Home
  • Privacy Policy
  • About
search
May 28, 2012 Posted on May 28, 2012 in Hints and Tips | 10 comments

Create a Facebook Graph API App in Flash: Generating Embed Code – Tuts+ Premium

In this second part of this mini-series of Premium tutorials, you’ll learn how to use Flash to build a Facebook Graph API application that can create slideshows for your public pages. This second part covers loading album information, and generating and displaying the embed code.


Premium Preview

Click to try the app on Facebook.

Welcome back to our Facebook Flash application tutorial! In this part, we’re going to continue building the Flash interface for building the Facebook slider. The interface will handle choosing an album for displaying in a Facebook tab.

This application allows you to select a Facebook album or event list from one of your public pages (not your personal profile) and turn it into a slideshow for your page tab. When the users enter your page, they will see photos from your chosen album, with your photo title and description, or event name, date and invites (for the Event tab).

In future parts of this series, we’ll create the actual Flash slider that does just that; meanwhile we’ll create the generator for the embed code that will reside at the Facebook application URL.

You’ll need to be logged in to Facebook in order to see this demo: https://apps.facebook.com/activetuts_tabmaker/


Read the Full Tutorial

Premium members can access the full tutorial right away!

If you’re not yet a Premium member, you can still read the first few steps for free.


Tuts+ Premium Membership

We run a Premium membership system which periodically gives members access to extra tutorials, like this one, from across the whole Tuts+ network. If you’re a Premium member, you can log in and read the tutorial. If you’re not a member, you can of course join today!

Also, don’t forget to follow @envatoactive on twitter, circle us on Google+, like us on Facebook, and grab the Activetuts+ RSS Feed to stay up to date with the latest tutorials and articles.



View full post on Activetuts+

Mar 10, 2012 Posted on Mar 10, 2012 in Hints and Tips | 10 comments

Create Flash Screen Transition Effects Entirely With Code

Flash games are very much the bread and butter of indie pop-nerd culture. If you consider the slices of bread the menu and the game itself, what is left? The butter – the very substance that makes the bread taste that much more delicious. And in terms of a Flash game, what comes in between menus and games are the transitions!


Final Result Preview

This is an example pattern of the transition effect that we will be working towards:


Step 1: Setting Up

Per usual we need to create a new Flash File (ActionScript 3.0). Set its width to 400px, its height to 200px, and the frame rate to 30fps. The background color can be left as the default. Save the file; it can be named whatever you please. I named mine Transitions.fla.

Next we need to create a document class. Go to your Flash file’s properties and set its class to Transitions. Then create the document class:

package {
	import flash.display.*;
	import flash.events.*;

	public class Transitions extends MovieClip {
		static public var val:Number = new Number();
		static public var transitionAttached:Boolean = new Boolean();
		public function Transitions() {
			val = 0;
			transitionAttached = false;
		}
	}
}

The code just introduced two variables. The first will be used to select the effect’s pattern, and the second will be used to check against having multiple instances of the effect on the stage.


Step 2: Creating the Square Sprite

Our next step is to create the sprite that will be used as each square for the transition. Create a new class and save it as Square.as:

package{
	import flash.display.*;
	import flash.events.*;

	public class Square extends Sprite{
		public var squareShape:Shape = new Shape();
		public function Square(){

		}
	}
}

We use the squareShape variable to draw our shape inside the Sprite. Draw a rectangle 40px by 40px (Which is the full size) and set its scale to 0.1, a tenth of its size – this will aid us in the effect later:

addChild(squareShape);
squareShape.graphics.beginFill(0x000000,1);
squareShape.graphics.drawRect(-20,-20,40,40);
squareShape.graphics.endFill();
this.scaleX = 0.1;
this.scaleY = 0.1;

Step 3: Creating the Effect

Create another new class for the effect itself. Once we are finished, adding the effect to the stage will be very simple:

package{
	import flash.display.*;
	import flash.events.*;
	import flash.utils.*;

	public class FadeEffect extends Sprite{
		public var currentFadeOut:int = 00;
		public var currentSquares:int = 01;
		public var pauseTime:int = 01;
		public var tempNum:int = 00;
		public var fading:String = "in";
		public var fadeinTimer:Timer = new Timer(100);
		public var fadeoutTimer:Timer = new Timer(100);
		public var fadeArray:Array = [
                       //top
                       [[01,01,01,01,01,01,01,01,01,01],
                        [02,02,02,02,02,02,02,02,02,02],
                        [03,03,03,03,03,03,03,03,03,03],
                        [04,04,04,04,04,04,04,04,04,04],
                        [05,05,05,05,05,05,05,05,05,05]],
                       //bottom
                       [[05,05,05,05,05,05,05,05,05,05],
                        [04,04,04,04,04,04,04,04,04,04],
                        [03,03,03,03,03,03,03,03,03,03],
                        [02,02,02,02,02,02,02,02,02,02],
                        [01,01,01,01,01,01,01,01,01,01]]];
		public var squaresArray:Array = new Array();
		public function FadeEffect(){

		}
	}
}

You are probably thinking “that is a heck of a lot of variables, what all are they used for?”:

  • currentFadeOut - used as a check for tempNum to see how many squares are to be scaled
  • currentSquares - the current value indicating which squares should be attached and/or scaled
  • pauseTime - a simple integer to give a slight pause in between transitions and removing itself
  • tempNum - used to check what numbers in the array are to be scaled
  • fading - a string to check if the transition is fading in or out
  • fadeinTimer - a timer that is called to begin the fading in of the current value of currentSquares
  • fadeoutTimer - another timer that is called to begin the fading out of the current value of currentSquares
  • fadeArray - the 3D array that contains all the transition patterns
  • squaresArray - an array for the Square sprites

Our effect will begin by initiating an event listener for fadeInTimer and starting it. We also need to add an event listener to continuously scale all of the sprites to their correct sizes. Use the following code inside the constructor:

fadeinTimer.addEventListener("timer", fadeSquaresInTimer);
fadeinTimer.start();
addEventListener(Event.ENTER_FRAME, enterFrame);

The next step is to create those two event listeners. We will start with the easier of the two, the enterFrame function:

public function enterFrame(e:Event){
	for each(var s1 in squaresArray){
		tempNum+=1;
		if(fading=="in"){
			if(s1.scaleX<=1){
				s1.scaleX+=0.05;
				s1.scaleY+=0.05;
			}
		}else if(fading=="out"){
			if(tempNum<=currentFadeOut){
				if(s1.scaleX>=0.1){
				s1.scaleX-=0.05;
				s1.scaleY-=0.05;
				}else{
					if(s1.visible == true){
						s1.visible = false;
					}
				}
			}
		}
	}
	tempNum=00;
}

It may not make total sense right now, but this should help shed some light.

  • s1 is the instance name that will be given to the Squares when we create them in a later function.
  • They are added to an array called squaresArray to keep track of the number of them and we perform the same operation for every object in the array.
  • Next we increase tempNum (used in the fading out if-statement) which is used to scale the sqaures in the order that they were added to the array. This means it is not pattern dependant and will work with any pattern.

After that…

  • We check if fading is true or not.
  • If true, it scales all the squares up until they reach their full size (they begin scaling immediately after currentSquares increases).
  • Once it begins fading out things become a little trickier; we only scale down the squares that are lower than the current value of currentFadeOut (these are the ones that should be scaling, all others should remain at full scale until the value increases).
  • Once they have scaled down to a tenth of the size we make those squares invisible (they will be deleted with the whole effect).

It’s time to add the event listener for the timer:

public function fadeSquaresInTimer(e:Event){
	fadeSquaresIn(fadeArray[Transitions.val]);
	currentSquares+=1;
}

At first glance it looks less complicated, but you should notice that we are calling a function with the fadeArray as the parameter. Which pattern is selected from the array depends on what you set val equal to in the Transitions class; right now it should use the first pattern because val is set to 0.

The next step is to create the fadeSquaresIn function that is called from the previous timer:

public function fadeSquaresIn(s:Array){
	for (var row=0; row<s[0].length; row++) {
		for (var col=0; col<s.length; col++) {

		}
	}
}

First thing that we accomplish is iterating through the selected pattern. We start at row 1, colomn 1 and cycle through every colomn until the end of the row has been reached. Then we move onto the next row and repeat the process.

The next thing to do is compare the current item in the array to the value of currentSquares:

if(int(s[col][row]) == currentSquares){

}

If they are equivalent we add a square, position it accordingly, and push it onto the squaresArray so that it can be scaled:

var s1:Sprite = new Square();
s1.x = 20+(row*40);
s1.y = 20+(col*40);
addChild(s1);
squaresArray.push(s1);

We are almost done with this function, we just have to perform a check for when there are the same number of squares as there are items in the pattern. We do so by adding the following if-statement outside both for-loops:

if(squaresArray.length == (s[0].length * s.length)){
	fadeinTimer.stop();
	addEventListener(Event.ENTER_FRAME, pauseBetween);
}

Self explanatory – we stopped the timer and called an event listener for the pause between fading in and fading out. That function is used to initiate the fading out and may also be used to cause change in your game:

public function pauseBetween(e:Event){
	pauseTime+=1;
	if(pauseTime==60){
		currentSquares=01;
		fading="out";
		fadeoutTimer.addEventListener("timer", fadeSquaresOutTimer);
		fadeoutTimer.start();
		removeEventListener(Event.ENTER_FRAME, pauseBetween);
	}
}

We won’t spend much time on this function due to its simplicity. Here we increase the value of pauseTime, and once it equals 60 (meaning two seconds have passed) we set the value of currentSquares back to 1, set fading to "out" so that the squares can scale backwards, remove the listener for pauseBetween() itself, and add an event listener for this new function:

public function fadeSquaresOutTimer(e:Event){
	fadeSquaresOut(fadeArray[Transitions.val]);
	currentSquares+=1;
}

This works much like fadeSquaresInTimer(), though this time we are calling the function fadeSquaresOut():

public function fadeSquaresOut(s:Array){
	for (var row=0; row<s[0].length; row++) {
		for (var col=0; col<s.length; col++) {
			if(int(s[col][row]) == currentSquares){
				currentFadeOut+=1;
			}
		}
	}
}

We cycle through, but this time when we find an equivalent item we increase the value of currentFadeOut so that the next item in the squaresArray can begin fading out.

Almost finished now; all that’s left is to stop the timer and remove the effect. Add this if-statement outside of the two for-loops:

if(currentFadeOut == (s[0].length * s.length)){
	fadeoutTimer.stop();
	pauseTime=01;
	addEventListener(Event.ENTER_FRAME, delayedRemove);
}

This checks whether all of the items have begun fading out. If so, it then stops the timer, sets pauseTime back to 1 and adds an event listener for the function delayedRemove():

public function delayedRemove(e:Event){
	pauseTime+=1;
	if(pauseTime==30){
		Transitions.transitionAttached = false;
		removeEventListener(Event.ENTER_FRAME, delayedRemove);
		stage.removeChild(this);
	}
}

Like before we increase the value of pauseTime, and once it equals 30 (1 second) we set the boolean back to false so that the effect can be added once again. We remove this event listener and we remove this effect from the stage.


Step 4: Adding the Effect

Now comes the easy part. Add the following code inside the document class constructor to add the effect:

if(transitionAttached == false){
	transitionAttached = true;
	var f1:Sprite=new FadeEffect;
	stage.addChild(f1);
}

Step 5: Creating More Patterns

Feel free to create your own patterns! It’s extremely simple, just create a new 2D array inside the 3D array. Here is the array that I have created (just replace your 3D array with it). It includes 8 different transitions:

[//top
[[01,01,01,01,01,01,01,01,01,01],
[02,02,02,02,02,02,02,02,02,02],
[03,03,03,03,03,03,03,03,03,03],
[04,04,04,04,04,04,04,04,04,04],
[05,05,05,05,05,05,05,05,05,05]],
//bottom
[[05,05,05,05,05,05,05,05,05,05],
[04,04,04,04,04,04,04,04,04,04],
[03,03,03,03,03,03,03,03,03,03],
[02,02,02,02,02,02,02,02,02,02],
[01,01,01,01,01,01,01,01,01,01]],
//left
[[01,02,03,04,05,06,07,08,09,10],
[01,02,03,04,05,06,07,08,09,10],
[01,02,03,04,05,06,07,08,09,10],
[01,02,03,04,05,06,07,08,09,10],
[01,02,03,04,05,06,07,08,09,10]],
//right
[[10,09,08,07,06,05,04,03,02,01],
[10,09,08,07,06,05,04,03,02,01],
[10,09,08,07,06,05,04,03,02,01],
[10,09,08,07,06,05,04,03,02,01],
[10,09,08,07,06,05,04,03,02,01]],
//top-left
[[01,02,03,04,05,06,07,08,09,10],
[02,03,04,05,06,07,08,09,10,11],
[03,04,05,06,07,08,09,10,11,12],
[04,05,06,07,08,09,10,11,12,13],
[05,06,07,08,09,10,11,12,13,14]],
//top-right
[[10,09,08,07,06,05,04,03,02,01],
[11,10,09,08,07,06,05,04,03,02],
[12,11,10,09,08,07,06,05,04,03],
[13,12,11,10,09,08,07,06,05,04],
[14,13,12,11,10,09,08,07,06,05]],
//bottom-left
[[05,06,07,08,09,10,11,12,13,14],
[04,05,06,07,08,09,10,11,12,13],
[03,04,05,06,07,08,09,10,11,12],
[02,03,04,05,06,07,08,09,10,11],
[01,02,03,04,05,06,07,08,09,10]],
//bottom-right
[[14,13,12,11,10,09,08,07,06,05],
[13,12,11,10,09,08,07,06,05,04],
[12,11,10,09,08,07,06,05,04,03],
[11,10,09,08,07,06,05,03,03,02],
[10,09,08,07,06,05,04,03,02,01]]];

You can change the value of Transitions.val to choose another pattern – for example, if val is 3, the transition will sweep in from the right.


Conclusion

Thanks for taking the time to read this tutorial. If you have any questions please leave a comment below. And if you would like a challenge, try making the effect fade in with one pattern and fade out with an opposing one.



View full post on Activetuts+

Jan 10, 2012 Posted on Jan 10, 2012 in Hints and Tips | 10 comments

Create a Microphone-Controlled Flash Game: Code

This entry is part 2 of 2 in the series Create a Microphone-Controlled Flash Game

In this mini-series, we’re creating a spaceship game where the main control is via the microphone: shout louder to make the ship fly higher. So far, we’ve created all the required graphical elements for the game. Now, it’s time to work on our code. We’ve got a lot to do, so let’s get started!


Final Result Preview

For the purposes of keeping the tutorial simple, we have done no error checking for the existence of a microphone. This means that, if you do not have a microphone plugged in, turned on, and set up for use with Flash, the game won’t work: you’ll get an Error #1009. Check the comments in Player.as in the source files for information on how to deal with this.


A Small Note:

For some reason Flash Builder isn’t working perfectly. In particular, it’s ignoring code hinting – but, nevertheless, one should be able to follow the tutorial.


Project Setup

Don’t like ads? Download the screencast, or subscribe to Activetuts+ screencasts via iTunes!


Creating the Player

Don’t like ads? Download the screencast, or subscribe to Activetuts+ screencasts via iTunes!


Creating Space Objects

Don’t like ads? Download the screencast, or subscribe to Activetuts+ screencasts via iTunes!


Player Animation and Collision Response

Don’t like ads? Download the screencast, or subscribe to Activetuts+ screencasts via iTunes!


Setting Up Scores and Lives

Don’t like ads? Download the screencast, or subscribe to Activetuts+ screencasts via iTunes!


Creating Our Background

Don’t like ads? Download the screencast, or subscribe to Activetuts+ screencasts via iTunes!


Cleaning Up Our Game

Don’t like ads? Download the screencast, or subscribe to Activetuts+ screencasts via iTunes!


Creating the Game Over Screen

Don’t like ads? Download the screencast, or subscribe to Activetuts+ screencasts via iTunes!


Conclusion

Thank you for watching. It’s been a huge tutorial, and afterwards I would have liked to do some things differently:

  • First off the classes have just been added one by one, but it would have made more sense for the classes to be organised in packages.
  • Even though our project works fine, we do get some run time errors, which isn’t very neat.
  • Also, it’s pretty easy to get very far by saying nothing, and just sticking to the bottom of the screen.

Nevertheless, I hope you enjoyed this tutorial, and most importantly learned something from it.



View full post on Activetuts+

Nov 30, 2011 Posted on Nov 30, 2011 in Hints and Tips | 10 comments

Drawing Beautiful Components With Code – Made Easy

Most programmers have never touched design. If you have always wanted to beautiful graphics in your Flash projects but never knew how to use Adobe Photoshop or Illustrator, this tutorial is for you. Nice graphics can be created entirely with code. Drawing graphics for components with code even has a few advantages.

Prerequisites

This tutorial requires that you know how to perform basic tweens using Greensock’s TweenLite or TweenMax. You can download the latest version of TweenLite from the Greensock website. I will be using Flash CS5 Professional to complete this project. You may use any Flash IDE you’d like (such as FlashDevelop or FDT). It would also help to have a fair understanding of inheritance.

A Brief Introduction

Before we get started, let’s take a look at what we’ll be learning and why it’s important. When designing Flash applications there are many ways to generate graphics. You can use an external tool such as Adobe Illustrator or draw complex graphics with Adobe Photoshop. You can even use 3D utilities such as Cinema 4D to create eye-popping 3D bitmaps to import into Flash. These techniques are great for creating a well designed static application – static meaning not very dynamic, or in most cases, not dynamic at all.

If you use one of the above methods to generate graphics for Flash, you may find it a little difficult to resize the graphics without some loss of quality or, even worse, distortion. On the sunny side, you can import a vector file that was generated with Adobe Illustrator into your Flash application and scale the image infinitely without distorting the image – but when you want to change the overall ratio of the image, you will notice that your image becomes a little deformed.

What we are going to do today is learn how efficient it can be to draw our application’s graphics with code. We are going to create a beautiful animated button that is completely generated with ActionScript.

Step 1: Pros and Cons

Before we dig in, I’d like to discuss the importance of planning for your application and answering simple questions to decide whether to draw the graphics with code or by hand (e.g. with Adobe Photoshop). To help us answer the questions below, let’s first examine the pros and cons to drawing with code.

The Pros

  • Portability: Graphics that are written in code are easy to import into other projects since they exist as AS files. No need to copy and paste an image into a new Flash project or import the image into the library. Just import the appropriate classes.
  • Simplicity: Graphics drawn with code are done using vectors so they have a delicate and simplistic feel that is both nice to look at and light on the CPU.
  • Consistency: When you’d like to resize your graphics, they will not distort (unless this is the effect you are going for) and they will maintain quality as the are scaled. Bitmap images, for example, become pixelated as they are made larger or zoomed into. Vector images don’t lose any quality or become pixelated. You can zoom into a vector image infinately and it will never lose quality. You can also be sure that your graphics still look amazing on screens with higher resolutions. As technology advances and new screen resolutions become available, your graphics are more likely to still be able to deliver a nice quality, as opposed to bitmap images that may not look so good.
  • Dynamics: Along with being able to resize and scale your graphics, you can also re-color segments of an image or component with very few lines of code. Changing properties of a graphic has never been so easy. What’s that you say? You no longer want the frame of your textfield to have rounded edges? No problem here. I’ll just change one line of code… and we’re good to go!
  • Precision: Although many graphics applications have features that simplify the positioning of graphical segments, you’ll find it easier to make modifications and position the contents of a graphic with code. You can easily center one segment inside another as the parent segment changes size or write an algorithm for handling how a segment will be displayed as it is resized. Hint, hint.

The Cons

  • Detail: Vector graphics drawn with code can be very detailed, but too much detail can have a dramatic effect on the performance of our applications. Although it may be possible, you won’t find me attempting to draw a detailed Spongebob Squarepants with code. Something like that should be done using Adobe Illustrator. Also vectors may not be able to be as detailed as a complex graphic drawn in Adobe Photoshop. Vectors tend to contain a smaller file size than your typical bitmap image. Vectors are connected points and bitmaps are represented pixel by pixel. But if you converted a bitmap into a vector image, the new vector’s file size would turn out to be a lot larger than the original bitmap image. This said, you won’t be able to paint an intricate portrait with code. Use Adobe Photoshop instead.
  • Limitations: There may be times where you’d like to use your graphics in different media. Sorry to say it but if you won’t be able to drop your dynamic graphics into that Java game you’ve been working on or that Objective-C application you just started. There are ways to render images using Flash but you will definately lose any dynamic capabilities provided by code.
  • Difficulty: Not to say that you will find it ridiculously difficult to draw graphics with code but depending on what you are drawing, you will most likely find the entire process a bit more complicated than using a software that is intended for this purpose. Don’t expect drawing with code to be an easy task. It really all depends on the expected outcome.

You should now find the following questions pretty easy to answer. There are three questions you need to ask yourself before you start your project:

  1. Does your application require graphics to be static or dynamic?

    1. Static
    2. Dynamic
  2. Do the graphics or components in your application need to be exclusive to Flash or be consistent across multiple platforms?

    1. Flash Platform only
    2. Multiple Platforms
  3. Is the graphic design of your application more detailed or quite simple?

    1. Relatively Simple (Basic Geometric Shapes)
    2. Moderate (Creative Designs with Simple Shapes)
    3. Intricate (Overly Complex Masterpieces)

Now examine your test results. If your test results closely resemble the results below, than the techniques we are getting ready to learn are for you?

  1. #2
  2. #1
  3. #1 or #2

If your results do not look like the results above, you may want to consider other methods. But for the rest of us, let’s proceed.

Step 2: Brainstorming

So here’s the scenario. A client has just asked us to create an animated button for their Flash site and AIR app. The button must be consistent with the science fiction theme of the client’s website. The button’s height can be a fixed size but the button must be able to accomodate for different widths. The button must have a toggle state that has a blatant difference between it’s active and inactive states. Finally the button must have an API that’s easy to work with.

Now that we know that we’ve got this themed component to create, we need to think about how we are going to go about creating it. Well, we know that we’re going to be drawing a lot of graphics with code so that the component will be easily and efficiently editable. Why not start off with a base class that will add high level functionality on top Flash’s drawing API?

We don’t want to draw graphics over and over again by writing the same lines of code so we’ll have a class with particular properties and methods specifically designed for reusing the code for us. We’ll extend this class to create the main shapes that we’ll need for our button.

Step 3: The Editable Shape Class

Now it’s time to get to it! Create a new class called EditableShape and add the following classes to the classpath.

import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Matrix;
import flash.display.BitmapData;
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;

Now create the class declaration. The class should extend the flash.display.Sprite class.

public class EditableShape extends Sprite {

Create the following variables(properties) before the class constructor.

private var _fillGradientType:String;
private var _fillSpreadMethod:String;
private var _fillColors:Array;
private var _fillAlphas:Array;
private var _fillRatios:Array;
private var _fillGradientWidth:Number;
private var _fillGradientHeight:Number;
private var _fillGradientRotation:Number;
private var _fillTx:Number;
private var _fillTy:Number;
private var _lineGradientType:String;
private var _lineSpreadMethod:String;
private var _lineThickness:Number;
private var _lineColors:Array;
private var _lineAlphas:Array;
private var _lineRatios:Array;
private var _lineGradientWidth:Number;
private var _lineGradientHeight:Number;
private var _lineGradientRotation:Number;
private var _lineTx:Number;
private var _lineTy:Number;

private var _width:Number;
private var _height:Number;
private var _matchGradientSize:Boolean;
private var _bitmapData:BitmapData;
private var _useBitmapFill:Boolean;
private var _pixelHinting:Boolean;

protected var fillGradientBox:Matrix;
protected var lineGradientBox:Matrix;

Within the class constructor add the following code and I’ll explain what we just did.

super();
_width = 100;
_height = 100;
_matchGradientSize = true;
_fillGradientType = "linear";
_fillSpreadMethod = "pad";
_fillColors = [ 0xFFFFFF, 0x000000 ];
_fillAlphas = [ 1, 1 ];
_fillRatios = [ 1, 255 ];
_fillGradientWidth = _width;
_fillGradientHeight = _height;
_fillGradientRotation = 0;
_fillTx = 0;
_fillTy = 0;
_lineGradientType = "linear";
_lineSpreadMethod = "pad";
_lineThickness = .1;
_lineColors = [ 0xFFFFFF, 0x000000 ];
_lineAlphas = [ 1, 1 ];
_lineRatios = [ 1, 255 ];
_lineGradientWidth = _width;
_lineGradientHeight = _height;
_lineGradientRotation = 0;
_lineTx = 0;
_lineTy = 0;
_useBitmapFill = false;
_pixelHinting = true;
fillGradientBox = new Matrix();
lineGradientBox = new Matrix();
init();

The primary function of the constructor is to instantiate all of the properties that we have defined. We also gave each property a default value. You will be able to see what the result of these values are later. Each property that begins with an underscore will be given read/write access to outside code. The reasons these properties are not public properites is because we want to respond to the change in value of each particular property. We shall do this within the setter methods that we’ll create later.

Each property is based on particular value that must be passed into any of the graphics object methods. One example is the _fillGradientColors property. It is an array of uints that will be passed into the graphics.beginGradientFill method. Another example is the _pixelHinting property. It will be passed into the graphics.lineStyle method’s pixelHinting parameter.

The last line of the constuctor calls the init method. The init method is very simple. It calls the update method.

Step 4: The Update Method

The update method is probably the most important method within the EditableShape class. The main objective of this method is to clear any existing graphics and redraw them based upon the latest data. We will call this method everytime a property has changed so the changes can be seen immediately by the user if necassary. Create the update method.

protected function update():void {

	if ( _matchGradientSize ) {

		_lineGradientWidth = _width;
		_lineGradientHeight = _height;
		_fillGradientWidth = _width;
		_fillGradientHeight = _height;
	}

	lineGradientBox.createGradientBox( lineGradientWidth, lineGradientHeight, toRadians( lineGradientRotation ), lineTx, lineTy );
	fillGradientBox.createGradientBox( fillGradientWidth, fillGradientHeight, toRadians( fillGradientRotation ), fillTx, fillTy );
	super.graphics.clear();
	super.graphics.lineStyle( lineThickness, 0, 0, pixelHinting );
	super.graphics.lineGradientStyle( lineGradientType, lineColors, lineAlphas, lineRatios, lineGradientBox, lineSpreadMethod );
	if ( !_bitmapData || !_useBitmapFill ) super.graphics.beginGradientFill( fillGradientType, fillColors, fillAlphas, fillRatios, fillGradientBox, fillSpreadMethod )
	else super.graphics.beginBitmapFill( _bitmapData );

	draw();
}

The Matrix objects we created in the constructor are used to manipulate gradients. We needed two of them. One for the fill gradient and the other for the line gradient.

We will be overriding the get graphics method so that we can forbid access to this property to outside code. We don’t want any outside code tampering with our graphics at all. Because we are going to override the get graphics method, we will need to access the method from the subclass. This is accomplished through the super object. We will also create a protected method called getGraphics later on. This method is needed to give subclasses access to the graphics object without granting access to the object to outside code.

In conclusion, the update method re-initializes the graphics and it does this based on the current values of the properties within the EditableShape instance. The last line of code calls the draw method which is an abstract method in the EditableShape class. The method should be overriden by a subclass and is intended for drawing a particular shape using the graphics object within its implementation.

Step 5: Clones and Copies

Create the draw method.

protected function draw():void {

	// Abstract
}

Again the draw method is just a simple abstract method that we can ignore for now.

We will need to copy the properties of one shape onto another. There may also be times when you’d like a complete clone of a particular shape. We’ll create two methods to accomplish this for us. Doing so will save us a lot of time in the long run. Instead of always re-writing code we’ll just call the appropriate method which copies or clones a shape. Create the copy and clone methods.

public function copy( shape:EditableShape ):void {

	_width = shape.width;
	_height = shape.height;
	_matchGradientSize = shape.matchGradientSize;
	_fillGradientType = shape.fillGradientType;
	_fillSpreadMethod = shape.fillSpreadMethod;
	_fillColors = shape.fillColors;
	_fillAlphas = shape.fillAlphas;
	_fillRatios = shape.fillRatios;
	_fillGradientWidth = shape.fillGradientWidth;
	_fillGradientHeight = shape.fillGradientHeight;
	_fillGradientRotation = shape.fillGradientRotation;
	_fillTx = shape.fillTx;
	_fillTy = shape.fillTy;
	_lineGradientType = shape.lineGradientType;
	_lineSpreadMethod = shape.lineSpreadMethod;
	_lineThickness = shape.lineThickness;
	_lineColors = shape.lineColors;
	_lineAlphas = shape.lineAlphas;
	_lineRatios = shape.lineRatios;
	_lineGradientWidth = shape.lineGradientWidth;
	_lineGradientHeight = shape.lineGradientHeight;
	_lineGradientRotation = shape.lineGradientRotation;
	_lineTx = shape.lineTx;
	_lineTy = shape.lineTy;
	_useBitmapFill = shape.useBitmapFill;
	if ( _bitmapData ) _bitmapData = shape.bitmapData.clone();
	if ( filters ) filters = shape.filters;
	alpha = shape.alpha;
	update();
}

public function clone():EditableShape {

	var c:Class = Class( getDefinitionByName( getQualifiedClassName( this ) ) );
	var shape:EditableShape = new c();
	shape.width = _width;
	shape.height = _height;
	shape.matchGradientSize = _matchGradientSize;
	shape.fillGradientType = _fillGradientType;
	shape.fillSpreadMethod = _fillSpreadMethod;
	shape.fillColors = _fillColors;
	shape.fillAlphas = _fillAlphas;
	shape.fillRatios = _fillRatios;
	shape.fillGradientWidth = _fillGradientWidth;
	shape.fillGradientHeight = _fillGradientHeight;
	shape.fillGradientRotation = _fillGradientRotation;
	shape.fillTx = _fillTx;
	shape.fillTy = _fillTy;
	shape.lineGradientType = _lineGradientType;
	shape.lineSpreadMethod = _lineSpreadMethod;
	shape.lineThickness = _lineThickness;
	shape.lineColors = _lineColors;
	shape.lineAlphas = _lineAlphas;
	shape.lineRatios = _lineRatios;
	shape.lineGradientWidth = _lineGradientWidth;
	shape.lineGradientHeight = _lineGradientHeight;
	shape.lineGradientRotation = _lineGradientRotation;
	shape.lineTx = _lineTx;
	shape.lineTy = _lineTy;
	shape.useBitmapFill = _useBitmapFill;
	if ( _bitmapData ) shape.bitmapData = _bitmapData.clone();
	shape.filters = filters;
	shape.alpha = alpha;
	return shape;
}

The copy method takes the shape parameter and sets all of the properties equal to that of the current EditableShape.

We will not be using the clone method in this tutorial but I just threw it in as an extra bonus. The method returns a cloned copy of the current EditableShape class.

Step 6: Finishing Up the EditableShape

The last thing we need to do is grant read/write access to all of the shape’s main properties. Write the following getter and setter methods within the EditableShape class.

		public override function set width(value:Number):void {

			_width = value;
			update();
		}

		public override function get width():Number {

			return _width;
		}

		public override function set height(value:Number):void {

			_height = value;
			update();
		}

		public override function get height():Number {

			return _height;
		}

		public function set fillGradientType( value:String ):void {

			switch ( value.toLowerCase() ) {

				case "linear" :
				case "radial" :
					_fillGradientType = value.toLowerCase();
					update();
					break;
				default :
					//Do nothing
			}
		}

		public function get fillGradientType():String {

			return _fillGradientType;
		}

		public function set fillSpreadMethod(value:String):void {

			switch ( value.toLowerCase() ) {

				case "pad" :
				case "reflect" :
				case "repeat" :
					_fillSpreadMethod = value.toLowerCase();
					update();
				default :
					//Do nothing
			}
		}

		public function get fillSpreadMethod():String {

			return _fillSpreadMethod;
		}

		public function set fillColors(array:Array):void {

			var a:Array = [];

			for each( var color:uint in array ) {

				if ( color is uint ) {

					a.push( color );
				}
			}

			_fillColors = a;
			update();
		}

		public function get fillColors():Array {

			return _fillColors;
		}

		public function set fillAlphas( array:Array ):void {

			var a:Array = [];

			for each( var nAlpha:Number in array ) {

				if ( nAlpha is Number)  {

					a.push( nAlpha );
				}
			}

			_fillAlphas = a;
			update();
		}

		public function get fillAlphas():Array {

			return _fillAlphas;
		}

		public function set fillRatios(array:Array):void {

			var a:Array = [];

			for each(var ratio:Number in array) {

				if (ratio is int) {

					a.push(ratio);
				}
			}

			_fillRatios = a;
			update();
		}

		public function get fillRatios():Array {

			return _fillRatios;
		}

		public function set fillGradientWidth(value:Number):void {

			_fillGradientWidth = value;
			update();
		}

		public function get fillGradientWidth():Number {

			return _fillGradientWidth;
		}

		public function set fillGradientHeight(value:Number):void {

			_fillGradientHeight = value;
			update();
		}

		public function get fillGradientHeight():Number {

			return _fillGradientHeight;
		}

		public function set fillGradientRotation(degrees:Number):void {

			_fillGradientRotation = degrees;
			update();
		}

		public function get fillGradientRotation():Number {

			return _fillGradientRotation;
		}

		public function set fillTx(value:Number):void {

			_fillTx = value;
			update();
		}

		public function get fillTx():Number {

			return _fillTx;
		}

		public function set fillTy(value:Number):void {

			_fillTy = value;
			update();
		}

		public function get fillTy():Number {

			return _fillTy;
		}

		public function set lineGradientType(value:String):void {

			switch (value.toLowerCase()) {

				case "linear" :
				case "radial" :
					_lineGradientType = value.toLowerCase();
					update();
					break;
				default :
					//Do nothing
			}
		}

		public function get lineGradientType():String {

			return _lineGradientType;
		}

		public function set lineSpreadMethod(value:String):void {

			switch (value.toLowerCase()) {

				case "pad" :
				case "reflect" :
				case "repeat" :
					_lineSpreadMethod = value.toLowerCase();
					update();
				default :
					//Do nothing
			}
		}

		public function get lineSpreadMethod():String {

			return _lineSpreadMethod;
		}

		public function set lineThickness(value:Number):void {

			_lineThickness = value;
			update();
		}

		public function get lineThickness():Number {

			return _lineThickness;
		}

		public function set lineColors(array:Array):void {

			var a:Array = [];

			for each(var color:uint in array) {

				if (color is uint) {

					a.push(color);
				}
			}

			_lineColors = array;
			update();
		}

		public function get lineColors():Array {

			return _lineColors;
		}

		public function set lineAlphas(array:Array):void {

			var a:Array = [];

			for each(var nAlpha:Number in array) {

				if (nAlpha is Number) {

					a.push(nAlpha);
				}
			}

			_lineAlphas = a;
			update();
		}

		public function get lineAlphas():Array {

			return _lineAlphas;
		}

		public function set lineRatios(array:Array):void {

			var a:Array = [];

			for each(var ratio:Number in array) {

				if (ratio is int) {

					a.push(ratio);
				}
			}

			_lineRatios = a;
			update();
		}

		public function get lineRatios():Array {

			return _lineRatios;
		}

		public function set lineGradientWidth(value:Number):void {

			_lineGradientWidth = value;
			update();
		}

		public function get lineGradientWidth():Number {

			return _lineGradientWidth;
		}

		public function set lineGradientHeight(value:Number):void {

			_lineGradientHeight = value;
			update();
		}

		public function get lineGradientHeight():Number {

			return _lineGradientHeight;
		}

		public function set lineGradientRotation(degrees:Number):void {

			_lineGradientRotation = degrees;
			update();
		}

		public function get lineGradientRotation():Number {

			return _lineGradientRotation;
		}

		public function set lineTx(value:Number):void {

			_lineTx = value;
			update();
		}

		public function get lineTx():Number {

			return _lineTx;
		}

		public function set lineTy(value:Number):void {

			_lineTy = value;
			update();
		}

		public function get lineTy():Number {

			return _lineTy;
		}

		public function set matchGradientSize(value:Boolean):void {

			_matchGradientSize = value;
			update();
		}

		public function get matchGradientSize():Boolean {

			return _matchGradientSize;
		}

		public function set bitmapData( value:BitmapData ):void {

			_bitmapData = value;
			update();
		}

		public function get bitmapData():BitmapData {

			return _bitmapData;
		}

		public function set useBitmapFill( value:Boolean ):void {

			_useBitmapFill = value;
			update();
		}

		public function get useBitmapFill():Boolean {

			return _useBitmapFill;
		}

		public function set firstFillColor( value:uint ):void {

			_fillColors[ 0 ] = value;
			update();
		}

		public function get firstFillColor():uint {

			if ( _fillColors.length > 0 ) {

				return _fillColors[ 0 ];
			}
			else {

				return 0;
			}
		}

		public function set pixelHinting( value:Boolean ):void {

			_pixelHinting = value;
			update();
		}

		public function get pixelHinting():Boolean {

			return _pixelHinting;
		}

		public override function get graphics():Graphics {

			return null;
		}

		protected function getGraphics():Graphics {

			return super.graphics;
		}

All of the getter methods just return the corresponding properties value. But for the setter methods we correct or filter out any unwanted input. We also call the update method so that there is an immediate reaction to the new value or values.

Step 7: Drawing Rectangles

The majority of our button will consist of rectangle shapes. Unless we want to bore our client’s users with a bunch of lame blocky shapes, we will want to be able to round the edges of our rectangles. The EditableShape class is meant to be extended, meaning that it should have subclasses that finalize the primary function of the class. The EditableShape class takes care of all of the hard work for us. All we have to do now is draw the shape within a subclass. Create a new class called RectangleShape which extends the EditableShape class. The class declaration should look as follows.

public class RectangleShape extends EditableShape {

Add the following private properties to the class directly after the class declaration.

private var _ellipseWidth:Number;
private var _ellipseHeight:Number;

I mentioned before that we will be rounding the edges to our rectangles. As you have probably guessed already, we will be granting read/write access to these properties just as we did with all of the other inherited properties. This will allow us to react to any change the ellipseWidth and ellipseHeight properties immediately after they have been altered.

Reminder: This is accomplished by calling the update method.

Create the class constructor. Give the _ellipseWidth and _ellipseHeight properties a default value of 0. We don’t want the edges to be rounded by default.

public function RectangleShape() {

	_ellipseWidth = 0;
	_ellipseHeight = 0;
    super();
}

You should remember the draw method from the EditableShape class was an abstract method. That is a method that has an empty implementation. We are going to override this method to give it the proper functionality. The methods name is self explanatory. The method will do the actual drawing of the shape.

Important: We call the base class’s constructor, super(), after we have assigned a value to the _ellipseWidth and _ellipseHeight properties. Remember the the constructor initializes the shape by calling the init method which then calls the update method which finally calls the draw method. You will see in a minute that the draw method requires these properties. Forgeting to call the constructor last will result in an argument error thrown by the drawRoundRect method of the graphics object.

protected override function draw():void {

	getGraphics().drawRoundRect( 0, 0, width, height, _ellipseWidth, _ellipseHeight );
}

I have to apologize to all of you who were expecting ten or more lines of code here in the draw method. That’s not the case here. Remember that the base class(EditableShape) does most of the work for us. It handles colors, gradients, alphas, line properties and so on. All we needed to do is draw the shape and that’s what we’ve done. The graphics object can no longer be accessed by outside code since the property has been overriden so we had to access it through the protected method, getGraphics. Finally we call the drawRoundRect method on the graphics object and we pass in the appropriate parameters.

Step 8: Overriding the Copy and Clone Methods

There are two more methods we need to override before we can conclude this class. The first method is the copy method. This is the method from the EditableShape class that takes an EditableShape as a parameter and causes the properties of the parent shape onto the parameter shape. We need add some functionality to this method. We will be overriding this method but that doesn’t mean that we have to forget everything that the base class does with this method. We’ll use the super object to call the method from the base class so that it inherits its original functionality while adding new functionality to it.

public override function copy( shape:EditableShape ):void {

	super.copy( shape );

	if ( shape is RectangleShape ) {

		var rect:RectangleShape = shape as RectangleShape;
		ellipseWidth = rect.ellipseWidth;
		ellipseHeight = rect.ellipseHeight;
	}
}

Can you tell what just happened? If the parameter, shape, is a RectangleShape we also copy the ellipseWidth and ellipseHeight properties. If you have a collection of RectangleShapes, that you are using to draw a graphic with, and you’d like them all to have the same ellipseWidth and ellipseHeight properties, this will keep you from writing too many extra lines of code.

The second method we need to override is the clone method.

public override function clone():EditableShape {

	var shape:RectangleShape = super.clone() as RectangleShape;
	shape.ellipseWidth = _ellipseWidth;
	shape.ellipseHeight = _ellipseHeight;
	return shape;
}

The clone method also inherits the implementation of the base class. But with this implementation we have added the ellipseWidth and ellipseHeight properties.

Step 9: More Access

Write the following getter and setter methods:

public function set ellipseWidth( value:Number ):void {

	if ( value < 0 ) value = 0;
	_ellipseWidth = value;
	update();
}

public function get ellipseWidth():Number {

	return _ellipseWidth;
}

public function set ellipseHeight( value:Number ):void {

	if ( value < 0 ) value = 0;
	_ellipseHeight = value;
	update();
}

public function get ellipseHeight():Number {

	return _ellipseHeight;
}

We have not only granted the read/write access that is needed by outside code, but we have also made sure that the ellipseWidth and ellipseHeight are never below zero. There is also an immediate reaction to these properties being set or changed.

Note: If you do not want to correct any values for the ellipseWidth or ellispeHeight properties, you do not have to. There may be a time when you’d want the ellipseWidth or ellipseHeight to be less than zero.

Now that we have our first shape complete. Let’s take a quick look at what our shape looks like when we first create it. You will need to create a document class and create a new instance of the RectangleShape object within it. Add the new RectangleShape to the stage. Here’s my code:

stage.addChild( new RectangleShape() );

Let’s look at the result.

This is the what our shape looks like by default. Feel free to play around with it a bit so that you get a good feel for it. Try changing the colors or modifying the size.

Step 9: Drawing Circles

We are going to create a sort of bubbling effect for the over state of our button. This means that we will need bubbles. Create the EclipseShape class. Make sure that it extends the EditableShape class.

package {

	public class EllipseShape extends EditableShape {

		public function EllipseShape() {

			super();
		}

		protected override function draw():void {

			getGraphics().drawEllipse( 0, 0, width, height );
		}
	}
}

Once again the power of inheritance has allowed us to recycle old code instead of writing the same code over and over again. This class only contains inherited properties and methods. We had to override the draw method in order to create the actual eclipse shape though. The drawEclipse method uses the inherited width and height properties to draw our shape. And once again we access the graphics object using the protected getGraphics method.

We now have all of the shapes we need to draw our button.

Step 10: Starting the Button

Create a new class that extends flash.display.Sprite. You can call the class whatever you’d like. I’m going to use the name MyButton. Import the following classes.

import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.filters.BlurFilter;
import flash.filters.GlowFilter;
import flash.events.MouseEvent;
import flash.filters.DropShadowFilter;
import flash.system.System;
import flash.filters.BevelFilter;
import com.greensock.TweenMax;

public class MyButton extends Sprite {

Define the following properties.

private var _width:Number;
private var _active:Boolean;
private var base:RectangleShape;
private var toggleBase:RectangleShape;
private var txt:TextField;
private var effectTxt:TextField;
private var toggleTxt:TextField;
private var toggleGlass:RectangleShape;
private var toggleGlassAlpha:Number;
private var ref:RectangleShape;
private var light:RectangleShape;
private var lightAlpha:Number;
private var glow:RectangleShape;
private var effectMask:RectangleShape;
private var txtMask:RectangleShape;
private var effectTxtMask:RectangleShape;
private var toggleTxtMask:RectangleShape;
private var effectContainer:Sprite;
private var circles:Array;
private var tweens:Array;
private var circleBlur:BlurFilter;
private var _toggle:Boolean;

Just like before, any property that starts with an underscore is either expected to cause an immediate reaction when set or the property will be read-only.

The _width property will be used to override the width property of the base class and we redraw the shape everytime the width property is set.

The active property is going to be used to swap the toggle states of the button later.

You will notice several properties that are RectangleShapes, several properties that are TextFields, and a Sprite. We will see the role each of these properties play later.

We’ll be storing all of our bubbles in the circles Array. To improve performance we will need to pause various tweens. In order to do this we will need to store these tweens in an array so that they can be accessed whenever we need them.

Last we have the circleBlur property which is a BlurFilter that is to be applied to each bubble, and we have the _toggle property which affects the behavior of the button.

Create the following public constants.

public static const BUTTON_HEIGHT:Number = 40;
public static const NUM_OF_CIRCLES:uint = 12;

The height of our button will not change so it’s appropriate to store the value of the button’s height in a class constant. The size of the button’s ellipse is relative to the button’s height. If the button becomes too large or too small, our button may lose the Pill Button look that we are going for. Also the number of bubbles is predetermined so we store this value in a class constant as well.

Step 11: The Base

When ever I am drawing graphics for a component like a text field or a button, I always, always, always… start with a base shape. This is a shape that acts as the foundation of the shape. It is the backbone of the component. How the graphic is structured is entirely dependent on how I construct the base.

You will notice a property that we have defined called toggleBase. I am not talking about this property. I am talking about the base property itself. This shape will define the outline of the button. Let’s create this property and initialize its values now. Add the following code to the constructor of the class that you have defined as your button.

public function MyButton() {

	super();
	buttonMode = true;
	mouseChildren = false;
	_width = 100;

	base = new RectangleShape();
	base.height = BUTTON_HEIGHT;
	base.ellipseHeight = base.ellipseWidth = BUTTON_HEIGHT;
	base.fillGradientRotation = 90;
	base.fillColors = [ 0xAAAAAA, 0x444444 ];
	base.lineColors = [ 0x222222 ];
	base.lineAlphas = [ .5 ];
	base.lineRatios = [ 1 ];

    addChild( base );
}

The default fillGradientRotation is 0. This value is in degrees but is converted into radians when passed into the gradient box(Matrix). Along with initializing the button’s size, we have to set the rotation of the gradient. In this case we want this value to be 90 degrees. We also set the fillColors (as an Array), and the lineColors.

It is important to remember that the default value for these properties is an Array that has a length of two. All of the Array properties(lineColor,lineAlpha, and lineRatios) must be the same length. If they aren’t, the graphics will not draw. This is why we set the lineAlphas and lineRatios properties.

If you test the Flash movie, you should get this.

This is the overrall shape we are going for, “The Gel Pill”. Let’s make it shine a little bit.

Step 12: The Reflection

We’ve got the main structure of the button down already but now we need to add the small thing that I love to preach about. We need lots and lots of depth. We can start by adding the reflection. When light hits a glossy surface, it reflects off of the surface. Instantiate and initialize the ref (short for reflection) property.

super();
buttonMode = true;
mouseChildren = false;
_width = 100;

base = new RectangleShape();
base.height = BUTTON_HEIGHT;
base.ellipseHeight = base.ellipseWidth = BUTTON_HEIGHT;
base.fillGradientRotation = 90;
base.fillColors = [ 0xAAAAAA, 0x444444 ];
base.lineColors = [ 0x222222 ];
base.lineAlphas = [ .5 ];
base.lineRatios = [ 1 ];

ref = new RectangleShape();
ref.fillGradientRotation = 90;
ref.ellipseHeight = ref.ellipseWidth = ref.height = BUTTON_HEIGHT / 2;
ref.fillColors = [ 0xFFFFFF, 0xFFFFFF ];
ref.fillAlphas = [ 1, 0 ];
ref.lineColors = [ 0 ];
ref.lineAlphas = [ 0 ];
ref.lineRatios = [ 0 ];
ref.alpha = .5;
ref.x = ref.ellipseHeight / 2;
ref.width = _width - ref.height;

addChild( base );
addChild( ref );

We have turned the alpha property down a little bit so the the reflection isn’t so intense but we have basically followed the same steps to draw the ref shape as we did with the base shape. And of course we have sized and positioned the reflection relative to the size of the button’s height. Let’s see what we have now.

Not too bad. Still needs a lot more depth though. We’ll add some more later.

Step 13: The Inner Light

Sometimes when you are creating art, you notice that it’s those tiny little details that make the biggest difference in the appearance of your work. The light property will add the tiny detail into our button that makes all of the difference. This property will also be used a little differently in our button’s over and out states, but for now it will make our button appear to have a semi-transparent surface.

Add the following code to your button’s constructor method.

light = new RectangleShape();
light.copy( ref );
light.x = ref.x;
light.y = BUTTON_HEIGHT - light.height;
light.width = _width - light.height;
light.fillColors = [ 0xFFFFFF, 0xDDDDDD ];
light.filters = [ new GlowFilter( 0xFFFFFF, .8, 10, 10, 2, 3 ), new BlurFilter( 6, 6, 3 ) ];
light.alpha = lightAlpha = .3;

addChild( light );

The constructor should now look like this:

public function MyButton() {

	super();
	buttonMode = true;
	mouseChildren = false;
	_width = 100;

	base = new RectangleShape();
	base.height = BUTTON_HEIGHT;
	base.ellipseHeight = base.ellipseWidth = BUTTON_HEIGHT;
	base.fillGradientRotation = 90;
	base.fillColors = [ 0xAAAAAA, 0x444444 ];
	base.lineColors = [ 0x222222 ];
	base.lineAlphas = [ .5 ];
	base.lineRatios = [ 1 ];

	ref = new RectangleShape();
	ref.fillGradientRotation = 90;
	ref.ellipseHeight = ref.ellipseWidth = ref.height = BUTTON_HEIGHT / 2;
	ref.fillColors = [ 0xFFFFFF, 0xFFFFFF ];
	ref.fillAlphas = [ 1, 0 ];
	ref.lineColors = [ 0 ];
	ref.lineAlphas = [ 0 ];
	ref.lineRatios = [ 0 ];
	ref.alpha = .5;
	ref.x = ref.ellipseHeight / 2;
	ref.width = _width - ref.height;

	light = new RectangleShape();
	light.copy( ref );
	light.x = ref.x;
	light.y = BUTTON_HEIGHT - light.height;
	light.width = _width - light.height;
	light.fillColors = [ 0xFFFFFF, 0xDDDDDD ];
	light.filters = [ new GlowFilter( 0xFFFFFF, .8, 10, 10, 2, 3 ), new BlurFilter( 6, 6, 3 ) ];
	light.alpha = lightAlpha = .3;

	addChild( base );
	addChild( light );
	addChild( ref );
}

We have added a GlowFilter and a BlurFilter to this object so that we can achieve a specific look. We don’t want the shape to look like a shape at all but empty space within the button. Notice that we have used the copy method to mimic the properties of the ref object. There’s no need to write the same lines of code for the light object. Just mimic the ref property and make just a few modifications and you have yourself a new shape.

See how we are beginning to see more depth as our shape is being constructed? The pill doesn’t look fully opaque and it isn’t very transparent either. We want an “Out of This World” kind of look so just in between is perfect.

Step 14: Simple Text

Now that we have a good foundation down on the table, it’s appropriate to begin adding the first TextField to the button. Initialize the txt property. And create a mask that is the same size and ellipse as the base so that the text doesn’t appear outside of the button.

public function TutButton() {

	super();
	buttonMode = true;
	mouseChildren = false;
	_width = 100;

	base = new RectangleShape();
	base.height = BUTTON_HEIGHT;
	base.ellipseHeight = base.ellipseWidth = BUTTON_HEIGHT;
	base.fillGradientRotation = 90;
	base.fillColors = [ 0xAAAAAA, 0x444444 ];
	base.lineColors = [ 0x222222 ];
	base.lineAlphas = [ .5 ];
	base.lineRatios = [ 1 ];

	ref = new RectangleShape();
	ref.fillGradientRotation = 90;
	ref.ellipseHeight = ref.ellipseWidth = ref.height = BUTTON_HEIGHT / 2;
	ref.fillColors = [ 0xFFFFFF, 0xFFFFFF ];
	ref.fillAlphas = [ 1, 0 ];
	ref.lineColors = [ 0 ];
	ref.lineAlphas = [ 0 ];
	ref.lineRatios = [ 0 ];
	ref.alpha = .5;
	ref.x = ref.ellipseHeight / 2;
	ref.width = _width - ref.height;

	light = new RectangleShape();
	light.copy( ref );
	light.x = ref.x;
	light.y = BUTTON_HEIGHT - light.height;
	light.width = _width - light.height;
	light.fillColors = [ 0xFFFFFF, 0xDDDDDD ];
	light.filters = [ new GlowFilter( 0xFFFFFF, .8, 10, 10, 2, 3 ), new BlurFilter( 6, 6, 3 ) ];
	light.alpha = lightAlpha = .3;

	txt = new TextField();
	txt.selectable = false;
	txt.type = "dynamic";
	txt.wordWrap = false;
	txt.multiline = false;
	txt.autoSize = "left";
	txt.defaultTextFormat = new TextFormat( null, 27 );
	txt.textColor = 0x333333;
	txt.text = "label";
	txt.height = BUTTON_HEIGHT;

	txtMask = new RectangleShape();
	txtMask.copy( base );
	txtMask.filters = [];
	txt.mask = txtMask;

	addChild( base );
	addChild( light );
	addChild( ref );
	addChild( txt );
	addChild( txtMask );
}

We have once again utilized the copy method by creating a copy of the base object. We could have very well have used the clone method also. The result would be the same. Also note that we have set the filters array of the txtMask object to a blank array. This is because when the copy method used the filters property is also inherited. We have just simply overriden this property. Let’s see where we’re at.

We will position all of the TextFields later on. For now our txt will just have to hang out on the left side of our button.

Step 15: Setting Up for the Over State

Our button will illuminate and display a sort of science fiction like animation sequence with bubbles when the mouse hovers over the button. Of course the entire sequence will be accomplished 100% with code.

But before we can do this we need to create the elements of the sequence. The first is the background object, or the glow property, of the over state. Let’s add the glow object now. Add the following code to the constructor method:

glow = new RectangleShape();
glow.copy( base );
glow.fillColors = [ 0xFFFFFF ];
glow.fillAlphas = [ 1 ];
glow.fillRatios = [ 0 ];
glow.lineColors = [ 0 ];
glow.lineAlphas = [ 0 ];
glow.lineRatios = [ 0 ];
glow.filters = [ new GlowFilter( 0x00BCE9, 1, 10, 10, 2, 3, false, false ), new GlowFilter( 0x00BCE9, 1, 20, 20, 2, 3, true ) ];

addChild( base );
addChild( light );
addChild( ref );
addChild( txt );
addChild( txtMask );
addChild( glow );

We will also need a container for the bubbles to be displayed in and a mask for that container so that the bubbles don’t float out of the button.

public function MyButton() {

	super();
	buttonMode = true;
	mouseChildren = false;
	_width = 100;

	base = new RectangleShape();
	base.height = BUTTON_HEIGHT;
	base.ellipseHeight = base.ellipseWidth = BUTTON_HEIGHT;
	base.fillGradientRotation = 90;
	base.fillColors = [ 0xAAAAAA, 0x444444 ];
	base.lineColors = [ 0x222222 ];
	base.lineAlphas = [ .5 ];
	base.lineRatios = [ 1 ];

	ref = new RectangleShape();
	ref.fillGradientRotation = 90;
	ref.ellipseHeight = ref.ellipseWidth = ref.height = BUTTON_HEIGHT / 2;
	ref.fillColors = [ 0xFFFFFF, 0xFFFFFF ];
	ref.fillAlphas = [ 1, 0 ];
	ref.lineColors = [ 0 ];
	ref.lineAlphas = [ 0 ];
	ref.lineRatios = [ 0 ];
	ref.alpha = .5;
	ref.x = ref.ellipseHeight / 2;
	ref.width = _width - ref.height;

	light = new RectangleShape();
	light.copy( ref );
	light.x = ref.x;
	light.y = BUTTON_HEIGHT - light.height;
	light.width = _width - light.height;
	light.fillColors = [ 0xFFFFFF, 0xDDDDDD ];
	light.filters = [ new GlowFilter( 0xFFFFFF, .8, 10, 10, 2, 3 ), new BlurFilter( 6, 6, 3 ) ];
	light.alpha = lightAlpha = .3;

	txt = new TextField();
	txt.selectable = false;
	txt.type = "dynamic";
	txt.wordWrap = false;
	txt.multiline = false;
	txt.autoSize = "left";
	txt.defaultTextFormat = new TextFormat( null, 27 );
	txt.textColor = 0x333333;
	txt.text = "label";
	txt.height = BUTTON_HEIGHT;

	txtMask = new RectangleShape();
	txtMask.copy( base );
	txtMask.filters = [];
	txt.mask = txtMask;

	glow = new RectangleShape();
	glow.copy( base );
	glow.fillColors = [ 0xFFFFFF ];
	glow.fillAlphas = [ 1 ];
	glow.fillRatios = [ 0 ];
	glow.lineColors = [ 0 ];
	glow.lineAlphas = [ 0 ];
	glow.lineRatios = [ 0 ];
	glow.filters = [ new GlowFilter( 0x00BCE9, 1, 10, 10, 2, 3, false, false ), new GlowFilter( 0x00BCE9, 1, 20, 20, 2, 3, true ) ];

	effectContainer = new Sprite();
	effectContainer.cacheAsBitmap = true;

	effectMask = new RectangleShape();
	effectMask.copy( base );
	effectMask.filters = [];
	effectContainer.mask = effectMask;

	addChild( base );
	addChild( light );
	addChild( ref );
	addChild( txt );
	addChild( txtMask );
	addChild( glow );
	addChild( effectContainer );
	addChild( effectMask );
}

Step 16: Bubbles

Now we are going to blow a few bubbles. Add the following lines of code to the constructor method:

circleBlur = new BlurFilter( 5, 5, 3 );
circles = [];
tweens = [];

The circleBlur is a BlurFilter that will be applied to all bubbles. This will give each bubble the specific science like look that we’re going for. We also need to create the arrays that will store all of the bubbles and the tweens that will animate each bubble.

We need a method that will generate all of the bubbles we need.

private function createEffect():void {

	for ( var i:int = 0; i < NUM_OF_CIRCLES; i++ ) {

		var circ:EllipseShape = new EllipseShape();
		resetCircle( circ );
	}

	stopEffect();
}

Use a loop to iterate a block of code that creates a new EllipseShape object, or in this case a bubble, and run the resetCircle method on the bubble. We haven’t created this method yet but it re-initializes the parameter bubble. In the loop, the method simply initializes each bubble since they haven’t been initialized to begin with. Finally the stopEffect method is called. This method pauses the bubble’s animation sequence. We’ll write this method in a bit.

For now, create the following methods. (Also now is a good time to import com.greensock.TweenMax).

private static function randomNumber( min:int = 0, max:int = 10 ):int {

	return Math.round( Math.random() * ( max - min ) + min );
}

private function resetCircle( circle:EllipseShape ):void {

	circle.width = circle.height = randomNumber( 10, 20 );
	effectContainer.addChild( circle );
	circle.cacheAsBitmap = true;
	circle.x = randomNumber( 0, _width );
	circle.y = BUTTON_HEIGHT;
	circle.filters = [ circleBlur ];

	if ( circles.indexOf( circle ) == -1 ) {

		circles.push( circle );
		circle.fillColors = [ 0x00BCE9 ];
		circle.fillAlphas = [ 1 ];
		circle.fillRatios = [ 1 ];
		circle.lineAlphas = [ 0 ];
		circle.lineRatios = [ 0 ];
		circle.lineColors = [ 0 ];
		circle.alpha = .6;
	}

	var tween:TweenMax = TweenMax.to( circle, randomNumber( 1, 6 ) * .5, { y:-BUTTON_HEIGHT, onComplete:doComplete } );
	tweens.push( tween );

	function doComplete():void {

		resetCircle( circle );
		removeTween( tween );
	}
}

private function removeTween( tween:TweenMax ):void {

	var a:Array = [];

	for each( var t:TweenMax in tweens ) {

		if ( t != tween ) a.push( t );
	}

	tweens = null;
	System.gc();
	tweens = a;
}

The randomNumber method returns a random number based on the parameters passed into the method. The first parameter specifies a the minimum value that can be generated and the second parameter specifies the maximum value that can be generated. We need this method to generate a random location and size for a bubble when we reset a bubble.

This brings me to the resetCircle method. I said before that this method re-initializes the specified bubble. To be more specific, the method recycles a bubble and makes it appear like a brand new bubble that has just been created when in reality it is just another old bubble.

The to method from the TweenMax class returns the tween that the bubble contains. We push this bubble into the tweens array. The bubble starts below the button and rises above the button. When the tween is finished it is no longer needed. The tween needs to be removed (using the removeTween method) and the bubble needs to be reset or recycled. The anonymous function doComplete does just that.

Before we can see what our bubbles look like we need to create two methods that will control playback of the bubbles’ animation sequence. Besides if we added a call to the createEffect method in the constructor and tested our movie now, the bubbles would be all there but we wouldn’t see them because they would be beneath the button. Remember that each bubble is added to the effectContainer in the resetCircle method and that the effectContainer is masked so that the bubbles aren’t seen outside of the button.

(Plus, if you tested the movie now you’d just get a compile-time error for not implementing the stopEffect method that is called when we create our bubbles.)

private function playEffect():void {

	for each( var tween:TweenMax in tweens ) {

		tween.play();
	}
}

private function stopEffect():void {

	for each( var tween:TweenMax in tweens ) {

		tween.pause();
	}
}

Loop through the tweens array to play each tween and to pause each tween when needed. Very simple.

Now add a call to the createEffect method and the playEffect method within the constructor. Test your movie. You should now have a beautiful display of bubbles. When you are finished remove the playEffect method from the constructor that you just added but keep the createEffect method.

Step 17: Glowing Text

Let’s add the glowing TextField to the button. We’re using a seperate TextField, effectTxt instead of txt, so that we can do a fading transition into the next state. We need an additional TextField for this. We also need another mask for our TextField just as we did with the first one.

public function MyButton() {

	super();
	buttonMode = true;
	mouseChildren = false;
	_width = 100;

	base = new RectangleShape();
	base.height = BUTTON_HEIGHT;
	base.ellipseHeight = base.ellipseWidth = BUTTON_HEIGHT;
	base.fillGradientRotation = 90;
	base.fillColors = [ 0xAAAAAA, 0x444444 ];
	base.lineColors = [ 0x222222 ];
	base.lineAlphas = [ .5 ];
	base.lineRatios = [ 1 ];

	ref = new RectangleShape();
	ref.fillGradientRotation = 90;
	ref.ellipseHeight = ref.ellipseWidth = ref.height = BUTTON_HEIGHT / 2;
	ref.fillColors = [ 0xFFFFFF, 0xFFFFFF ];
	ref.fillAlphas = [ 1, 0 ];
	ref.lineColors = [ 0 ];
	ref.lineAlphas = [ 0 ];
	ref.lineRatios = [ 0 ];
	ref.alpha = .5;
	ref.x = ref.ellipseHeight / 2;
	ref.width = _width - ref.height;

	light = new RectangleShape();
	light.copy( ref );
	light.x = ref.x;
	light.y = BUTTON_HEIGHT - light.height;
	light.width = _width - light.height;
	light.fillColors = [ 0xFFFFFF, 0xDDDDDD ];
	light.filters = [ new GlowFilter( 0xFFFFFF, .8, 10, 10, 2, 3 ), new BlurFilter( 6, 6, 3 ) ];
	light.alpha = lightAlpha = .3;

	txt = new TextField();
	txt.selectable = false;
	txt.type = "dynamic";
	txt.wordWrap = false;
	txt.multiline = false;
	txt.autoSize = "left";
	txt.defaultTextFormat = new TextFormat( null, 27 );
	txt.textColor = 0x333333;
	txt.text = "label";
	txt.height = BUTTON_HEIGHT;

	txtMask = new RectangleShape();
	txtMask.copy( base );
	txtMask.filters = [];
	txt.mask = txtMask;

	glow = new RectangleShape();
	glow.copy( base );
	glow.fillColors = [ 0xFFFFFF ];
	glow.fillAlphas = [ 1 ];
	glow.fillRatios = [ 0 ];
	glow.lineColors = [ 0 ];
	glow.lineAlphas = [ 0 ];
	glow.lineRatios = [ 0 ];
	glow.filters = [ new GlowFilter( 0x00BCE9, 1, 10, 10, 2, 3, false, false ), new GlowFilter( 0x00BCE9, 1, 20, 20, 2, 3, true ) ];

	effectContainer = new Sprite();
	effectContainer.cacheAsBitmap = true;

	effectMask = new RectangleShape();
	effectMask.copy( base );
	effectMask.filters = [];
	effectContainer.mask = effectMask;

	effectTxt = new TextField();
	effectTxt.selectable = false;
	effectTxt.type = "dynamic";
	effectTxt.wordWrap = false;
	effectTxt.multiline = false;
	effectTxt.autoSize = "left";
	effectTxt.defaultTextFormat = new TextFormat( null, 27 );
	effectTxt.textColor = 0x00BCE9;
	effectTxt.text = "label";
	effectTxt.filters = [ new GlowFilter( 0x00BCE9, 1, 16, 16, 2, 3 ) ];

	effectTxtMask = new RectangleShape();
	effectTxtMask.copy( base );
	effectTxtMask.filters = [];
	effectTxt.mask = effectTxtMask;

	circleBlur = new BlurFilter( 5, 5, 3 );
	circles = [];
	tweens = [];

	addChild( base );
	addChild( light );
	addChild( ref );
	addChild( txt );
	addChild( txtMask );
	addChild( glow );
	addChild( effectContainer );
	addChild( effectMask );
	addChild( effectTxt );
	addChild( effectTxtMask );

	createEffect();
}

Just another TextField with a glow filter. Again we will position the text fields later when we create the update method. Now you should have something that looks like this.

Now that all of the elements for the over state have been generated, we only have one more task to complete. Next we position the contents of the button.

Step 18: Positioning

Encapsulated in our button class is a function that positions the button’s contents based on the current value of the _width property. The method I am referring to is the update method. Call the update method on the last line of code of the constructor method. Then create the update method.

	addChild( effectTxt );
	addChild( effectTxtMask );

	createEffect();
	update();
}

protected function update():void {

	base.width = _width;
	glow.width = _width;
	ref.width = _width - ref.height;
	light.width = _width - light.height;
	txt.x = ( _width - txt.width ) / 2;
	txt.y = ( BUTTON_HEIGHT - txt.height ) / 2;
	effectTxt.x = txt.x;
	effectTxt.y = txt.y;
	effectMask.width = _width;
	txtMask.width = _width;
	effectTxtMask.width = _width;
}

Resize particalar objects and reposition others. Test the movie:

We now have centered text. Set the alpha property of all of the effect base objects(effectContainer, effectTxt and glow) to zero. Re-test the movie and now you should see the original state of the button.

Step 19: The Over State

At last we finally get to the ever-so-exciting “over” state. Okay let’s go! Add the following lines of code at the end of the constructor method.

addEventListener( "rollOver", overState );
addEventListener( "rollOut", outState );

Now create the overState and outState event handler methods.

private function overState( e:MouseEvent ):void {

	playEffect();
	TweenMax.to( light, 3, { alpha:1 } );
	TweenMax.to( glow, 1, { alpha:1 } );
	TweenMax.to( effectTxt, 1, { alpha:1 } );
	TweenMax.to( effectContainer, 1, { alpha:1 } );
}

private function outState( e:MouseEvent ):void {

	TweenMax.to( light, 3, { alpha:lightAlpha } );
	TweenMax.to( glow, 1, { alpha:0 } );
	TweenMax.to( effectTxt, 1, { alpha:0 } );
	TweenMax.to( effectContainer, 1, { alpha:0, onComplete:stopEffect } );
	//upState();
}

The overState method plays the bubbles animation and performs a fade in transition of the effect whenever the mouse hovers over the button.

The outState method does the complete opposite: it returns the button back to its original state when the mouse hovers off of the button, lets the light property linger for a second to give the button a sense of losing power or losing illumination.

Comment out the upState method so that you can test the movie without any errors. We’ll create this method soon.

Important: Remember to uncomment out the call to the upState method within the outState method after we have created that method.

Step 20: Up and Down States

Add the following code at the end of the constructor method.

addEventListener( "mouseDown", downState );
addEventListener( "mouseUp", upState );

Create the following methods.

private function downState( e:MouseEvent ):void {

	filters = [ new GlowFilter( 0 ) ];
}

private function upState( e:MouseEvent = null ):void {

	filters = [];
}

The downState method displays a background glow around the button when the mouse button is down and the upState button removes that glow return the button back to it’s initial state. The upState method’s e parameter is set to null by default. This allows the method to be called manually and not require the dispatching of a MouseEvent. We’ll test to see where were at after the next step.

Reminder: Uncomment the call to the upState method from the outState method.

Step 21: Toggle Button

Add the missing code to the constructor method.

public function MyButton() {

	super();
	buttonMode = true;
	mouseChildren = false;
	_width = 100;

	base = new RectangleShape();
	base.height = BUTTON_HEIGHT;
	base.ellipseHeight = base.ellipseWidth = BUTTON_HEIGHT;
	base.fillGradientRotation = 90;
	base.fillColors = [ 0xAAAAAA, 0x444444 ];
	base.lineColors = [ 0x222222 ];
	base.lineAlphas = [ .5 ];
	base.lineRatios = [ 1 ];

	ref = new RectangleShape();
	ref.fillGradientRotation = 90;
	ref.ellipseHeight = ref.ellipseWidth = ref.height = BUTTON_HEIGHT / 2;
	ref.fillColors = [ 0xFFFFFF, 0xFFFFFF ];
	ref.fillAlphas = [ 1, 0 ];
	ref.lineColors = [ 0 ];
	ref.lineAlphas = [ 0 ];
	ref.lineRatios = [ 0 ];
	ref.alpha = .5;
	ref.x = ref.ellipseHeight / 2;
	ref.width = _width - ref.height;

	light = new RectangleShape();
	light.copy( ref );
	light.x = ref.x;
	light.y = BUTTON_HEIGHT - light.height;
	light.width = _width - light.height;
	light.fillColors = [ 0xFFFFFF, 0xDDDDDD ];
	light.filters = [ new GlowFilter( 0xFFFFFF, .8, 10, 10, 2, 3 ), new BlurFilter( 6, 6, 3 ) ];
	light.alpha = lightAlpha = .3;

	txt = new TextField();
	txt.selectable = false;
	txt.type = "dynamic";
	txt.wordWrap = false;
	txt.multiline = false;
	txt.autoSize = "left";
	txt.defaultTextFormat = new TextFormat( null, 27 );
	txt.textColor = 0x333333;
	txt.text = "label";
	txt.height = BUTTON_HEIGHT;

	txtMask = new RectangleShape();
	txtMask.copy( base );
	txtMask.filters = [];
	txt.mask = txtMask;

	glow = new RectangleShape();
	glow.copy( base );
	glow.fillColors = [ 0xFFFFFF ];
	glow.fillAlphas = [ 1 ];
	glow.fillRatios = [ 0 ];
	glow.lineColors = [ 0 ];
	glow.lineAlphas = [ 0 ];
	glow.lineRatios = [ 0 ];
	glow.filters = [ new GlowFilter( 0x00BCE9, 1, 10, 10, 2, 3, false, false ), new GlowFilter( 0x00BCE9, 1, 20, 20, 2, 3, true ) ];
	glow.alpha = 0;

	effectContainer = new Sprite();
	effectContainer.cacheAsBitmap = true;
	effectContainer.alpha = 0;

	effectMask = new RectangleShape();
	effectMask.copy( base );
	effectMask.filters = [];
	effectContainer.mask = effectMask;

	effectTxt = new TextField();
	effectTxt.selectable = false;
	effectTxt.type = "dynamic";
	effectTxt.wordWrap = false;
	effectTxt.multiline = false;
	effectTxt.autoSize = "left";
	effectTxt.defaultTextFormat = new TextFormat( null, 27 );
	effectTxt.textColor = 0x00BCE9;
	effectTxt.text = "label";
	effectTxt.filters = [ new GlowFilter( 0x00BCE9, 1, 16, 16, 2, 3 ) ];
	effectTxt.alpha = 0;

	effectTxtMask = new RectangleShape();
	effectTxtMask.copy( base );
	effectTxtMask.filters = [];
	effectTxt.mask = effectTxtMask;

	toggleBase = new RectangleShape();
	toggleBase.height = BUTTON_HEIGHT;
	toggleBase.ellipseHeight = toggleBase.ellipseWidth = BUTTON_HEIGHT;
	toggleBase.fillGradientRotation = 90;
	toggleBase.fillColors = [ 0x00CDFF, 0x00A9D2 ];
	toggleBase.lineColors = [ 0x00A9D2 ];
	toggleBase.lineAlphas = [ .5 ];
	toggleBase.lineRatios = [ 1 ];
	toggleBase.visible = false;
	toggleBase.alpha = 0;
	toggleBase.filters = [ new BevelFilter( 5, 45, 0xFFFFFF, 1, 0, .6, 18, 18, 1, 3, "inner" ), new GlowFilter( 0x00BCE9, .8, 6, 6, 1, 3 ) ];

	toggleGlass = new RectangleShape();
	toggleGlass.copy( toggleBase );
	toggleGlass.fillColors = [ 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF ];
	toggleGlass.fillAlphas = [ 0, .3, .2, .3 ];
	toggleGlass.fillRatios = [ 1, 127, 127, 255 ];
	toggleGlass.filters = [ new DropShadowFilter( 0, 45, 0xFFFFFF, .8, 10, 10, 2, 3, true ) ];
	toggleGlass.visible = false;

	toggleTxt = new TextField();
	toggleTxt.selectable = false;
	toggleTxt.type = "dynamic";
	toggleTxt.wordWrap = false;
	toggleTxt.multiline = false;
	toggleTxt.autoSize = "left";
	toggleTxt.defaultTextFormat = new TextFormat( null, 27 );
	toggleTxt.textColor = 0xFFFFFF;
	toggleTxt.text = "label";
	toggleTxt.filters = [ new BevelFilter( 1, 45, 0, .4, 0xFFFFFF, 1, 2, 2, 2, 3, "inner" ), new GlowFilter( 0xFFFFFF, 1, 16, 16, 2, 3 ) ];
	toggleTxt.alpha = 0;
	toggleTxt.visible = false;

	toggleTxtMask = new RectangleShape();
	toggleTxtMask.copy( base );
	toggleTxtMask.filters = [];
	toggleTxt.mask = toggleTxtMask;

	circleBlur = new BlurFilter( 5, 5, 3 );
	circles = [];
	tweens = [];

	addChild( base );
	addChild( light );
	addChild( ref );
	addChild( txt );
	addChild( txtMask );
	addChild( glow );
	addChild( effectContainer );
	addChild( effectMask );
	addChild( effectTxt );
	addChild( effectTxtMask );
	addChild( toggleBase );
	addChild( toggleGlass );
	addChild( toggleTxt );
	addChild( toggleTxtMask );

	createEffect();
	update();

	addEventListener( "rollOver", overState );
	addEventListener( "rollOut", outState );
	addEventListener( "mouseDown", downState );
	addEventListener( "mouseUp", upState );
}

We have just created the all of the objects that we need for what I call the active state. When the button's _toggle property is set to true, the button behaves differently. We'll see how in a moment. First add the following lines of code to the update method.

toggleBase.width = _width;
toggleTxtMask.width = _width;
toggleGlass.width = _width;
toggleTxt.x = txt.x;
toggleTxt.y = txt.y;

Now create two new methods. The goActive method and the goInactive method.

private function goActive():void {

	if ( !_active ) {

		_active = true;
		TweenMax.allTo( [ toggleBase, toggleGlass, toggleTxt ], .4, { autoAlpha:1 } );
		TweenMax.to( glow, 1, { alpha:1 } );
	}
}

private function goInactive():void {

	if ( _active ) {

		_active = false;
		TweenMax.allTo( [ toggleBase, toggleGlass, toggleTxt ], .4, { autoAlpha:0 } );
	}
}

Let's take a quick look at each method. The goActive method animates to the active state only if the button is inactive. It then set's the _active property to true. The goInactive method does the complete opposite. If the button is active, it returns to an inactive state and sets the _active property to false.

Now for the final step in creating toggle behavior for our button. Add this code to the upState method.

if ( e && _toggle ) {

	if ( _active ) {

		goInactive();
	}
	else {

		goActive();
	}
}

The code above checks to see if the method has been called do to an event being dispatched (we don't want this block of code to execute otherwise) and it checks to see if the button's toggle property has been enabled. Then the button travels to the appropriate state based on its current state. In other words, it toggles.

Set the _toggle property to true somewhere in the constructor and test the movie.

We now have a beautiful button. There's just one last problem. Our button isn't editable - well, not from outside of itself anyway. So, next were going to create the class's getters and setters.

Step 23: Edit This

First let's override the width property to give access to our custom _width property.

public override function set width( value:Number ):void {

	if ( value < 0 ) value = 0;
	_width = value;
	update();
}

public override function get width():Number {

	return _width;
}

Don't allow the value to be lower than zero. Set the _width property and call the update method.

Now override the height property.

public override function set height( value:Number ):void {

	throw new Error( "Property 'height' has been overriden and is now read-only." );
}

public override function get height():Number {

	return BUTTON_HEIGHT;
}

Trying to set the height property just throws an error because this property now has a fixed value which is the BUTTON_HEIGHT constant.

Create the following getter and setter methods.

public function set label( value:String ):void {

	txt.text = value;
	effectTxt.text = value;
	toggleTxt.text = value;
	update();
}

public function get label():String {

	return txt.text;
}

public function set active( value:Boolean ):void {

	if ( value ) {

		goActive();
	}
	else {

		goInactive();
	}
}

public function get active():Boolean {

	return _active;
}

public function set toggle( value:Boolean ):void {

	_toggle = value;

	if ( !value && active ) goInactive();
}

public function get toggle():Boolean {

	return _toggle;
}

When the label is set we immediatly react to the change by setting the text values of all of the TextField objects and we position them by calling the update method. The active property changes states based on the new value. When we set the toggle property, if it's new value is false we check to see if the button is active and if it is we switch it to its original state.

Trying setting the width property to 300 and the label to "Push Me", and making the button an active toggle button.

Step 24: More Depth

I said earlier that we would add more depth to the button. I also said that the tiny details make a large difference. Well this can be accomplished very quickly and easily by applying a couple of filters. Add these two lines of code anywhere in the constructor method. Then test the movie.

base.filters = [ new DropShadowFilter( 5, 45, 0, .6, 6, 6, 1, 3 ), new BevelFilter( 0, 0, 0xFFFFFF, .5, 0, .5, 10, 10, 1, 3 ) ];
txt.filters = [ new DropShadowFilter( 3, 45, 0, 1, 6, 6, 1, 3 ) ];

Let's see what we have now. The button on top is the original and the button on the button is the new and improved button with the above filters.

Wow! Look at that button pop out. Now you can see how important it is to use filters when drawing graphics to add in shadows and other little details that make your graphics that much better.

Extras

There are a couple of features within the EditableShape class that we didn't have time to use. One feature is the clone method. It returns a clone of the parent shape. Another is the useBitmapFill property. You must specify a valid BitmapData object by setting the bitmapData property and you have to set useBitmapFill to true.

Here's our button with a bitmap fill applied to the base property.

I also didn't discuss the matchGradientSize property which is true by default. If set to false the width and height of the fill and line gradients will not mimic the size of the actual shape. You can get create by deactivating this property. You can even use TweenLite (or TweenMax) to animate these and most of the properties in the EditableShape class.

Conclusion

Well our button is complete and our client is happy. We have only scratched the surface. There's a lot more that you can do with Flash's drawing API. I challenge you to make a CustomShape class that extends EditableShape. The class should use the lineTo methods of the graphics object to draw irregular shapes. Have fun with it. Thanks for tuning in. We've learned a lot. See you next time.



View full post on Activetuts+

Nov 8, 2011 Posted on Nov 8, 2011 in Hints and Tips | 10 comments

Create a QR Code Generator in Flash Using AS3

QR codes are everywhere these days: magazine advertisements, billboards, even TV commercials. Chances are you have a phone in your pocket that can read a QR code and decode the URL or message contained within. In this tutorial, you’ll learn how to create a SWF that can reverse the process: create a QR code from a URL or message. Read on!


Final Result Preview

Let’s take a look at the final app we will be working towards:


Step 1: Brief Overview

Using pre-made graphic elements we’ll create good looking interface that will be powered by several ActionScript 3 classes.

The code will make good use of a QR Code Encoder class, created by Jean-Baptiste Pin.


Step 2: Flash Document Settings

Open Flash and create a 480 pixels wide, 480 pixels tall document. Set the Frame rate to 24fps.


Step 3: Interface

A colorful nice looking interface will be displayed, this involves multiple shapes, buttons and more.
Simple shapes were created using the Flash Drawing Tools so it won’t be necessary to include their creation.


Step 4: Instance Names

The image above shows the Instance Names used in the MovieClips. The ones that start with a Capital Letter are Library Class Names and should not be on stage.


Step 5: TweenNano

We’ll use a different tween engine from the default included in Flash, this will increase performace as well as being easier to use.

You can download TweenNano from its official website.


Step 6: QR Code Library

We’ll make use of a fantastic QR Code Encoder library which can be downloaded from here. You can learn more about using external libraries in your code with this tutorial.


Step 7: Set Main Class

Add the class name to the Class field in the Publish section of the Properties panel to associate the FLA with the Main document class.


Step 8: Create a New ActionScript Class

Create a new (Cmd + N) ActionScript 3.0 Class and save it as Main.as in your class folder.


Step 9: Class Structure

Create your basic class structure to begin writing your code.

package
{
	import flash.display.Sprite;

	public class Main extends Sprite
	{
		public function Main():void
		{
			// constructor code
		}
	}
}

Step 10: Required Classes

These are the classes we’ll need to import for our class to work, the import directive makes externally defined classes and packages available to your code.

import flash.display.Sprite;
import flash.events.MouseEvent;
import org.qrcode.QRCode;
import flash.display.Bitmap;
import com.greensock.TweenNano;
import com.greensock.easing.Expo;

Step 11: Variables

These are the variables we’ll use, read the comments in the code to know more about them, some of their names are self explaining so there will be no comment there.

private var textView:TextView;
private var smsView:SMSView = new SMSView();
private var emailView:EmailView = new EmailView();
private var linkView:LinkView = new LinkView();
private var lastView:Sprite;
private var currentTarget:String; //current string to convert
private var qrImg:Bitmap;

Step 12: Constructor

The constructor is a function that runs when an object is created from a class, this code is the first to execute when you make an instance of an object or runs using the Document Class.

It calls the necessary functions to start the app. Check those functions in the next steps.

public final function Main():void
{
	addTextView();
	addListeners();
}

Step 13: Add Text View

The first function executed by the constructor. It will instantiate the TextView and add it to the stage. This will be the default view that will be shown starting the application. It includes a call to remove the currently visible view (in case there’s one) and also performs a Tween as a detail to the interface.

private final function addTextView():void
{
	removeLastView();

	textView = new TextView();
	textView.x = stage.stageWidth * 0.5;
	textView.y = 110;
	addChild(textView);

	TweenNano.from(textView, 0.5, {y: textView.y - 10, alpha:0, ease:Expo});

	lastView = textView;
}

Step 14: SMS View

This code handles the SMSView position and animation. It is called when the SMS button tab is pressed.

private final function addSMSView():void
{
	removeLastView();

	smsView = new SMSView();
	smsView.x = stage.stageWidth * 0.5;
	smsView.y = 150;
	addChild(smsView);

	TweenNano.from(smsView, 0.5, {y: smsView.y - 10, alpha:0, ease:Expo});

	lastView = smsView;
}

Step 15: Email View

The EmailView code. It will place and animate this view on the stage.

private final function addEmailView():void
{
	removeLastView();

	emailView = new EmailView();
	emailView.x = stage.stageWidth * 0.5;
	emailView.y = 155;
	addChild(emailView);

	TweenNano.from(emailView, 0.5, {y: emailView.y - 10, alpha:0, ease:Expo});

	lastView = emailView;
}

Step 16: Link View

This is the final tab, it removes the last visible view and adds the LinkView to the stage.

private final function addLinkView():void
{
	removeLastView();

	linkView = new LinkView();
	linkView.x = stage.stageWidth * 0.5;
	linkView.y = 110;
	addChild(linkView);

	TweenNano.from(linkView, 0.5, {y: linkView.y - 10, alpha:0, ease:Expo});

	lastView = linkView;
}

Step 17: Remove Last View

This function removes the currently visible view from the stage and frees it up for garbage collection.

private final function removeLastView():void
{
	if(lastView != null)
	{
		removeChild(lastView);
		lastView = null;
	}
}

Step 18: Add Listeners

The next code links the buttons to their corresponding functions. This will enable the tab based navigation.

private final function addListeners():void
{
	abcBtn.addEventListener(MouseEvent.MOUSE_UP, indicatorHandler);
	smsBtn.addEventListener(MouseEvent.MOUSE_UP, indicatorHandler);
	emailBtn.addEventListener(MouseEvent.MOUSE_UP, indicatorHandler);
	linkBtn.addEventListener(MouseEvent.MOUSE_UP, indicatorHandler);
	refreshBtn.addEventListener(MouseEvent.MOUSE_UP, refreshCode);
}

Step 19: Indicator Handler

The Indicator MovieClip is the little arrow that shows the active tab. This function places it in the correct position and calls the tab function.

private final function indicatorHandler(e:MouseEvent):void
{
	indicator.x = e.target.x;

	switch(e.target.name)
	{
		case 'abcBtn':
			addTextView();
			break;
		case 'smsBtn':
			addSMSView();
			break;
		case 'emailBtn':
			addEmailView();
			break;
		case 'linkBtn':
			addLinkView();
			break;
		default:
			trace('Button Names Error');
	}
}

Step 20: Refresh QR Code

This function will run when the Refresh button is pressed, it determines the current string to convert and the QRObject encode() method to generate a bitmap that is next added to the stage.

private final function refreshCode(e:MouseEvent):void
{
	switch(lastView)
	{
		case textView:
			currentTarget = textView.textTF.text;
			break;
		case smsView:
			currentTarget = 'SMSTO:' + smsView.phoneTF.text + ':' + smsView.contentTF.text;
			break;
		case emailView:
			currentTarget = 'SMTP:' + emailView.toTF.text + ':' + emailView.subjectTF.text + ':' + emailView.bodyTF.text;
			break;
		case linkView:
			currentTarget = linkView.linkTF.text;
			if (currentTarget.indexOf('://') == -1)
			{
				currentTarget = 'http://' + currentTarget;	//automatically add http:// to the front of links if required
			}
			break;
		default:
			trace('Target Error');
	}

	if(qrImg != null)
	{
		removeChild(qrImg);
		qrImg = null;
	}

	var qrObj:QRCode = new QRCode();
	qrObj.encode(currentTarget);

	qrImg = new Bitmap(qrObj.bitmapData);

	qrImg.x = stage.stageWidth * 0.5 - (qrImg.width * 0.5);
	qrImg.y = 300 - (qrImg.height * 0.5);

	addChild(qrImg);

	TweenNano.from(qrImg, 1, {alpha:0, ease:Expo});
}

Conclusion

Use this application to generate your custom QR Codes and remember to explore the source files.

I hope you liked this tutorial, thank you for reading!



View full post on Activetuts+

Page 1 of 41234»
search search search search search
Find an Article
Categories
  • Flash Video Training
  • Hints and Tips
  • Recommended
Please Support Our Sponsors
Recent Posts
  • Tuts+ Community Meetup in New York!
  • HTML5 Canvas Optimization: A Practical Example
  • Recreate the Cover Flow Effect Using Flash and AS3
  • Drawing Activetuts+ to a Close
  • Intro to Dart: Creating a Marquee
Tag Cloud
2011 ActionScript Active Activetuts+ Adobe animation Basic Basix Best Build Button Character Code Create Creating Critique Custom design Effect Effects Files Flash from Game Guide HTML5 Introduction Macromedia Motion Muzzle part Player Premium Professional Quick Silverlight Simple Text Tool Tutorial Tuts+ Using Video website Workshop
About Our Site:

Hey there and welcome to "Flash Video Training Source", a resource for anybody interested in learning more about Adobe's great tool. We feature educational videos, which will help you master Adobe Flash and help you get to know all of its features. We at "Flash Video Training Source" believe that video training and video... more

Why don't you follow us on Twitter and get the latest video tutorials twitted to your account. Just click on the floating twitter bar to your right!

Go Back In Time
May 2013
M T W T F S S
« Jul    
 12345
6789101112
13141516171819
20212223242526
2728293031  
Pretty Blank Box
top

Blogroll

  • Development Blog
  • Documentation
  • Plugins
  • Suggest Ideas
  • Support Forum
  • Themes
  • WordPress Planet

Meta

  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org

Archives

  • July 2012
  • June 2012
  • May 2012
  • April 2012
  • March 2012
  • February 2012
  • January 2012
  • December 2011
  • November 2011
  • October 2011
  • September 2011
  • August 2011
  • July 2011
  • June 2011
  • May 2011
  • April 2011
  • March 2011
  • February 2011
  • January 2011
  • December 2010
  • November 2010
  • October 2010
  • September 2010
  • August 2010
  • July 2010
  • June 2010
  • May 2010
  • April 2010
Powered by WordPress  |  Designed by Elegant Themes  |  Lightning Fast Hosting by Site 5 Hosting