Adobe MAX 2008 kicks off with Shantanu Narayen, troche Adobe CEO.

I will do some live blogging from MAX. All post are being typed on my iPhone, due to my broken laptop, so do not expect a lot of details.

Over 5000 in attendence.

Followed by 2 more MAX conferences in europe and Asia.

Flash catalyst announced, previously Thurmo.

(Red) Wire announced, delivered on AIR. $5 a month.

Kevin Lynch on stage.

Cloud and client. Across multiple screens/devices.

Flash player 10 is awesome.
Audio waveform data, 3D, text engine, drawing API, pixel blender.
FAST realtime processing.

Adobe MAX 2008 kicks off with Shantanu Narayen, troche Adobe CEO.

I will do some live blogging from MAX. All post are being typed on my iPhone, due to my broken laptop, so do not expect a lot of details.

Over 5000 in attendence.

Followed by 2 more MAX conferences in europe and Asia.

Flash catalyst announced, previously Thurmo.

(Red) Wire announced, delivered on AIR. $5 a month.

Kevin Lynch on stage.

Cloud and client. Across multiple screens/devices.

Flash player 10 is awesome.
Audio waveform data, 3D, text engine, drawing API, pixel blender.
FAST realtime processing.

Max keynote is available online now. keynote

I cannot do it justice from my iPhone, pilule so check it out.

Updates:

Apparantly the keynote video does not live at the address I placed above, visit web that is what was on the big screen at the end of the keynote. sorry about that.
Here are a couple links of real live blogging (bet they had a laptop).
Liveblogging MAX 2008 Day 1 General Session Keynote

Adobe MAX 2008: Monday – Keynote

Tour de Flex on a 20′ screen, shot by Greg Wilson. Tour de Flex on a 20 ft Screen
Adobe MAX 2008 kicks off with Shantanu Narayen, troche Adobe CEO.

I will do some live blogging from MAX. All post are being typed on my iPhone, due to my broken laptop, so do not expect a lot of details.

Over 5000 in attendence.

Followed by 2 more MAX conferences in europe and Asia.

Flash catalyst announced, previously Thurmo.

(Red) Wire announced, delivered on AIR. $5 a month.

Kevin Lynch on stage.

Cloud and client. Across multiple screens/devices.

Flash player 10 is awesome.
Audio waveform data, 3D, text engine, drawing API, pixel blender.
FAST realtime processing.

Max keynote is available online now. keynote

I cannot do it justice from my iPhone, pilule so check it out.

Updates:

Apparantly the keynote video does not live at the address I placed above, visit web that is what was on the big screen at the end of the keynote. sorry about that.
Here are a couple links of real live blogging (bet they had a laptop).
Liveblogging MAX 2008 Day 1 General Session Keynote

Adobe MAX 2008: Monday – Keynote

Tour de Flex on a 20′ screen, shot by Greg Wilson. Tour de Flex on a 20 ft Screen
The first day of MAX has ended at 10:30 pm Monday night. East coast time is taking it’s toll, sales but I know I am not the only one. I just finished moderating a video tips group that was full of drooping eyes.

Today was a success with 4 new t-shirts and a few new tips learned. All of the sessions are going to be available for free at Adobe TV. I have heard the Flash Catylist (thermo) sessions were really good, information pills the Flash Player Internals session had some nice insight on optimizing code, this my favorite one of the day. The Flex Tips session showed off some features of Flex Builder that I never new existed and now will not be able to live without.

MAX 2008 Sessions added to Adobe TV – 12/11/08

MAX 2008 on Adobe TV.

Adobe MAX 2008 kicks off with Shantanu Narayen, troche Adobe CEO.

I will do some live blogging from MAX. All post are being typed on my iPhone, due to my broken laptop, so do not expect a lot of details.

Over 5000 in attendence.

Followed by 2 more MAX conferences in europe and Asia.

Flash catalyst announced, previously Thurmo.

(Red) Wire announced, delivered on AIR. $5 a month.

Kevin Lynch on stage.

Cloud and client. Across multiple screens/devices.

Flash player 10 is awesome.
Audio waveform data, 3D, text engine, drawing API, pixel blender.
FAST realtime processing.

Max keynote is available online now. keynote

I cannot do it justice from my iPhone, pilule so check it out.

Updates:

Apparantly the keynote video does not live at the address I placed above, visit web that is what was on the big screen at the end of the keynote. sorry about that.
Here are a couple links of real live blogging (bet they had a laptop).
Liveblogging MAX 2008 Day 1 General Session Keynote

Adobe MAX 2008: Monday – Keynote

Tour de Flex on a 20′ screen, shot by Greg Wilson. Tour de Flex on a 20 ft Screen
The first day of MAX has ended at 10:30 pm Monday night. East coast time is taking it’s toll, sales but I know I am not the only one. I just finished moderating a video tips group that was full of drooping eyes.

Today was a success with 4 new t-shirts and a few new tips learned. All of the sessions are going to be available for free at Adobe TV. I have heard the Flash Catylist (thermo) sessions were really good, information pills the Flash Player Internals session had some nice insight on optimizing code, this my favorite one of the day. The Flex Tips session showed off some features of Flex Builder that I never new existed and now will not be able to live without.

MAX 2008 Sessions added to Adobe TV – 12/11/08

MAX 2008 on Adobe TV.

In a Birds-Of-A-Feather discussion group at Adobe MAX last week. No remarks were planned, search It was supposed to be a discussion, stuff we hoped to talk to other developers about what’s new in using Flash video. We did not get a bunch of new information but we did get a lot of hard questions. Some of them were not fully answered and others were speculated upon. When I was asked my tips, I gave all I could think of at the time. Later that evening I remembered a couple more, some of my best ones.

So for those who went to MAX and those that did not, here are my official video tips for Flash and Flex.

Disclaimer: Technology changes on a regular basis, as of the date of this post I feel very comfortable with the statements made below. As new versions of software are released some of the comments may become outdated.

1. Your source file is king when it comes to getting good quality video. A good source file is the difference between hulu and youtube video. If you have control over your video source, make sure you get a good high-res lossless video file. They are huge and some clients do not know what you are talking about when you ask for it, but try your best to get a good source file.

2. Encode your own files. There are many flv encoders out there, some even your clients can use. But if you want good quality, then encode them yourselves. Of course some clients are pretty savvy when it comes to these things, in that case train them.

3. Use the Flash Video Encoder standalone application. *I have exported flv’s from many other programs, but quality is more consistent with the Flash Video Encoder application. Plus the encoding speed is a lot better with the Flash Video Encoder. It does suck to encode something twice, once to a lossless file, then a second time to flv, but in my testing it has been worth it.
(*H.264 can be encoded from other applications with equal quality. I have not compared them yet, but it is a very standard codec.)

4. If you do not have Flash CS4, use on2 VP6 encoding, it is much better than the other codec options. H.264 is a great improvement even over on2 VP6. Mp4 files can use different codecs, so make sure you are using H.246 and mp3 audio if you are encoding with other applications.

5. Not all video files are the same. Video containing a lot of motion/action can not handle as much compression as a low motion, talking head video. You will have to test your video files and encode each file with different settings to get optimum performance, size and quality. Also if you have control over the editing of your source files, certain video transitions (cross dissolve) encode worse than others.

6. Do not change frame rate when encoding an flv. This will cause your a/v sync to drift. Any edits to frame rate needs to be made in your source file before you encode. This does not apply to video without sound.

7. Dropping FPS and lowering the Key Frame Interval can lower file size of the flv, but there are consequences. For lowering frame rate, see number 6. Lowering the frame rate interval will effect fast-forwarding and rewinding and may effect syncing between key frames. If you need smooth fast forward and rewind, then leave the key frame interval to automatic or raise it a little more. I believe it is set to 24 frames by default.

8. If you want to have good streaming performance, place your streaming files on a server setup for streaming content. There could be cross-domain security sandbox issues, if your files do not load, first check if you need a crossdomain.xml file.

9. Video has come along way from the timeline full of image sequences from pre Flash MX days. Video still has a large file size that can only be compressed so far. Video needs to buffer before playing and can consume a lot of CPU. If possible stop other animations, visual effects, and any processor intense code while your videos are playing.

10. There are still times when video is not the best solution. I still use image sequences if the job requires it, even though video can be the easier way to go in most cases. You may have to push your animation skills to pull off video type effects. Building your animation in Flash will give you more control over the size and quality of your project.
Adobe MAX 2008 kicks off with Shantanu Narayen, troche Adobe CEO.

I will do some live blogging from MAX. All post are being typed on my iPhone, due to my broken laptop, so do not expect a lot of details.

Over 5000 in attendence.

Followed by 2 more MAX conferences in europe and Asia.

Flash catalyst announced, previously Thurmo.

(Red) Wire announced, delivered on AIR. $5 a month.

Kevin Lynch on stage.

Cloud and client. Across multiple screens/devices.

Flash player 10 is awesome.
Audio waveform data, 3D, text engine, drawing API, pixel blender.
FAST realtime processing.

Max keynote is available online now. keynote

I cannot do it justice from my iPhone, pilule so check it out.

Updates:

Apparantly the keynote video does not live at the address I placed above, visit web that is what was on the big screen at the end of the keynote. sorry about that.
Here are a couple links of real live blogging (bet they had a laptop).
Liveblogging MAX 2008 Day 1 General Session Keynote

Adobe MAX 2008: Monday – Keynote

Tour de Flex on a 20′ screen, shot by Greg Wilson. Tour de Flex on a 20 ft Screen
The first day of MAX has ended at 10:30 pm Monday night. East coast time is taking it’s toll, sales but I know I am not the only one. I just finished moderating a video tips group that was full of drooping eyes.

Today was a success with 4 new t-shirts and a few new tips learned. All of the sessions are going to be available for free at Adobe TV. I have heard the Flash Catylist (thermo) sessions were really good, information pills the Flash Player Internals session had some nice insight on optimizing code, this my favorite one of the day. The Flex Tips session showed off some features of Flex Builder that I never new existed and now will not be able to live without.

MAX 2008 Sessions added to Adobe TV – 12/11/08

MAX 2008 on Adobe TV.

In a Birds-Of-A-Feather discussion group at Adobe MAX last week. No remarks were planned, search It was supposed to be a discussion, stuff we hoped to talk to other developers about what’s new in using Flash video. We did not get a bunch of new information but we did get a lot of hard questions. Some of them were not fully answered and others were speculated upon. When I was asked my tips, I gave all I could think of at the time. Later that evening I remembered a couple more, some of my best ones.

So for those who went to MAX and those that did not, here are my official video tips for Flash and Flex.

Disclaimer: Technology changes on a regular basis, as of the date of this post I feel very comfortable with the statements made below. As new versions of software are released some of the comments may become outdated.

1. Your source file is king when it comes to getting good quality video. A good source file is the difference between hulu and youtube video. If you have control over your video source, make sure you get a good high-res lossless video file. They are huge and some clients do not know what you are talking about when you ask for it, but try your best to get a good source file.

2. Encode your own files. There are many flv encoders out there, some even your clients can use. But if you want good quality, then encode them yourselves. Of course some clients are pretty savvy when it comes to these things, in that case train them.

3. Use the Flash Video Encoder standalone application. *I have exported flv’s from many other programs, but quality is more consistent with the Flash Video Encoder application. Plus the encoding speed is a lot better with the Flash Video Encoder. It does suck to encode something twice, once to a lossless file, then a second time to flv, but in my testing it has been worth it.
(*H.264 can be encoded from other applications with equal quality. I have not compared them yet, but it is a very standard codec.)

4. If you do not have Flash CS4, use on2 VP6 encoding, it is much better than the other codec options. H.264 is a great improvement even over on2 VP6. Mp4 files can use different codecs, so make sure you are using H.246 and mp3 audio if you are encoding with other applications.

5. Not all video files are the same. Video containing a lot of motion/action can not handle as much compression as a low motion, talking head video. You will have to test your video files and encode each file with different settings to get optimum performance, size and quality. Also if you have control over the editing of your source files, certain video transitions (cross dissolve) encode worse than others.

6. Do not change frame rate when encoding an flv. This will cause your a/v sync to drift. Any edits to frame rate needs to be made in your source file before you encode. This does not apply to video without sound.

7. Dropping FPS and lowering the Key Frame Interval can lower file size of the flv, but there are consequences. For lowering frame rate, see number 6. Lowering the frame rate interval will effect fast-forwarding and rewinding and may effect syncing between key frames. If you need smooth fast forward and rewind, then leave the key frame interval to automatic or raise it a little more. I believe it is set to 24 frames by default.

8. If you want to have good streaming performance, place your streaming files on a server setup for streaming content. There could be cross-domain security sandbox issues, if your files do not load, first check if you need a crossdomain.xml file.

9. Video has come along way from the timeline full of image sequences from pre Flash MX days. Video still has a large file size that can only be compressed so far. Video needs to buffer before playing and can consume a lot of CPU. If possible stop other animations, visual effects, and any processor intense code while your videos are playing.

10. There are still times when video is not the best solution. I still use image sequences if the job requires it, even though video can be the easier way to go in most cases. You may have to push your animation skills to pull off video type effects. Building your animation in Flash will give you more control over the size and quality of your project.

Using Random in Game Development, buy with strict guidelines, order can bring some variety to game play.

This sample is not a single solution but an approached I used in developing Whacky Voting – a politically smashing game. It uses random with some strict rules to get rid of sequences that some players can easily remember, yet keeping game play consistent from one game to the next.

This demo starts with a configuration section, used to set up how we want the game to act. The engine it self could be organized a little better to be more transportable. It is commented pretty well though, so it should be easy enough to understand the approach as well as practical usage. Random is used to shuffle all of the objects that appear on screen as well as what container the objects are associated with.

Configuration:
We use config data for each game so that we can easily tweak game-play without hacking our code later. We can use arrays, xml or other data sources. Plan ahead and build config options into your game as it is developed.

This array designates slots or containers to hold each appearing object. Use this to limit how many objects appear at a time and where they are placed on screen. this can represent MovieClips or other classes.

?View Code ACTIONSCRIPT
var objHolderArr:Array = [];
objHolderArr[0] = {obj:"object0",id:0,stat:false,timer:20,type:"",score:0,targ:null,xCoor:10};
objHolderArr[1] = {obj:"object1",id:1,stat:false,timer:20,type:"",score:0,targ:null,xCoor:90};
objHolderArr[2] = {obj:"object2",id:2,stat:false,timer:20,type:"",score:0,targ:null,xCoor:170};
objHolderArr[3] = {obj:"object3",id:3,stat:false,timer:20,type:"",score:0,targ:null,xCoor:250};
objHolderArr[4] = {obj:"object4",id:4,stat:false,timer:20,type:"",score:0,targ:null,xCoor:330};
objHolderArr[5] = {obj:"object5",id:5,stat:false,timer:20,type:"",score:0,targ:null,xCoor:410};

Next is an array of objects to appear, this is to control what type of objects appear and to make sure they are nicely distributed through out each level. You may have different scores, wilds and/or bonus score objects that need to get incorporated into the object list, but using random by it self will not allow them to be distributed appropriately for consistent game play.

?View Code ACTIONSCRIPT
var objSequenceArr:Array = [];
objSequenceArr[0] = {obj:"type0", count:20,score:100};
objSequenceArr[1] = {obj:"type1", count:15, score:150};
objSequenceArr[2] = {obj:"type2", count:5, score:500};
objSequenceArr[3] = {obj:"type3", count:5, score:1000};
objSequenceArr[4] = {obj:"null", count:5, score:0};
 
//timer increment for the engine to trigger an event
var timeInc:int = 500;
 
// integer to keep track of increment of game engine
var arrLoc:int = 0;
 
// random key
var randomKey:int = 1000;
 
// time for each object to stay visible;
var delay:int = 4;

It is good to set game status variables to allow games controls to be a little more intuitive. Sometimes I use a gameStatus string variable and a string to denote the current status. That way I can get more mileage out of one variable.

?View Code ACTIONSCRIPT
var gameOver:Boolean;
 
//or
 
var gameStatus:String = "_play";

Build Config Data for Engine:
The current level array built from config data above. The method then adds to the level array all the objects that we want to appear during the game.

?View Code ACTIONSCRIPT
var levelArr:Array = [];
 
function buildConfigData():void{
for(var p:String in objSequenceArr){
var loopCnt:int = objSequenceArr[p].count;
for(var i:uint = 0; i < loopCnt; i++){
var randNum:int = randomNumber(randomKey);
levelArr.push({obj:objSequenceArr[p].obj, score:objSequenceArr[p].score, key:randNum});
}
}
 
levelArr.sortOn("key",Array.NUMERIC || Array.DESCENDING);
}
buildConfigData();

Last, we sort the list so that it is shuffled which gives us the first random effect. All the objects are placed in the array in order of the sequence array, but we added a random number as the key to sort the array with. Now all of the objects will be randomly placed throughout the array and we will always have the right amount of objects for consistent game play.

Game Engine:
Now that we have our data, we are ready to start the engine.

1. Pull first random number

2. Loop until random number is not a slot that is already taken. We add a break and status variable to stop the loop if we can not find an available object. On a break, we will wait until the next TimerEvent and try again.

3. We have an active slot that is not already taken, we set it’s status to true and show and configure our object.

4. Use this timer event to also run our Active Checker Method below. The more you can piggy-back off of single timers and EnterFrame events the better.

?View Code ACTIONSCRIPT
var timer:Timer = new Timer(timeInc,0);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
 
function timerHandler(ev:TimerEvent):void{
 
//1.
var randSlot:int = randomNumber(objHolderArr.length);
 
//2.
if(arrLoc < levelArr.length){
if(levelArr[arrLoc].obj != "null"){
var breakCnt:int
var breakStatus:Boolean;
while(objHolderArr[randSlot].stat == true){
randSlot = randomNumber(objHolderArr.length);
breakCnt ++;
if(breakCnt >= 100){
breakStatus = true;
break;
}
}
 
if(!breakStatus){
//3.
var slotObj:Object = objHolderArr[randSlot];
slotObj.stat = true;
slotObj.timer = delay;
slotObj.score = levelArr[arrLoc].score;
slotObj.type = levelArr[arrLoc].type;
 
//******* add code here to initiate your visual objects.
var tempBO:ballObj = new ballObj();
tempBO.x = slotObj.xCoor;
tempBO.y = 20;
tempBO.objIDStr = arrLoc.toString();
tempBO.objScoreStr = levelArr[arrLoc].score;
tempBO.objTypeStr = levelArr[arrLoc].obj;
addChild(tempBO);
 
//********* end visual code here.
 
slotObj.targ = tempBO;
activeObjArr.push(slotObj);
// we advance the array location variable.
arrLoc ++;
}
}
else{
arrLoc ++;
}
}
 
//4.
activeChecker();
}

After each object is initiated, we need to give them an amount of time to be active. This is the activeObject array, we will track the time, if the user does not score with the object then it will be removed by the timer.

1. Loop through the active array to decrease each object’s timer.

2. If the timer is run out, remove the object from the array and reset the object’s status.

?View Code ACTIONSCRIPT
var activeObjArr:Array = [];
 
function activeChecker():void{
for(var p:String in activeObjArr){
//1.
activeObjArr[p].timer --;
 
//2.
if(activeObjArr[p].timer <= 0){
activeObjArr[p].stat = false;
removeChild(activeObjArr[p].targ);
activeObjArr.splice(int(p),1);
 
if(arrLoc >= levelArr.length && activeObjArr.length == 0){
//game is over.
gameOver = true;
timer.stop();
btn.enabled = true;
btn.alpha = 1;
}
}
}
}

Here is where you can place your event handlers for a user interactive with an object. We have to remove and reset the object, shown above and add the objects score to the main score.

We will also need a method for when the game clears the last array object.

Utilities:
method to pull random numbers just so I do not need to write this same code more than once.

?View Code ACTIONSCRIPT
function randomNumber(limit:int):int{
var randNum:int = Math.random()*limit;
return randNum;
}

Controls:
A restart control availble when game is over

?View Code ACTIONSCRIPT
btn.addEventListener(MouseEvent.CLICK,clickHandler);
btn.enabled = false;
btn.alpha = 0.2;
function clickHandler(ev:MouseEvent):void{
if(gameOver){
// rebuild data to show off shuffling.
levelArr = [];
buildConfigData();
 
//reset game controls and game engine.
arrLoc = 0;
timer.start();
gameOver = false;
btn.enabled = false;
btn.alpha = 0.2;
}
}

The Ball Object:
The ball object is a simple class that displays the data for each object. You would normally place a button or some other way to capture user interaction and send it back to the engine to initiate scores and feedback.

?View Code ACTIONSCRIPT
package{
import flash.display.MovieClip;
import flash.text.TextField;
import flash.events.Event;
 
public class ballObj extends MovieClip{
 
public var objIDStr:String = "";
public var objTypeStr:String = "";
public var objScoreStr:String = "";
 
public function ballObj():void{
init();
stop();
}
 
private function init():void{
this.addEventListener(Event.ADDED,addedHandler);
}
 
private function addedHandler(ev:Event):void{
objID.text = objIDStr;
objScore.text = objScoreStr;
objType.text = objTypeStr;
 
}
}
}

Source Here
Adobe MAX 2008 kicks off with Shantanu Narayen, troche Adobe CEO.

I will do some live blogging from MAX. All post are being typed on my iPhone, due to my broken laptop, so do not expect a lot of details.

Over 5000 in attendence.

Followed by 2 more MAX conferences in europe and Asia.

Flash catalyst announced, previously Thurmo.

(Red) Wire announced, delivered on AIR. $5 a month.

Kevin Lynch on stage.

Cloud and client. Across multiple screens/devices.

Flash player 10 is awesome.
Audio waveform data, 3D, text engine, drawing API, pixel blender.
FAST realtime processing.

Max keynote is available online now. keynote

I cannot do it justice from my iPhone, pilule so check it out.

Updates:

Apparantly the keynote video does not live at the address I placed above, visit web that is what was on the big screen at the end of the keynote. sorry about that.
Here are a couple links of real live blogging (bet they had a laptop).
Liveblogging MAX 2008 Day 1 General Session Keynote

Adobe MAX 2008: Monday - Keynote

Tour de Flex on a 20' screen, shot by Greg Wilson. Tour de Flex on a 20 ft Screen
The first day of MAX has ended at 10:30 pm Monday night. East coast time is taking it's toll, sales but I know I am not the only one. I just finished moderating a video tips group that was full of drooping eyes.

Today was a success with 4 new t-shirts and a few new tips learned. All of the sessions are going to be available for free at Adobe TV. I have heard the Flash Catylist (thermo) sessions were really good, information pills the Flash Player Internals session had some nice insight on optimizing code, this my favorite one of the day. The Flex Tips session showed off some features of Flex Builder that I never new existed and now will not be able to live without.

MAX 2008 Sessions added to Adobe TV - 12/11/08

MAX 2008 on Adobe TV.

In a Birds-Of-A-Feather discussion group at Adobe MAX last week. No remarks were planned, search It was supposed to be a discussion, stuff we hoped to talk to other developers about what's new in using Flash video. We did not get a bunch of new information but we did get a lot of hard questions. Some of them were not fully answered and others were speculated upon. When I was asked my tips, I gave all I could think of at the time. Later that evening I remembered a couple more, some of my best ones.

So for those who went to MAX and those that did not, here are my official video tips for Flash and Flex.

Disclaimer: Technology changes on a regular basis, as of the date of this post I feel very comfortable with the statements made below. As new versions of software are released some of the comments may become outdated.

1. Your source file is king when it comes to getting good quality video. A good source file is the difference between hulu and youtube video. If you have control over your video source, make sure you get a good high-res lossless video file. They are huge and some clients do not know what you are talking about when you ask for it, but try your best to get a good source file.

2. Encode your own files. There are many flv encoders out there, some even your clients can use. But if you want good quality, then encode them yourselves. Of course some clients are pretty savvy when it comes to these things, in that case train them.

3. Use the Flash Video Encoder standalone application. *I have exported flv's from many other programs, but quality is more consistent with the Flash Video Encoder application. Plus the encoding speed is a lot better with the Flash Video Encoder. It does suck to encode something twice, once to a lossless file, then a second time to flv, but in my testing it has been worth it.
(*H.264 can be encoded from other applications with equal quality. I have not compared them yet, but it is a very standard codec.)

4. If you do not have Flash CS4, use on2 VP6 encoding, it is much better than the other codec options. H.264 is a great improvement even over on2 VP6. Mp4 files can use different codecs, so make sure you are using H.246 and mp3 audio if you are encoding with other applications.

5. Not all video files are the same. Video containing a lot of motion/action can not handle as much compression as a low motion, talking head video. You will have to test your video files and encode each file with different settings to get optimum performance, size and quality. Also if you have control over the editing of your source files, certain video transitions (cross dissolve) encode worse than others.

6. Do not change frame rate when encoding an flv. This will cause your a/v sync to drift. Any edits to frame rate needs to be made in your source file before you encode. This does not apply to video without sound.

7. Dropping FPS and lowering the Key Frame Interval can lower file size of the flv, but there are consequences. For lowering frame rate, see number 6. Lowering the frame rate interval will effect fast-forwarding and rewinding and may effect syncing between key frames. If you need smooth fast forward and rewind, then leave the key frame interval to automatic or raise it a little more. I believe it is set to 24 frames by default.

8. If you want to have good streaming performance, place your streaming files on a server setup for streaming content. There could be cross-domain security sandbox issues, if your files do not load, first check if you need a crossdomain.xml file.

9. Video has come along way from the timeline full of image sequences from pre Flash MX days. Video still has a large file size that can only be compressed so far. Video needs to buffer before playing and can consume a lot of CPU. If possible stop other animations, visual effects, and any processor intense code while your videos are playing.

10. There are still times when video is not the best solution. I still use image sequences if the job requires it, even though video can be the easier way to go in most cases. You may have to push your animation skills to pull off video type effects. Building your animation in Flash will give you more control over the size and quality of your project.

Using Random in Game Development, buy with strict guidelines, order can bring some variety to game play.

This sample is not a single solution but an approached I used in developing Whacky Voting - a politically smashing game. It uses random with some strict rules to get rid of sequences that some players can easily remember, yet keeping game play consistent from one game to the next.

This demo starts with a configuration section, used to set up how we want the game to act. The engine it self could be organized a little better to be more transportable. It is commented pretty well though, so it should be easy enough to understand the approach as well as practical usage. Random is used to shuffle all of the objects that appear on screen as well as what container the objects are associated with.

Configuration:
We use config data for each game so that we can easily tweak game-play without hacking our code later. We can use arrays, xml or other data sources. Plan ahead and build config options into your game as it is developed.

This array designates slots or containers to hold each appearing object. Use this to limit how many objects appear at a time and where they are placed on screen. this can represent MovieClips or other classes.

?View Code ACTIONSCRIPT
var objHolderArr:Array = [];
objHolderArr[0] = {obj:"object0",id:0,stat:false,timer:20,type:"",score:0,targ:null,xCoor:10};
objHolderArr[1] = {obj:"object1",id:1,stat:false,timer:20,type:"",score:0,targ:null,xCoor:90};
objHolderArr[2] = {obj:"object2",id:2,stat:false,timer:20,type:"",score:0,targ:null,xCoor:170};
objHolderArr[3] = {obj:"object3",id:3,stat:false,timer:20,type:"",score:0,targ:null,xCoor:250};
objHolderArr[4] = {obj:"object4",id:4,stat:false,timer:20,type:"",score:0,targ:null,xCoor:330};
objHolderArr[5] = {obj:"object5",id:5,stat:false,timer:20,type:"",score:0,targ:null,xCoor:410};

Next is an array of objects to appear, this is to control what type of objects appear and to make sure they are nicely distributed through out each level. You may have different scores, wilds and/or bonus score objects that need to get incorporated into the object list, but using random by it self will not allow them to be distributed appropriately for consistent game play.

?View Code ACTIONSCRIPT
var objSequenceArr:Array = [];
objSequenceArr[0] = {obj:"type0", count:20,score:100};
objSequenceArr[1] = {obj:"type1", count:15, score:150};
objSequenceArr[2] = {obj:"type2", count:5, score:500};
objSequenceArr[3] = {obj:"type3", count:5, score:1000};
objSequenceArr[4] = {obj:"null", count:5, score:0};
 
//timer increment for the engine to trigger an event
var timeInc:int = 500;
 
// integer to keep track of increment of game engine
var arrLoc:int = 0;
 
// random key
var randomKey:int = 1000;
 
// time for each object to stay visible;
var delay:int = 4;

It is good to set game status variables to allow games controls to be a little more intuitive. Sometimes I use a gameStatus string variable and a string to denote the current status. That way I can get more mileage out of one variable.

?View Code ACTIONSCRIPT
var gameOver:Boolean;
 
//or
 
var gameStatus:String = "_play";

Build Config Data for Engine:
The current level array built from config data above. The method then adds to the level array all the objects that we want to appear during the game.

?View Code ACTIONSCRIPT
var levelArr:Array = [];
 
function buildConfigData():void{
for(var p:String in objSequenceArr){
var loopCnt:int = objSequenceArr[p].count;
for(var i:uint = 0; i < loopCnt; i++){
var randNum:int = randomNumber(randomKey);
levelArr.push({obj:objSequenceArr[p].obj, score:objSequenceArr[p].score, key:randNum});
}
}
 
levelArr.sortOn("key",Array.NUMERIC || Array.DESCENDING);
}
buildConfigData();

Last, we sort the list so that it is shuffled which gives us the first random effect. All the objects are placed in the array in order of the sequence array, but we added a random number as the key to sort the array with. Now all of the objects will be randomly placed throughout the array and we will always have the right amount of objects for consistent game play.

Game Engine:
Now that we have our data, we are ready to start the engine.

1. Pull first random number

2. Loop until random number is not a slot that is already taken. We add a break and status variable to stop the loop if we can not find an available object. On a break, we will wait until the next TimerEvent and try again.

3. We have an active slot that is not already taken, we set it's status to true and show and configure our object.

4. Use this timer event to also run our Active Checker Method below. The more you can piggy-back off of single timers and EnterFrame events the better.

?View Code ACTIONSCRIPT
var timer:Timer = new Timer(timeInc,0);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
 
function timerHandler(ev:TimerEvent):void{
 
//1.
var randSlot:int = randomNumber(objHolderArr.length);
 
//2.
if(arrLoc < levelArr.length){
if(levelArr[arrLoc].obj != "null"){
var breakCnt:int
var breakStatus:Boolean;
while(objHolderArr[randSlot].stat == true){
randSlot = randomNumber(objHolderArr.length);
breakCnt ++;
if(breakCnt >= 100){
breakStatus = true;
break;
}
}
 
if(!breakStatus){
//3.
var slotObj:Object = objHolderArr[randSlot];
slotObj.stat = true;
slotObj.timer = delay;
slotObj.score = levelArr[arrLoc].score;
slotObj.type = levelArr[arrLoc].type;
 
//******* add code here to initiate your visual objects.
var tempBO:ballObj = new ballObj();
tempBO.x = slotObj.xCoor;
tempBO.y = 20;
tempBO.objIDStr = arrLoc.toString();
tempBO.objScoreStr = levelArr[arrLoc].score;
tempBO.objTypeStr = levelArr[arrLoc].obj;
addChild(tempBO);
 
//********* end visual code here.
 
slotObj.targ = tempBO;
activeObjArr.push(slotObj);
// we advance the array location variable.
arrLoc ++;
}
}
else{
arrLoc ++;
}
}
 
//4.
activeChecker();
}

After each object is initiated, we need to give them an amount of time to be active. This is the activeObject array, we will track the time, if the user does not score with the object then it will be removed by the timer.

1. Loop through the active array to decrease each object's timer.

2. If the timer is run out, remove the object from the array and reset the object's status.

?View Code ACTIONSCRIPT
var activeObjArr:Array = [];
 
function activeChecker():void{
for(var p:String in activeObjArr){
//1.
activeObjArr[p].timer --;
 
//2.
if(activeObjArr[p].timer <= 0){
activeObjArr[p].stat = false;
removeChild(activeObjArr[p].targ);
activeObjArr.splice(int(p),1);
 
if(arrLoc >= levelArr.length && activeObjArr.length == 0){
//game is over.
gameOver = true;
timer.stop();
btn.enabled = true;
btn.alpha = 1;
}
}
}
}

Here is where you can place your event handlers for a user interactive with an object. We have to remove and reset the object, shown above and add the objects score to the main score.

We will also need a method for when the game clears the last array object.

Utilities:
method to pull random numbers just so I do not need to write this same code more than once.

?View Code ACTIONSCRIPT
function randomNumber(limit:int):int{
var randNum:int = Math.random()*limit;
return randNum;
}

Controls:
A restart control availble when game is over

?View Code ACTIONSCRIPT
btn.addEventListener(MouseEvent.CLICK,clickHandler);
btn.enabled = false;
btn.alpha = 0.2;
function clickHandler(ev:MouseEvent):void{
if(gameOver){
// rebuild data to show off shuffling.
levelArr = [];
buildConfigData();
 
//reset game controls and game engine.
arrLoc = 0;
timer.start();
gameOver = false;
btn.enabled = false;
btn.alpha = 0.2;
}
}

The Ball Object:
The ball object is a simple class that displays the data for each object. You would normally place a button or some other way to capture user interaction and send it back to the engine to initiate scores and feedback.

?View Code ACTIONSCRIPT
package{
import flash.display.MovieClip;
import flash.text.TextField;
import flash.events.Event;
 
public class ballObj extends MovieClip{
 
public var objIDStr:String = "";
public var objTypeStr:String = "";
public var objScoreStr:String = "";
 
public function ballObj():void{
init();
stop();
}
 
private function init():void{
this.addEventListener(Event.ADDED,addedHandler);
}
 
private function addedHandler(ev:Event):void{
objID.text = objIDStr;
objScore.text = objScoreStr;
objType.text = objTypeStr;
 
}
}
}

Source Here
This is it, about it the very first bit of actionscript code I ever learned, site besides play() and gotoAndStop() of course. The lesson went down with an experienced programmer looking over my shoulder telling me what to type. After this little app was finished, approved my brain hurt only understanding a few of the lines we wrote. That code was referenced and/or modified on more then a few projects that came after, each time deciphering more and applying it to new functionalities.

The original script was back in the day of AS1, but I am going to present it to you in AS3. If you are a beginner to ActionScript then it is the perfect time to learn AS3.

We are going to start really remedial for a minute and go over the basics of the classes and objects we will be using. It is kind-of long, so if you already have the basics covered, you can skip to the Application code.

The Variable:
Remember Pre-Algebra? 2+x = y? Variables are used for more then just place holders in a math equation. Programming is a very literal language, variables are how we make it figurative. Now instead of addressing one object with a snippet of code, that code can be applied to the many objects and properties our variables represent.

To use a variable, we must declare it using these three letters "var". Then comes the creative part, we get to think of a name. This can be a lot of fun making up funny names for things until someone else has to figure out your code or you forget that you called the variable that is going to bring balance to your application "anakin", oops, or was that "luke"?

After naming the variable, we have to declare it's type. We really don't have to, but it is a good idea. This variable will be a Number, because we will need it to include decimals.

Here are some examples of how variables can be used. Think about if we were selling apples that costs 65¢ a peace. A person wants to buy 5 apples. so we build an equation to handle the transaction.

?View Code ACTIONSCRIPT
var totalCost:Number;
totalCost = 0.65 * 5; //3.25

Ok, so we went conservitive, using "totalCost" for the total of apples purchased. Now what do we do when someone wants to buy 4 apples, or 6, or 8? Now we should add a new variable to represent the amount of apples. This variables declaration is an "int" (integer) as we will not be selling fractions of apples.

?View Code ACTIONSCRIPT
var numApples:int = 5;
var totalCost:Number;
totalCost = 0.65 * numApples; // 3.25

Everyone is happy until next week when there is an apple shortage and the price increases to 85¢ a piece. Now you have to go through you app and change all the prices from 65¢ to 85¢. If we use variables we can easily modify the app when the price changes, better yet, now this same app could be used to handle bananas, grapefruit and pears which all have different prices.

?View Code ACTIONSCRIPT
var cost:Number = 0.85;
var numFruit = 5;
var totalCost:Numer;
totalCost = cost * numFruit; // $4.25

Array:
Array is one of the most powerful classes in Flash. It's power comes from the way an array holds a collection of information. Not only do we have access to the information, but we can loop through all the items in an array and monitor the length of the collection.

This is how we might set up some variables without arrays. If we add or take away an item, we have to update a separate variable to keep track of the total amount. Looping through this is information is possible, but tricky.

?View Code ACTIONSCRIPT
var fuit1:String = "apple";
var fruit2:String = "banana";
var fruit3:String = "pear";
var fruits:int = 3;
 
// Or we can do the same thing with an array.
 
var fruitArr:Array = ["apple","banana","pear"];
 
trace(fruitArr[0]); //"apple
trace(fruitArr.length); //3

One thing that you must remember when using arrays is that they are zero indexed, meaning the first position in the array is 0. This can cause a little confusion because we teach our children to start counting at 1, not 0. This will hopefully make more sense later or maybe more confusion, but at least you will know why you are confused.

Tip: instead of useing var fruitArr:Array = new Array(); which you may have seen before. Using the square braces will do same thing. var fruitArr:Array = [];

If we think of our application as if it were an engine, the data objects (arrays, XML) are the fuel. The part of the application that interates like loops, enter frame events and timers are the heart of the engine, like the pistons, cams and crank shaft. This engine starts once the app loads and runs until we stop everything or close the app.

for() Loop:
Interates or repeats a a specified amount allowing our engine to apply the same code to multiple objects. Loops will run and complete in between each frame, before each render. This means you will not visually see what the loop is doing until it completes and the stage renders.

?View Code ACTIONSCRIPT
// This is a loop using the array from above:
for(var p:String in fruitArr){
trace(fruitArr[p] + " | index = " + p);
}
 
output:
apple | index = 0
banana | index = 1
pear | index = 2

First we assign a variable to the item that is going to loop trough the array. p stands for property and is a string. Here you can see the output of "p" which is showing the index or location of each item in the array. Notice that "apple" is the first item, which has an index of 0. If we get the length of the array (fruitArr.length) it will return a 3 which is 1 more then the last index in the array (2). Length counts like we do, starting at #1, index counts like computers do, starting at 0.

Tip: The p variable outputs a number in this case. This number is not really a number, it is a string using number characters. If we tried to add these "numbers" up, we would get "012" instead of the sum of 3. This is one reason declaring variable types are important. The compiler will tell us immediately if we are passing a string into an equation where a number or integer should be. Many external data sources will pass numbers into Flash as strings. Declaring variable types adds integrity to our applications.

Function:
A function is like a little wrapper or snippet of code that we can call at a later time. They are like the transmission, servos, clutch and any other metaphorical mechanism that takes energy and makes stuff happen.

Functions can run with or without feedback, adding a few arguments they can become very flexible. Let's use our fruit price calculator equation as a sample. This function receives two arguments (quantity and price), does the calculation, then returns the price. Nothing happens when the script loads, only when the function is called, see below.

?View Code ACTIONSCRIPT
function chaChing(quantity:int, price:Number):Number{
var calc:Number = price * quantity;
return calc;
}
var totalCost:Number = chaChing(5, 0.85);
trace(totalCost); //$4.25
 
// Notice the declaration :Number after the close parenthases
// on the function name.
function chaChing():Number{
}
 
// This lets the compiler know that the function is returning
// a value when it is called. If we do not need to return a value
// when the funciton is called, we would use void.
 
function chaChing():void{
}

This is a really simple one line function, but even this is a valid use. If you ever use the same equation or sequence more then once in your application, wrap it in a function.

Tip: A variables declared inside of a function will not be accessable outside of that function, but variables decaleared outside of the function are visible to it.

Tip: The words method and function are interchangeable.

Tip: Most "Real" programmers will put the opening curly brace one the next line under the function name.

if / else Condition:
Basically a switch, if a cindition is met, do one thing, if not then do something different.

Event:
These enable our controls and is the triggering system for our functions. Events monitors the engine and user input, they can be considered part of the engines electrical system.

Finally the Application:
The simple application we are going to build is an image loader. We will build a custom button, the code will place a button on the stage for each image. We will then hook up these controls to dynamically load in each image.

The beginning of our app is the config area, this is where we set up all of our variables and any constants.

?View Code ACTIONSCRIPT
/*
* first is the array, this is a list of image urls.
* We are going to loop through this array to create the correct amount of buttons.
* When the buttons are pressed, we will use the array to pull to corresponding image url.
*/
var imageArr:Array = ["images/apple.jpg","images/banana.jpg","images/pear.jpg"];
 
 
/****************************************************
* variables
****************************************************/
// buffHeight: will be use this to calulate the y possition of each button.
// 22 is the y coordinate to start the first button.
var buffHeight:int = 22;
 
// loadX and loadY: This will place our image in the correct spot on the stage.
var loadX:int = 156;
var loady:int = 22;
 
/****************************************************
* the loop:
* Iterates through the array, adds a button for each item, adds event listeners,
* updates the buffHeight variable then stops when it reaches the end of the array.
*****************************************************/
 
// There are a few different types of loops, this one is based on the items of an array.
// The first part of the loop conditions is declaring a variable to represent the index
// as the loop iterates through the array.
 
for(var p:String in imageArr){
 
// create new ImageButton
var imgBtn:ImageButton = new ImageButton();
 
// add a button label
imgBtn.labelText.text = "Image " + p;
 
// give the button a id from "p" which references the index
// of the current item in the array.
imgBtn.id = int(p);
 
// set the y property using the buffHeight variable.
imgBtn.y = buffHeight;
imgBtn.x = 20;
 
// add the eventListener to capture the button clicks
imgBtn.addEventListener(MouseEvent.CLICK,clickHandler);
 
//add the button to the stage.
addChild(imgBtn);
 
//update the variable with the height of this button, so the next button's y position will be below it.
buffHeight += imgBtn.height + 5;
}
 
/****************************************************
* function clickHandler(MouseEvent)
* handler for the Click MouseEvent assigned to each button in the loop.
****************************************************/
function clickHandler(ev:MouseEvent):void{
 
// the event's target property tells which button fired the event, now we can get the correct id.
var id:int = ev.currentTarget.id;
 
//use the id and the imageArr to get the correct image url.
var url:String = imageArr[id];
 
//call the loadImage function with the url as an argument.
loadImage(url);
}
 
/****************************************************
* function loadImage(url:String)
* function for loading the images
****************************************************/
function loadImage(url:String):void{
 
// new variable of new loader object
var ldr:Loader = new Loader();
 
// new URLRequest using the url we passed in as an argument.
// this converts the string into a url request we can pass to the loader to load the image.
var req:URLRequest = new URLRequest(url);
 
//loading the image
ldr.load(req);
 
ldr.x = loadX;
ldr.y = loady;
 
// add loader to MovieClip referenced by loadTarget.
addChild(ldr);
}
 
stop();

Button code and instructions:
Make a new MovieClip. Inside this new MovieClip create some artwork to be used as the button background. Add a textField and variable declaration for id (we will pass in the id during the loop). Then check the Export to ActionScript option in the MovieClips *properties window.

*To get to the MovieClips property window, right-click on the MovieClip in the Library, then choose properties. You may need to click the advanced button to see all the options.

We are using a MovieClip instead of a button, so that we can pass in an id and control the text. So we are going to build a MovieClip to act as a button.

Source Here

Where to go from here:
1. Play with the application variables and the array. Expand the app by giving each button a better name. Maybe build the array using names in stead of urls, then you can create the new url string using "images/" + name + ".jpg". You could also create a name array in the same sequence or use slice on the url to pull the name out.

2. Expand the buttons, if you really want to get fancy, create an on-state for each button, so that you can tell which image is currently displayed.

3. Add the calculator code to display how much each item cost when you click a button and a loader.

Tip: The ldr function above places one item on top of another, this may cause an issue if you want to show something behind each image while it is loading.

Take the existing code and come up with another uses for it. If you come up with some cool ideas, post some links below. Also if you figure out any of the previous enhancement, post some code.

To put your code in a code block, you can wrap it in these tags. Take out the "[" and "]" ,square brackets.
[<]pre lang="actionscript"[>]
// all code goes here.
[<]/pre[>]

Adobe MAX 2008 kicks off with Shantanu Narayen, troche Adobe CEO.

I will do some live blogging from MAX. All post are being typed on my iPhone, due to my broken laptop, so do not expect a lot of details.

Over 5000 in attendence.

Followed by 2 more MAX conferences in europe and Asia.

Flash catalyst announced, previously Thurmo.

(Red) Wire announced, delivered on AIR. $5 a month.

Kevin Lynch on stage.

Cloud and client. Across multiple screens/devices.

Flash player 10 is awesome.
Audio waveform data, 3D, text engine, drawing API, pixel blender.
FAST realtime processing.

Max keynote is available online now. keynote

I cannot do it justice from my iPhone, pilule so check it out.

Updates:

Apparantly the keynote video does not live at the address I placed above, visit web that is what was on the big screen at the end of the keynote. sorry about that.
Here are a couple links of real live blogging (bet they had a laptop).
Liveblogging MAX 2008 Day 1 General Session Keynote

Adobe MAX 2008: Monday - Keynote

Tour de Flex on a 20' screen, shot by Greg Wilson. Tour de Flex on a 20 ft Screen
The first day of MAX has ended at 10:30 pm Monday night. East coast time is taking it's toll, sales but I know I am not the only one. I just finished moderating a video tips group that was full of drooping eyes.

Today was a success with 4 new t-shirts and a few new tips learned. All of the sessions are going to be available for free at Adobe TV. I have heard the Flash Catylist (thermo) sessions were really good, information pills the Flash Player Internals session had some nice insight on optimizing code, this my favorite one of the day. The Flex Tips session showed off some features of Flex Builder that I never new existed and now will not be able to live without.

MAX 2008 Sessions added to Adobe TV - 12/11/08

MAX 2008 on Adobe TV.

In a Birds-Of-A-Feather discussion group at Adobe MAX last week. No remarks were planned, search It was supposed to be a discussion, stuff we hoped to talk to other developers about what's new in using Flash video. We did not get a bunch of new information but we did get a lot of hard questions. Some of them were not fully answered and others were speculated upon. When I was asked my tips, I gave all I could think of at the time. Later that evening I remembered a couple more, some of my best ones.

So for those who went to MAX and those that did not, here are my official video tips for Flash and Flex.

Disclaimer: Technology changes on a regular basis, as of the date of this post I feel very comfortable with the statements made below. As new versions of software are released some of the comments may become outdated.

1. Your source file is king when it comes to getting good quality video. A good source file is the difference between hulu and youtube video. If you have control over your video source, make sure you get a good high-res lossless video file. They are huge and some clients do not know what you are talking about when you ask for it, but try your best to get a good source file.

2. Encode your own files. There are many flv encoders out there, some even your clients can use. But if you want good quality, then encode them yourselves. Of course some clients are pretty savvy when it comes to these things, in that case train them.

3. Use the Flash Video Encoder standalone application. *I have exported flv's from many other programs, but quality is more consistent with the Flash Video Encoder application. Plus the encoding speed is a lot better with the Flash Video Encoder. It does suck to encode something twice, once to a lossless file, then a second time to flv, but in my testing it has been worth it.
(*H.264 can be encoded from other applications with equal quality. I have not compared them yet, but it is a very standard codec.)

4. If you do not have Flash CS4, use on2 VP6 encoding, it is much better than the other codec options. H.264 is a great improvement even over on2 VP6. Mp4 files can use different codecs, so make sure you are using H.246 and mp3 audio if you are encoding with other applications.

5. Not all video files are the same. Video containing a lot of motion/action can not handle as much compression as a low motion, talking head video. You will have to test your video files and encode each file with different settings to get optimum performance, size and quality. Also if you have control over the editing of your source files, certain video transitions (cross dissolve) encode worse than others.

6. Do not change frame rate when encoding an flv. This will cause your a/v sync to drift. Any edits to frame rate needs to be made in your source file before you encode. This does not apply to video without sound.

7. Dropping FPS and lowering the Key Frame Interval can lower file size of the flv, but there are consequences. For lowering frame rate, see number 6. Lowering the frame rate interval will effect fast-forwarding and rewinding and may effect syncing between key frames. If you need smooth fast forward and rewind, then leave the key frame interval to automatic or raise it a little more. I believe it is set to 24 frames by default.

8. If you want to have good streaming performance, place your streaming files on a server setup for streaming content. There could be cross-domain security sandbox issues, if your files do not load, first check if you need a crossdomain.xml file.

9. Video has come along way from the timeline full of image sequences from pre Flash MX days. Video still has a large file size that can only be compressed so far. Video needs to buffer before playing and can consume a lot of CPU. If possible stop other animations, visual effects, and any processor intense code while your videos are playing.

10. There are still times when video is not the best solution. I still use image sequences if the job requires it, even though video can be the easier way to go in most cases. You may have to push your animation skills to pull off video type effects. Building your animation in Flash will give you more control over the size and quality of your project.

Using Random in Game Development, buy with strict guidelines, order can bring some variety to game play.

This sample is not a single solution but an approached I used in developing Whacky Voting - a politically smashing game. It uses random with some strict rules to get rid of sequences that some players can easily remember, yet keeping game play consistent from one game to the next.

This demo starts with a configuration section, used to set up how we want the game to act. The engine it self could be organized a little better to be more transportable. It is commented pretty well though, so it should be easy enough to understand the approach as well as practical usage. Random is used to shuffle all of the objects that appear on screen as well as what container the objects are associated with.

Configuration:
We use config data for each game so that we can easily tweak game-play without hacking our code later. We can use arrays, xml or other data sources. Plan ahead and build config options into your game as it is developed.

This array designates slots or containers to hold each appearing object. Use this to limit how many objects appear at a time and where they are placed on screen. this can represent MovieClips or other classes.

?View Code ACTIONSCRIPT
var objHolderArr:Array = [];
objHolderArr[0] = {obj:"object0",id:0,stat:false,timer:20,type:"",score:0,targ:null,xCoor:10};
objHolderArr[1] = {obj:"object1",id:1,stat:false,timer:20,type:"",score:0,targ:null,xCoor:90};
objHolderArr[2] = {obj:"object2",id:2,stat:false,timer:20,type:"",score:0,targ:null,xCoor:170};
objHolderArr[3] = {obj:"object3",id:3,stat:false,timer:20,type:"",score:0,targ:null,xCoor:250};
objHolderArr[4] = {obj:"object4",id:4,stat:false,timer:20,type:"",score:0,targ:null,xCoor:330};
objHolderArr[5] = {obj:"object5",id:5,stat:false,timer:20,type:"",score:0,targ:null,xCoor:410};

Next is an array of objects to appear, this is to control what type of objects appear and to make sure they are nicely distributed through out each level. You may have different scores, wilds and/or bonus score objects that need to get incorporated into the object list, but using random by it self will not allow them to be distributed appropriately for consistent game play.

?View Code ACTIONSCRIPT
var objSequenceArr:Array = [];
objSequenceArr[0] = {obj:"type0", count:20,score:100};
objSequenceArr[1] = {obj:"type1", count:15, score:150};
objSequenceArr[2] = {obj:"type2", count:5, score:500};
objSequenceArr[3] = {obj:"type3", count:5, score:1000};
objSequenceArr[4] = {obj:"null", count:5, score:0};
 
//timer increment for the engine to trigger an event
var timeInc:int = 500;
 
// integer to keep track of increment of game engine
var arrLoc:int = 0;
 
// random key
var randomKey:int = 1000;
 
// time for each object to stay visible;
var delay:int = 4;

It is good to set game status variables to allow games controls to be a little more intuitive. Sometimes I use a gameStatus string variable and a string to denote the current status. That way I can get more mileage out of one variable.

?View Code ACTIONSCRIPT
var gameOver:Boolean;
 
//or
 
var gameStatus:String = "_play";

Build Config Data for Engine:
The current level array built from config data above. The method then adds to the level array all the objects that we want to appear during the game.

?View Code ACTIONSCRIPT
var levelArr:Array = [];
 
function buildConfigData():void{
for(var p:String in objSequenceArr){
var loopCnt:int = objSequenceArr[p].count;
for(var i:uint = 0; i < loopCnt; i++){
var randNum:int = randomNumber(randomKey);
levelArr.push({obj:objSequenceArr[p].obj, score:objSequenceArr[p].score, key:randNum});
}
}
 
levelArr.sortOn("key",Array.NUMERIC || Array.DESCENDING);
}
buildConfigData();

Last, we sort the list so that it is shuffled which gives us the first random effect. All the objects are placed in the array in order of the sequence array, but we added a random number as the key to sort the array with. Now all of the objects will be randomly placed throughout the array and we will always have the right amount of objects for consistent game play.

Game Engine:
Now that we have our data, we are ready to start the engine.

1. Pull first random number

2. Loop until random number is not a slot that is already taken. We add a break and status variable to stop the loop if we can not find an available object. On a break, we will wait until the next TimerEvent and try again.

3. We have an active slot that is not already taken, we set it's status to true and show and configure our object.

4. Use this timer event to also run our Active Checker Method below. The more you can piggy-back off of single timers and EnterFrame events the better.

?View Code ACTIONSCRIPT
var timer:Timer = new Timer(timeInc,0);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
 
function timerHandler(ev:TimerEvent):void{
 
//1.
var randSlot:int = randomNumber(objHolderArr.length);
 
//2.
if(arrLoc < levelArr.length){
if(levelArr[arrLoc].obj != "null"){
var breakCnt:int
var breakStatus:Boolean;
while(objHolderArr[randSlot].stat == true){
randSlot = randomNumber(objHolderArr.length);
breakCnt ++;
if(breakCnt >= 100){
breakStatus = true;
break;
}
}
 
if(!breakStatus){
//3.
var slotObj:Object = objHolderArr[randSlot];
slotObj.stat = true;
slotObj.timer = delay;
slotObj.score = levelArr[arrLoc].score;
slotObj.type = levelArr[arrLoc].type;
 
//******* add code here to initiate your visual objects.
var tempBO:ballObj = new ballObj();
tempBO.x = slotObj.xCoor;
tempBO.y = 20;
tempBO.objIDStr = arrLoc.toString();
tempBO.objScoreStr = levelArr[arrLoc].score;
tempBO.objTypeStr = levelArr[arrLoc].obj;
addChild(tempBO);
 
//********* end visual code here.
 
slotObj.targ = tempBO;
activeObjArr.push(slotObj);
// we advance the array location variable.
arrLoc ++;
}
}
else{
arrLoc ++;
}
}
 
//4.
activeChecker();
}

After each object is initiated, we need to give them an amount of time to be active. This is the activeObject array, we will track the time, if the user does not score with the object then it will be removed by the timer.

1. Loop through the active array to decrease each object's timer.

2. If the timer is run out, remove the object from the array and reset the object's status.

?View Code ACTIONSCRIPT
var activeObjArr:Array = [];
 
function activeChecker():void{
for(var p:String in activeObjArr){
//1.
activeObjArr[p].timer --;
 
//2.
if(activeObjArr[p].timer <= 0){
activeObjArr[p].stat = false;
removeChild(activeObjArr[p].targ);
activeObjArr.splice(int(p),1);
 
if(arrLoc >= levelArr.length && activeObjArr.length == 0){
//game is over.
gameOver = true;
timer.stop();
btn.enabled = true;
btn.alpha = 1;
}
}
}
}

Here is where you can place your event handlers for a user interactive with an object. We have to remove and reset the object, shown above and add the objects score to the main score.

We will also need a method for when the game clears the last array object.

Utilities:
method to pull random numbers just so I do not need to write this same code more than once.

?View Code ACTIONSCRIPT
function randomNumber(limit:int):int{
var randNum:int = Math.random()*limit;
return randNum;
}

Controls:
A restart control availble when game is over

?View Code ACTIONSCRIPT
btn.addEventListener(MouseEvent.CLICK,clickHandler);
btn.enabled = false;
btn.alpha = 0.2;
function clickHandler(ev:MouseEvent):void{
if(gameOver){
// rebuild data to show off shuffling.
levelArr = [];
buildConfigData();
 
//reset game controls and game engine.
arrLoc = 0;
timer.start();
gameOver = false;
btn.enabled = false;
btn.alpha = 0.2;
}
}

The Ball Object:
The ball object is a simple class that displays the data for each object. You would normally place a button or some other way to capture user interaction and send it back to the engine to initiate scores and feedback.

?View Code ACTIONSCRIPT
package{
import flash.display.MovieClip;
import flash.text.TextField;
import flash.events.Event;
 
public class ballObj extends MovieClip{
 
public var objIDStr:String = "";
public var objTypeStr:String = "";
public var objScoreStr:String = "";
 
public function ballObj():void{
init();
stop();
}
 
private function init():void{
this.addEventListener(Event.ADDED,addedHandler);
}
 
private function addedHandler(ev:Event):void{
objID.text = objIDStr;
objScore.text = objScoreStr;
objType.text = objTypeStr;
 
}
}
}

Source Here
This is it, about it the very first bit of actionscript code I ever learned, site besides play() and gotoAndStop() of course. The lesson went down with an experienced programmer looking over my shoulder telling me what to type. After this little app was finished, approved my brain hurt only understanding a few of the lines we wrote. That code was referenced and/or modified on more then a few projects that came after, each time deciphering more and applying it to new functionalities.

The original script was back in the day of AS1, but I am going to present it to you in AS3. If you are a beginner to ActionScript then it is the perfect time to learn AS3.

We are going to start really remedial for a minute and go over the basics of the classes and objects we will be using. It is kind-of long, so if you already have the basics covered, you can skip to the Application code.

The Variable:
Remember Pre-Algebra? 2+x = y? Variables are used for more then just place holders in a math equation. Programming is a very literal language, variables are how we make it figurative. Now instead of addressing one object with a snippet of code, that code can be applied to the many objects and properties our variables represent.

To use a variable, we must declare it using these three letters "var". Then comes the creative part, we get to think of a name. This can be a lot of fun making up funny names for things until someone else has to figure out your code or you forget that you called the variable that is going to bring balance to your application "anakin", oops, or was that "luke"?

After naming the variable, we have to declare it's type. We really don't have to, but it is a good idea. This variable will be a Number, because we will need it to include decimals.

Here are some examples of how variables can be used. Think about if we were selling apples that costs 65¢ a peace. A person wants to buy 5 apples. so we build an equation to handle the transaction.

?View Code ACTIONSCRIPT
var totalCost:Number;
totalCost = 0.65 * 5; //3.25

Ok, so we went conservitive, using "totalCost" for the total of apples purchased. Now what do we do when someone wants to buy 4 apples, or 6, or 8? Now we should add a new variable to represent the amount of apples. This variables declaration is an "int" (integer) as we will not be selling fractions of apples.

?View Code ACTIONSCRIPT
var numApples:int = 5;
var totalCost:Number;
totalCost = 0.65 * numApples; // 3.25

Everyone is happy until next week when there is an apple shortage and the price increases to 85¢ a piece. Now you have to go through you app and change all the prices from 65¢ to 85¢. If we use variables we can easily modify the app when the price changes, better yet, now this same app could be used to handle bananas, grapefruit and pears which all have different prices.

?View Code ACTIONSCRIPT
var cost:Number = 0.85;
var numFruit = 5;
var totalCost:Numer;
totalCost = cost * numFruit; // $4.25

Array:
Array is one of the most powerful classes in Flash. It's power comes from the way an array holds a collection of information. Not only do we have access to the information, but we can loop through all the items in an array and monitor the length of the collection.

This is how we might set up some variables without arrays. If we add or take away an item, we have to update a separate variable to keep track of the total amount. Looping through this is information is possible, but tricky.

?View Code ACTIONSCRIPT
var fuit1:String = "apple";
var fruit2:String = "banana";
var fruit3:String = "pear";
var fruits:int = 3;
 
// Or we can do the same thing with an array.
 
var fruitArr:Array = ["apple","banana","pear"];
 
trace(fruitArr[0]); //"apple
trace(fruitArr.length); //3

One thing that you must remember when using arrays is that they are zero indexed, meaning the first position in the array is 0. This can cause a little confusion because we teach our children to start counting at 1, not 0. This will hopefully make more sense later or maybe more confusion, but at least you will know why you are confused.

Tip: instead of useing var fruitArr:Array = new Array(); which you may have seen before. Using the square braces will do same thing. var fruitArr:Array = [];

If we think of our application as if it were an engine, the data objects (arrays, XML) are the fuel. The part of the application that interates like loops, enter frame events and timers are the heart of the engine, like the pistons, cams and crank shaft. This engine starts once the app loads and runs until we stop everything or close the app.

for() Loop:
Interates or repeats a a specified amount allowing our engine to apply the same code to multiple objects. Loops will run and complete in between each frame, before each render. This means you will not visually see what the loop is doing until it completes and the stage renders.

?View Code ACTIONSCRIPT
// This is a loop using the array from above:
for(var p:String in fruitArr){
trace(fruitArr[p] + " | index = " + p);
}
 
output:
apple | index = 0
banana | index = 1
pear | index = 2

First we assign a variable to the item that is going to loop trough the array. p stands for property and is a string. Here you can see the output of "p" which is showing the index or location of each item in the array. Notice that "apple" is the first item, which has an index of 0. If we get the length of the array (fruitArr.length) it will return a 3 which is 1 more then the last index in the array (2). Length counts like we do, starting at #1, index counts like computers do, starting at 0.

Tip: The p variable outputs a number in this case. This number is not really a number, it is a string using number characters. If we tried to add these "numbers" up, we would get "012" instead of the sum of 3. This is one reason declaring variable types are important. The compiler will tell us immediately if we are passing a string into an equation where a number or integer should be. Many external data sources will pass numbers into Flash as strings. Declaring variable types adds integrity to our applications.

Function:
A function is like a little wrapper or snippet of code that we can call at a later time. They are like the transmission, servos, clutch and any other metaphorical mechanism that takes energy and makes stuff happen.

Functions can run with or without feedback, adding a few arguments they can become very flexible. Let's use our fruit price calculator equation as a sample. This function receives two arguments (quantity and price), does the calculation, then returns the price. Nothing happens when the script loads, only when the function is called, see below.

?View Code ACTIONSCRIPT
function chaChing(quantity:int, price:Number):Number{
var calc:Number = price * quantity;
return calc;
}
var totalCost:Number = chaChing(5, 0.85);
trace(totalCost); //$4.25
 
// Notice the declaration :Number after the close parenthases
// on the function name.
function chaChing():Number{
}
 
// This lets the compiler know that the function is returning
// a value when it is called. If we do not need to return a value
// when the funciton is called, we would use void.
 
function chaChing():void{
}

This is a really simple one line function, but even this is a valid use. If you ever use the same equation or sequence more then once in your application, wrap it in a function.

Tip: A variables declared inside of a function will not be accessable outside of that function, but variables decaleared outside of the function are visible to it.

Tip: The words method and function are interchangeable.

Tip: Most "Real" programmers will put the opening curly brace one the next line under the function name.

if / else Condition:
Basically a switch, if a cindition is met, do one thing, if not then do something different.

Event:
These enable our controls and is the triggering system for our functions. Events monitors the engine and user input, they can be considered part of the engines electrical system.

Finally the Application:
The simple application we are going to build is an image loader. We will build a custom button, the code will place a button on the stage for each image. We will then hook up these controls to dynamically load in each image.

The beginning of our app is the config area, this is where we set up all of our variables and any constants.

?View Code ACTIONSCRIPT
/*
* first is the array, this is a list of image urls.
* We are going to loop through this array to create the correct amount of buttons.
* When the buttons are pressed, we will use the array to pull to corresponding image url.
*/
var imageArr:Array = ["images/apple.jpg","images/banana.jpg","images/pear.jpg"];
 
 
/****************************************************
* variables
****************************************************/
// buffHeight: will be use this to calulate the y possition of each button.
// 22 is the y coordinate to start the first button.
var buffHeight:int = 22;
 
// loadX and loadY: This will place our image in the correct spot on the stage.
var loadX:int = 156;
var loady:int = 22;
 
/****************************************************
* the loop:
* Iterates through the array, adds a button for each item, adds event listeners,
* updates the buffHeight variable then stops when it reaches the end of the array.
*****************************************************/
 
// There are a few different types of loops, this one is based on the items of an array.
// The first part of the loop conditions is declaring a variable to represent the index
// as the loop iterates through the array.
 
for(var p:String in imageArr){
 
// create new ImageButton
var imgBtn:ImageButton = new ImageButton();
 
// add a button label
imgBtn.labelText.text = "Image " + p;
 
// give the button a id from "p" which references the index
// of the current item in the array.
imgBtn.id = int(p);
 
// set the y property using the buffHeight variable.
imgBtn.y = buffHeight;
imgBtn.x = 20;
 
// add the eventListener to capture the button clicks
imgBtn.addEventListener(MouseEvent.CLICK,clickHandler);
 
//add the button to the stage.
addChild(imgBtn);
 
//update the variable with the height of this button, so the next button's y position will be below it.
buffHeight += imgBtn.height + 5;
}
 
/****************************************************
* function clickHandler(MouseEvent)
* handler for the Click MouseEvent assigned to each button in the loop.
****************************************************/
function clickHandler(ev:MouseEvent):void{
 
// the event's target property tells which button fired the event, now we can get the correct id.
var id:int = ev.currentTarget.id;
 
//use the id and the imageArr to get the correct image url.
var url:String = imageArr[id];
 
//call the loadImage function with the url as an argument.
loadImage(url);
}
 
/****************************************************
* function loadImage(url:String)
* function for loading the images
****************************************************/
function loadImage(url:String):void{
 
// new variable of new loader object
var ldr:Loader = new Loader();
 
// new URLRequest using the url we passed in as an argument.
// this converts the string into a url request we can pass to the loader to load the image.
var req:URLRequest = new URLRequest(url);
 
//loading the image
ldr.load(req);
 
ldr.x = loadX;
ldr.y = loady;
 
// add loader to MovieClip referenced by loadTarget.
addChild(ldr);
}
 
stop();

Button code and instructions:
Make a new MovieClip. Inside this new MovieClip create some artwork to be used as the button background. Add a textField and variable declaration for id (we will pass in the id during the loop). Then check the Export to ActionScript option in the MovieClips *properties window.

*To get to the MovieClips property window, right-click on the MovieClip in the Library, then choose properties. You may need to click the advanced button to see all the options.

We are using a MovieClip instead of a button, so that we can pass in an id and control the text. So we are going to build a MovieClip to act as a button.

Source Here

Where to go from here:
1. Play with the application variables and the array. Expand the app by giving each button a better name. Maybe build the array using names in stead of urls, then you can create the new url string using "images/" + name + ".jpg". You could also create a name array in the same sequence or use slice on the url to pull the name out.

2. Expand the buttons, if you really want to get fancy, create an on-state for each button, so that you can tell which image is currently displayed.

3. Add the calculator code to display how much each item cost when you click a button and a loader.

Tip: The ldr function above places one item on top of another, this may cause an issue if you want to show something behind each image while it is loading.

Take the existing code and come up with another uses for it. If you come up with some cool ideas, post some links below. Also if you figure out any of the previous enhancement, post some code.

To put your code in a code block, you can wrap it in these tags. Take out the "[" and "]" ,square brackets.
[<]pre lang="actionscript"[>]
// all code goes here.
[<]/pre[>]

Construction

Wether I am illustrating an imaginary device or something I use everyday, mind it is good to understand how the object is or should be constructed. Other information like functionality, page and how these objects are interacted with are very important in making our illustrations more convincing.

Questions you could ask yourself are how much heft and mass does this object possess, What kids of materials are used to build this object? How does this information effect how light reflects/refracts off the object. These evaluations help us understand how the details should be rendered.

The object could be steel, but is it built assembled with welds, bolts or both? The object could be made from concrete, Styrofoam, wood, glass or plastic molds. Each material is assembled differently with different types of joints. The time when an object is built also will give us a clue as to the type of assembly would have been used. We should carry that information or hints of that information into our illustration.

We do not have to have an engineering degree to know that some buildings are made from glass and steal, brick/concrete block, or wood. A glass building would be smooth and shiny on the outside with little definition where each glass plate comes together. Brick buildings have thick walls so windows are inset into the wall. Wood buildings have window frames that are used to hold the window into the wall.

These are the types of things that should be going through our heads as we sketch, construct, color, and touch up our work. In the meantime we are building our forms in Illustrator, here are some techniques to speed up our work as we construct our illustrations with the provided tools.

Using divide and Unite:
Divide and Unite are two pathfinder tools I use the most. You should set these to actions with keyboard shortcuts.

Divide Tip 1:
Create a shadow, reflection, glare on a larger shape. One of the rules for quick illustration in Illustrator is to never draw the same line twice. Another rule is divide does not have to be destructive. If you have ever used Divide before on a shape and zoomed out, sometimes you will notice a little background seeping through where the Divide incision are applied.

Draw the path how you would like your incision, over lapping on both ends and making sure the path has no fill. Select the larger shape first, Copy and Paste in Front (Command + F / Cntr + F) then select the line you created for your incision. Apply the Divide to the shape and delete the unwanted piece.

This creates a smaller shape on top of the original shape, in seconds, with no gaps and non-destructive. If we do not like the way it looks, we can always delete it and start over with our original shape still intact.

Divide Tip 2:
Again Divide does not have to be destructive. If you have a few overlapping paths, Divide with create a joined shape and trim off the excess paths. This can come in handy when using a grid, copy the lines we want to use from the grid, and apply a Divide. You will now have a new shape that matches your guides without having to draw anything. We drew the lines once for the guide, we should not have to draw them a gain.

Divide Tip 3:
Overlap your paths with working with divide. It is much easier to make sure your division are complete if you see your incision paths are overlapping your original shape.

Unite Tip 1:
Sometimes Divide can have some unwelcome results, but they can be cleaned up quickly with Unite.

Unite Tip 2:
Unite goes hand with Outline Stroke. If you have a fill and a stroke, using Outline Stroke then Unite will convert a path into a new solid shape. I like to use this for making nice outlines or inking effects. Depending on your Illustrator Preference settings, paths will scale on one machine and not another. It is also a good idea to Outline & Unite paths if the size relationship is important.

Below is a simple funny faced frog made almost intierly with the oval tool and Outlined paths.

For a better explanation of these tips, watch Illustrating in Illustrator, the Happy Frog video tutorial.

Flash tip: Paths have never translated well to Flash, so try Outline & Unite before importing to Flash.

Offset Stroke:
Found in the Object:Path menu, is similar to Outline Stroke. In CS3 and before the new path is automatically grouped to the original path. So if you have a few paths being made from the Outline Stroke command, you will have to select all the pieces and Cut & Paste them out of the group to work with them easier. I still use it very often, mostly on simpler shapes.

In Illustrator CS4 Outline Stroke works much better and mimics the functionality mentioned in Unite Tip 2.

Duplicate and Transform:
There are many times while we are illustrating that we come across many objects that are similar like windows, bolts, or even spider eyes. By completing on object, then copying and distributing those copies around will make creating all these objects less redundant. Even if shapes, size, perspective differ, there may be parts that are reusable, or a quick transform can really help save time.

Drawing vs Editing:
We have discussed never drawing the same line twice and was to create new shapes from exiting ones. Also we went over duplicating shapes and objects to help speed things up. The rules in this series are just like most rules, there is very often an exception. If you are comfortable with the pen tool in Illustrator, it is almost always faster to draw a new line then it is to edit an existing one. If you are tweaking a couple points on an existing path, that is one thing, but if you copy an path with the intent on modifying many points, it is most likely faster to draw a whole new path. Or at least delete the points you would like to edit, and draw a new path in it's place.

Join and Average:
Even drawing paths holding down the shift key will not always get our lines straight. The keyboard shortcut for Average is Command + Option + J on a Mac and Control + Alt + J on PC. Any lines that are supposed to be straight that for some reason are not, is just a second away from be so, but you have to remember the keyboard short cut to really make it worth while.

Another Keyboard shortcut to remember is Join. Command + J on a Mac and Control + J on PC, will be used over and over again to clean up stray points. Divide, Outline Stroke and other wonderful tools we have covered so far are great time savers but can put unwanted points in our paths. One of our objectives it to create Clean artwork. Extra points and text Miter spikes will not do, so a quick select with the Hollow Arrow, or Hollow Lasso, then Join, will clean those points up quickly.

Group and Layer as you go:
As discussed in Part 1 of the series, grouping is important in speeding up our work. It is much easier to grab a bunch of paths that have been grouped with the solid arrow, then selecting many paths to do a tweak. Many time you will be working on something else in the illustration and you will notice something you want to tweak something that was done previously. As you finish objects with multiple paths they should be grouped.

Distributing artwork in layer is a great way to create a groups too. The results of good groups is easy selection and/or isolation of parts of the illustration. Using Lock and Hide as well as layers are great ways to isolate our work.

Next - Illustrating In Illustrator 101 Part 3 of 5: Defining Shapes

For a better explanation of these tips, watch Illustrating in Illustrator, the Happy Frog video tutorial.

Adobe MAX 2008 kicks off with Shantanu Narayen, troche Adobe CEO.

I will do some live blogging from MAX. All post are being typed on my iPhone, due to my broken laptop, so do not expect a lot of details.

Over 5000 in attendence.

Followed by 2 more MAX conferences in europe and Asia.

Flash catalyst announced, previously Thurmo.

(Red) Wire announced, delivered on AIR. $5 a month.

Kevin Lynch on stage.

Cloud and client. Across multiple screens/devices.

Flash player 10 is awesome.
Audio waveform data, 3D, text engine, drawing API, pixel blender.
FAST realtime processing.

Max keynote is available online now. keynote

I cannot do it justice from my iPhone, pilule so check it out.

Updates:

Apparantly the keynote video does not live at the address I placed above, visit web that is what was on the big screen at the end of the keynote. sorry about that.
Here are a couple links of real live blogging (bet they had a laptop).
Liveblogging MAX 2008 Day 1 General Session Keynote

Adobe MAX 2008: Monday - Keynote

Tour de Flex on a 20' screen, shot by Greg Wilson. Tour de Flex on a 20 ft Screen
The first day of MAX has ended at 10:30 pm Monday night. East coast time is taking it's toll, sales but I know I am not the only one. I just finished moderating a video tips group that was full of drooping eyes.

Today was a success with 4 new t-shirts and a few new tips learned. All of the sessions are going to be available for free at Adobe TV. I have heard the Flash Catylist (thermo) sessions were really good, information pills the Flash Player Internals session had some nice insight on optimizing code, this my favorite one of the day. The Flex Tips session showed off some features of Flex Builder that I never new existed and now will not be able to live without.

MAX 2008 Sessions added to Adobe TV - 12/11/08

MAX 2008 on Adobe TV.

In a Birds-Of-A-Feather discussion group at Adobe MAX last week. No remarks were planned, search It was supposed to be a discussion, stuff we hoped to talk to other developers about what's new in using Flash video. We did not get a bunch of new information but we did get a lot of hard questions. Some of them were not fully answered and others were speculated upon. When I was asked my tips, I gave all I could think of at the time. Later that evening I remembered a couple more, some of my best ones.

So for those who went to MAX and those that did not, here are my official video tips for Flash and Flex.

Disclaimer: Technology changes on a regular basis, as of the date of this post I feel very comfortable with the statements made below. As new versions of software are released some of the comments may become outdated.

1. Your source file is king when it comes to getting good quality video. A good source file is the difference between hulu and youtube video. If you have control over your video source, make sure you get a good high-res lossless video file. They are huge and some clients do not know what you are talking about when you ask for it, but try your best to get a good source file.

2. Encode your own files. There are many flv encoders out there, some even your clients can use. But if you want good quality, then encode them yourselves. Of course some clients are pretty savvy when it comes to these things, in that case train them.

3. Use the Flash Video Encoder standalone application. *I have exported flv's from many other programs, but quality is more consistent with the Flash Video Encoder application. Plus the encoding speed is a lot better with the Flash Video Encoder. It does suck to encode something twice, once to a lossless file, then a second time to flv, but in my testing it has been worth it.
(*H.264 can be encoded from other applications with equal quality. I have not compared them yet, but it is a very standard codec.)

4. If you do not have Flash CS4, use on2 VP6 encoding, it is much better than the other codec options. H.264 is a great improvement even over on2 VP6. Mp4 files can use different codecs, so make sure you are using H.246 and mp3 audio if you are encoding with other applications.

5. Not all video files are the same. Video containing a lot of motion/action can not handle as much compression as a low motion, talking head video. You will have to test your video files and encode each file with different settings to get optimum performance, size and quality. Also if you have control over the editing of your source files, certain video transitions (cross dissolve) encode worse than others.

6. Do not change frame rate when encoding an flv. This will cause your a/v sync to drift. Any edits to frame rate needs to be made in your source file before you encode. This does not apply to video without sound.

7. Dropping FPS and lowering the Key Frame Interval can lower file size of the flv, but there are consequences. For lowering frame rate, see number 6. Lowering the frame rate interval will effect fast-forwarding and rewinding and may effect syncing between key frames. If you need smooth fast forward and rewind, then leave the key frame interval to automatic or raise it a little more. I believe it is set to 24 frames by default.

8. If you want to have good streaming performance, place your streaming files on a server setup for streaming content. There could be cross-domain security sandbox issues, if your files do not load, first check if you need a crossdomain.xml file.

9. Video has come along way from the timeline full of image sequences from pre Flash MX days. Video still has a large file size that can only be compressed so far. Video needs to buffer before playing and can consume a lot of CPU. If possible stop other animations, visual effects, and any processor intense code while your videos are playing.

10. There are still times when video is not the best solution. I still use image sequences if the job requires it, even though video can be the easier way to go in most cases. You may have to push your animation skills to pull off video type effects. Building your animation in Flash will give you more control over the size and quality of your project.

Using Random in Game Development, buy with strict guidelines, order can bring some variety to game play.

This sample is not a single solution but an approached I used in developing Whacky Voting - a politically smashing game. It uses random with some strict rules to get rid of sequences that some players can easily remember, yet keeping game play consistent from one game to the next.

This demo starts with a configuration section, used to set up how we want the game to act. The engine it self could be organized a little better to be more transportable. It is commented pretty well though, so it should be easy enough to understand the approach as well as practical usage. Random is used to shuffle all of the objects that appear on screen as well as what container the objects are associated with.

Configuration:
We use config data for each game so that we can easily tweak game-play without hacking our code later. We can use arrays, xml or other data sources. Plan ahead and build config options into your game as it is developed.

This array designates slots or containers to hold each appearing object. Use this to limit how many objects appear at a time and where they are placed on screen. this can represent MovieClips or other classes.

?View Code ACTIONSCRIPT
var objHolderArr:Array = [];
objHolderArr[0] = {obj:"object0",id:0,stat:false,timer:20,type:"",score:0,targ:null,xCoor:10};
objHolderArr[1] = {obj:"object1",id:1,stat:false,timer:20,type:"",score:0,targ:null,xCoor:90};
objHolderArr[2] = {obj:"object2",id:2,stat:false,timer:20,type:"",score:0,targ:null,xCoor:170};
objHolderArr[3] = {obj:"object3",id:3,stat:false,timer:20,type:"",score:0,targ:null,xCoor:250};
objHolderArr[4] = {obj:"object4",id:4,stat:false,timer:20,type:"",score:0,targ:null,xCoor:330};
objHolderArr[5] = {obj:"object5",id:5,stat:false,timer:20,type:"",score:0,targ:null,xCoor:410};

Next is an array of objects to appear, this is to control what type of objects appear and to make sure they are nicely distributed through out each level. You may have different scores, wilds and/or bonus score objects that need to get incorporated into the object list, but using random by it self will not allow them to be distributed appropriately for consistent game play.

?View Code ACTIONSCRIPT
var objSequenceArr:Array = [];
objSequenceArr[0] = {obj:"type0", count:20,score:100};
objSequenceArr[1] = {obj:"type1", count:15, score:150};
objSequenceArr[2] = {obj:"type2", count:5, score:500};
objSequenceArr[3] = {obj:"type3", count:5, score:1000};
objSequenceArr[4] = {obj:"null", count:5, score:0};
 
//timer increment for the engine to trigger an event
var timeInc:int = 500;
 
// integer to keep track of increment of game engine
var arrLoc:int = 0;
 
// random key
var randomKey:int = 1000;
 
// time for each object to stay visible;
var delay:int = 4;

It is good to set game status variables to allow games controls to be a little more intuitive. Sometimes I use a gameStatus string variable and a string to denote the current status. That way I can get more mileage out of one variable.

?View Code ACTIONSCRIPT
var gameOver:Boolean;
 
//or
 
var gameStatus:String = "_play";

Build Config Data for Engine:
The current level array built from config data above. The method then adds to the level array all the objects that we want to appear during the game.

?View Code ACTIONSCRIPT
var levelArr:Array = [];
 
function buildConfigData():void{
for(var p:String in objSequenceArr){
var loopCnt:int = objSequenceArr[p].count;
for(var i:uint = 0; i < loopCnt; i++){
var randNum:int = randomNumber(randomKey);
levelArr.push({obj:objSequenceArr[p].obj, score:objSequenceArr[p].score, key:randNum});
}
}
 
levelArr.sortOn("key",Array.NUMERIC || Array.DESCENDING);
}
buildConfigData();

Last, we sort the list so that it is shuffled which gives us the first random effect. All the objects are placed in the array in order of the sequence array, but we added a random number as the key to sort the array with. Now all of the objects will be randomly placed throughout the array and we will always have the right amount of objects for consistent game play.

Game Engine:
Now that we have our data, we are ready to start the engine.

1. Pull first random number

2. Loop until random number is not a slot that is already taken. We add a break and status variable to stop the loop if we can not find an available object. On a break, we will wait until the next TimerEvent and try again.

3. We have an active slot that is not already taken, we set it's status to true and show and configure our object.

4. Use this timer event to also run our Active Checker Method below. The more you can piggy-back off of single timers and EnterFrame events the better.

?View Code ACTIONSCRIPT
var timer:Timer = new Timer(timeInc,0);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
 
function timerHandler(ev:TimerEvent):void{
 
//1.
var randSlot:int = randomNumber(objHolderArr.length);
 
//2.
if(arrLoc < levelArr.length){
if(levelArr[arrLoc].obj != "null"){
var breakCnt:int
var breakStatus:Boolean;
while(objHolderArr[randSlot].stat == true){
randSlot = randomNumber(objHolderArr.length);
breakCnt ++;
if(breakCnt >= 100){
breakStatus = true;
break;
}
}
 
if(!breakStatus){
//3.
var slotObj:Object = objHolderArr[randSlot];
slotObj.stat = true;
slotObj.timer = delay;
slotObj.score = levelArr[arrLoc].score;
slotObj.type = levelArr[arrLoc].type;
 
//******* add code here to initiate your visual objects.
var tempBO:ballObj = new ballObj();
tempBO.x = slotObj.xCoor;
tempBO.y = 20;
tempBO.objIDStr = arrLoc.toString();
tempBO.objScoreStr = levelArr[arrLoc].score;
tempBO.objTypeStr = levelArr[arrLoc].obj;
addChild(tempBO);
 
//********* end visual code here.
 
slotObj.targ = tempBO;
activeObjArr.push(slotObj);
// we advance the array location variable.
arrLoc ++;
}
}
else{
arrLoc ++;
}
}
 
//4.
activeChecker();
}

After each object is initiated, we need to give them an amount of time to be active. This is the activeObject array, we will track the time, if the user does not score with the object then it will be removed by the timer.

1. Loop through the active array to decrease each object's timer.

2. If the timer is run out, remove the object from the array and reset the object's status.

?View Code ACTIONSCRIPT
var activeObjArr:Array = [];
 
function activeChecker():void{
for(var p:String in activeObjArr){
//1.
activeObjArr[p].timer --;
 
//2.
if(activeObjArr[p].timer <= 0){
activeObjArr[p].stat = false;
removeChild(activeObjArr[p].targ);
activeObjArr.splice(int(p),1);
 
if(arrLoc >= levelArr.length && activeObjArr.length == 0){
//game is over.
gameOver = true;
timer.stop();
btn.enabled = true;
btn.alpha = 1;
}
}
}
}

Here is where you can place your event handlers for a user interactive with an object. We have to remove and reset the object, shown above and add the objects score to the main score.

We will also need a method for when the game clears the last array object.

Utilities:
method to pull random numbers just so I do not need to write this same code more than once.

?View Code ACTIONSCRIPT
function randomNumber(limit:int):int{
var randNum:int = Math.random()*limit;
return randNum;
}

Controls:
A restart control availble when game is over

?View Code ACTIONSCRIPT
btn.addEventListener(MouseEvent.CLICK,clickHandler);
btn.enabled = false;
btn.alpha = 0.2;
function clickHandler(ev:MouseEvent):void{
if(gameOver){
// rebuild data to show off shuffling.
levelArr = [];
buildConfigData();
 
//reset game controls and game engine.
arrLoc = 0;
timer.start();
gameOver = false;
btn.enabled = false;
btn.alpha = 0.2;
}
}

The Ball Object:
The ball object is a simple class that displays the data for each object. You would normally place a button or some other way to capture user interaction and send it back to the engine to initiate scores and feedback.

?View Code ACTIONSCRIPT
package{
import flash.display.MovieClip;
import flash.text.TextField;
import flash.events.Event;
 
public class ballObj extends MovieClip{
 
public var objIDStr:String = "";
public var objTypeStr:String = "";
public var objScoreStr:String = "";
 
public function ballObj():void{
init();
stop();
}
 
private function init():void{
this.addEventListener(Event.ADDED,addedHandler);
}
 
private function addedHandler(ev:Event):void{
objID.text = objIDStr;
objScore.text = objScoreStr;
objType.text = objTypeStr;
 
}
}
}

Source Here
This is it, about it the very first bit of actionscript code I ever learned, site besides play() and gotoAndStop() of course. The lesson went down with an experienced programmer looking over my shoulder telling me what to type. After this little app was finished, approved my brain hurt only understanding a few of the lines we wrote. That code was referenced and/or modified on more then a few projects that came after, each time deciphering more and applying it to new functionalities.

The original script was back in the day of AS1, but I am going to present it to you in AS3. If you are a beginner to ActionScript then it is the perfect time to learn AS3.

We are going to start really remedial for a minute and go over the basics of the classes and objects we will be using. It is kind-of long, so if you already have the basics covered, you can skip to the Application code.

The Variable:
Remember Pre-Algebra? 2+x = y? Variables are used for more then just place holders in a math equation. Programming is a very literal language, variables are how we make it figurative. Now instead of addressing one object with a snippet of code, that code can be applied to the many objects and properties our variables represent.

To use a variable, we must declare it using these three letters "var". Then comes the creative part, we get to think of a name. This can be a lot of fun making up funny names for things until someone else has to figure out your code or you forget that you called the variable that is going to bring balance to your application "anakin", oops, or was that "luke"?

After naming the variable, we have to declare it's type. We really don't have to, but it is a good idea. This variable will be a Number, because we will need it to include decimals.

Here are some examples of how variables can be used. Think about if we were selling apples that costs 65¢ a peace. A person wants to buy 5 apples. so we build an equation to handle the transaction.

?View Code ACTIONSCRIPT
var totalCost:Number;
totalCost = 0.65 * 5; //3.25

Ok, so we went conservitive, using "totalCost" for the total of apples purchased. Now what do we do when someone wants to buy 4 apples, or 6, or 8? Now we should add a new variable to represent the amount of apples. This variables declaration is an "int" (integer) as we will not be selling fractions of apples.

?View Code ACTIONSCRIPT
var numApples:int = 5;
var totalCost:Number;
totalCost = 0.65 * numApples; // 3.25

Everyone is happy until next week when there is an apple shortage and the price increases to 85¢ a piece. Now you have to go through you app and change all the prices from 65¢ to 85¢. If we use variables we can easily modify the app when the price changes, better yet, now this same app could be used to handle bananas, grapefruit and pears which all have different prices.

?View Code ACTIONSCRIPT
var cost:Number = 0.85;
var numFruit = 5;
var totalCost:Numer;
totalCost = cost * numFruit; // $4.25

Array:
Array is one of the most powerful classes in Flash. It's power comes from the way an array holds a collection of information. Not only do we have access to the information, but we can loop through all the items in an array and monitor the length of the collection.

This is how we might set up some variables without arrays. If we add or take away an item, we have to update a separate variable to keep track of the total amount. Looping through this is information is possible, but tricky.

?View Code ACTIONSCRIPT
var fuit1:String = "apple";
var fruit2:String = "banana";
var fruit3:String = "pear";
var fruits:int = 3;
 
// Or we can do the same thing with an array.
 
var fruitArr:Array = ["apple","banana","pear"];
 
trace(fruitArr[0]); //"apple
trace(fruitArr.length); //3

One thing that you must remember when using arrays is that they are zero indexed, meaning the first position in the array is 0. This can cause a little confusion because we teach our children to start counting at 1, not 0. This will hopefully make more sense later or maybe more confusion, but at least you will know why you are confused.

Tip: instead of useing var fruitArr:Array = new Array(); which you may have seen before. Using the square braces will do same thing. var fruitArr:Array = [];

If we think of our application as if it were an engine, the data objects (arrays, XML) are the fuel. The part of the application that interates like loops, enter frame events and timers are the heart of the engine, like the pistons, cams and crank shaft. This engine starts once the app loads and runs until we stop everything or close the app.

for() Loop:
Interates or repeats a a specified amount allowing our engine to apply the same code to multiple objects. Loops will run and complete in between each frame, before each render. This means you will not visually see what the loop is doing until it completes and the stage renders.

?View Code ACTIONSCRIPT
// This is a loop using the array from above:
for(var p:String in fruitArr){
trace(fruitArr[p] + " | index = " + p);
}
 
output:
apple | index = 0
banana | index = 1
pear | index = 2

First we assign a variable to the item that is going to loop trough the array. p stands for property and is a string. Here you can see the output of "p" which is showing the index or location of each item in the array. Notice that "apple" is the first item, which has an index of 0. If we get the length of the array (fruitArr.length) it will return a 3 which is 1 more then the last index in the array (2). Length counts like we do, starting at #1, index counts like computers do, starting at 0.

Tip: The p variable outputs a number in this case. This number is not really a number, it is a string using number characters. If we tried to add these "numbers" up, we would get "012" instead of the sum of 3. This is one reason declaring variable types are important. The compiler will tell us immediately if we are passing a string into an equation where a number or integer should be. Many external data sources will pass numbers into Flash as strings. Declaring variable types adds integrity to our applications.

Function:
A function is like a little wrapper or snippet of code that we can call at a later time. They are like the transmission, servos, clutch and any other metaphorical mechanism that takes energy and makes stuff happen.

Functions can run with or without feedback, adding a few arguments they can become very flexible. Let's use our fruit price calculator equation as a sample. This function receives two arguments (quantity and price), does the calculation, then returns the price. Nothing happens when the script loads, only when the function is called, see below.

?View Code ACTIONSCRIPT
function chaChing(quantity:int, price:Number):Number{
var calc:Number = price * quantity;
return calc;
}
var totalCost:Number = chaChing(5, 0.85);
trace(totalCost); //$4.25
 
// Notice the declaration :Number after the close parenthases
// on the function name.
function chaChing():Number{
}
 
// This lets the compiler know that the function is returning
// a value when it is called. If we do not need to return a value
// when the funciton is called, we would use void.
 
function chaChing():void{
}

This is a really simple one line function, but even this is a valid use. If you ever use the same equation or sequence more then once in your application, wrap it in a function.

Tip: A variables declared inside of a function will not be accessable outside of that function, but variables decaleared outside of the function are visible to it.

Tip: The words method and function are interchangeable.

Tip: Most "Real" programmers will put the opening curly brace one the next line under the function name.

if / else Condition:
Basically a switch, if a cindition is met, do one thing, if not then do something different.

Event:
These enable our controls and is the triggering system for our functions. Events monitors the engine and user input, they can be considered part of the engines electrical system.

Finally the Application:
The simple application we are going to build is an image loader. We will build a custom button, the code will place a button on the stage for each image. We will then hook up these controls to dynamically load in each image.

The beginning of our app is the config area, this is where we set up all of our variables and any constants.

?View Code ACTIONSCRIPT
/*
* first is the array, this is a list of image urls.
* We are going to loop through this array to create the correct amount of buttons.
* When the buttons are pressed, we will use the array to pull to corresponding image url.
*/
var imageArr:Array = ["images/apple.jpg","images/banana.jpg","images/pear.jpg"];
 
 
/****************************************************
* variables
****************************************************/
// buffHeight: will be use this to calulate the y possition of each button.
// 22 is the y coordinate to start the first button.
var buffHeight:int = 22;
 
// loadX and loadY: This will place our image in the correct spot on the stage.
var loadX:int = 156;
var loady:int = 22;
 
/****************************************************
* the loop:
* Iterates through the array, adds a button for each item, adds event listeners,
* updates the buffHeight variable then stops when it reaches the end of the array.
*****************************************************/
 
// There are a few different types of loops, this one is based on the items of an array.
// The first part of the loop conditions is declaring a variable to represent the index
// as the loop iterates through the array.
 
for(var p:String in imageArr){
 
// create new ImageButton
var imgBtn:ImageButton = new ImageButton();
 
// add a button label
imgBtn.labelText.text = "Image " + p;
 
// give the button a id from "p" which references the index
// of the current item in the array.
imgBtn.id = int(p);
 
// set the y property using the buffHeight variable.
imgBtn.y = buffHeight;
imgBtn.x = 20;
 
// add the eventListener to capture the button clicks
imgBtn.addEventListener(MouseEvent.CLICK,clickHandler);
 
//add the button to the stage.
addChild(imgBtn);
 
//update the variable with the height of this button, so the next button's y position will be below it.
buffHeight += imgBtn.height + 5;
}
 
/****************************************************
* function clickHandler(MouseEvent)
* handler for the Click MouseEvent assigned to each button in the loop.
****************************************************/
function clickHandler(ev:MouseEvent):void{
 
// the event's target property tells which button fired the event, now we can get the correct id.
var id:int = ev.currentTarget.id;
 
//use the id and the imageArr to get the correct image url.
var url:String = imageArr[id];
 
//call the loadImage function with the url as an argument.
loadImage(url);
}
 
/****************************************************
* function loadImage(url:String)
* function for loading the images
****************************************************/
function loadImage(url:String):void{
 
// new variable of new loader object
var ldr:Loader = new Loader();
 
// new URLRequest using the url we passed in as an argument.
// this converts the string into a url request we can pass to the loader to load the image.
var req:URLRequest = new URLRequest(url);
 
//loading the image
ldr.load(req);
 
ldr.x = loadX;
ldr.y = loady;
 
// add loader to MovieClip referenced by loadTarget.
addChild(ldr);
}
 
stop();

Button code and instructions:
Make a new MovieClip. Inside this new MovieClip create some artwork to be used as the button background. Add a textField and variable declaration for id (we will pass in the id during the loop). Then check the Export to ActionScript option in the MovieClips *properties window.

*To get to the MovieClips property window, right-click on the MovieClip in the Library, then choose properties. You may need to click the advanced button to see all the options.

We are using a MovieClip instead of a button, so that we can pass in an id and control the text. So we are going to build a MovieClip to act as a button.

Source Here

Where to go from here:
1. Play with the application variables and the array. Expand the app by giving each button a better name. Maybe build the array using names in stead of urls, then you can create the new url string using "images/" + name + ".jpg". You could also create a name array in the same sequence or use slice on the url to pull the name out.

2. Expand the buttons, if you really want to get fancy, create an on-state for each button, so that you can tell which image is currently displayed.

3. Add the calculator code to display how much each item cost when you click a button and a loader.

Tip: The ldr function above places one item on top of another, this may cause an issue if you want to show something behind each image while it is loading.

Take the existing code and come up with another uses for it. If you come up with some cool ideas, post some links below. Also if you figure out any of the previous enhancement, post some code.

To put your code in a code block, you can wrap it in these tags. Take out the "[" and "]" ,square brackets.
[<]pre lang="actionscript"[>]
// all code goes here.
[<]/pre[>]

Construction

Wether I am illustrating an imaginary device or something I use everyday, mind it is good to understand how the object is or should be constructed. Other information like functionality, page and how these objects are interacted with are very important in making our illustrations more convincing.

Questions you could ask yourself are how much heft and mass does this object possess, What kids of materials are used to build this object? How does this information effect how light reflects/refracts off the object. These evaluations help us understand how the details should be rendered.

The object could be steel, but is it built assembled with welds, bolts or both? The object could be made from concrete, Styrofoam, wood, glass or plastic molds. Each material is assembled differently with different types of joints. The time when an object is built also will give us a clue as to the type of assembly would have been used. We should carry that information or hints of that information into our illustration.

We do not have to have an engineering degree to know that some buildings are made from glass and steal, brick/concrete block, or wood. A glass building would be smooth and shiny on the outside with little definition where each glass plate comes together. Brick buildings have thick walls so windows are inset into the wall. Wood buildings have window frames that are used to hold the window into the wall.

These are the types of things that should be going through our heads as we sketch, construct, color, and touch up our work. In the meantime we are building our forms in Illustrator, here are some techniques to speed up our work as we construct our illustrations with the provided tools.

Using divide and Unite:
Divide and Unite are two pathfinder tools I use the most. You should set these to actions with keyboard shortcuts.

Divide Tip 1:
Create a shadow, reflection, glare on a larger shape. One of the rules for quick illustration in Illustrator is to never draw the same line twice. Another rule is divide does not have to be destructive. If you have ever used Divide before on a shape and zoomed out, sometimes you will notice a little background seeping through where the Divide incision are applied.

Draw the path how you would like your incision, over lapping on both ends and making sure the path has no fill. Select the larger shape first, Copy and Paste in Front (Command + F / Cntr + F) then select the line you created for your incision. Apply the Divide to the shape and delete the unwanted piece.

This creates a smaller shape on top of the original shape, in seconds, with no gaps and non-destructive. If we do not like the way it looks, we can always delete it and start over with our original shape still intact.

Divide Tip 2:
Again Divide does not have to be destructive. If you have a few overlapping paths, Divide with create a joined shape and trim off the excess paths. This can come in handy when using a grid, copy the lines we want to use from the grid, and apply a Divide. You will now have a new shape that matches your guides without having to draw anything. We drew the lines once for the guide, we should not have to draw them a gain.

Divide Tip 3:
Overlap your paths with working with divide. It is much easier to make sure your division are complete if you see your incision paths are overlapping your original shape.

Unite Tip 1:
Sometimes Divide can have some unwelcome results, but they can be cleaned up quickly with Unite.

Unite Tip 2:
Unite goes hand with Outline Stroke. If you have a fill and a stroke, using Outline Stroke then Unite will convert a path into a new solid shape. I like to use this for making nice outlines or inking effects. Depending on your Illustrator Preference settings, paths will scale on one machine and not another. It is also a good idea to Outline & Unite paths if the size relationship is important.

Below is a simple funny faced frog made almost intierly with the oval tool and Outlined paths.

For a better explanation of these tips, watch Illustrating in Illustrator, the Happy Frog video tutorial.

Flash tip: Paths have never translated well to Flash, so try Outline & Unite before importing to Flash.

Offset Stroke:
Found in the Object:Path menu, is similar to Outline Stroke. In CS3 and before the new path is automatically grouped to the original path. So if you have a few paths being made from the Outline Stroke command, you will have to select all the pieces and Cut & Paste them out of the group to work with them easier. I still use it very often, mostly on simpler shapes.

In Illustrator CS4 Outline Stroke works much better and mimics the functionality mentioned in Unite Tip 2.

Duplicate and Transform:
There are many times while we are illustrating that we come across many objects that are similar like windows, bolts, or even spider eyes. By completing on object, then copying and distributing those copies around will make creating all these objects less redundant. Even if shapes, size, perspective differ, there may be parts that are reusable, or a quick transform can really help save time.

Drawing vs Editing:
We have discussed never drawing the same line twice and was to create new shapes from exiting ones. Also we went over duplicating shapes and objects to help speed things up. The rules in this series are just like most rules, there is very often an exception. If you are comfortable with the pen tool in Illustrator, it is almost always faster to draw a new line then it is to edit an existing one. If you are tweaking a couple points on an existing path, that is one thing, but if you copy an path with the intent on modifying many points, it is most likely faster to draw a whole new path. Or at least delete the points you would like to edit, and draw a new path in it's place.

Join and Average:
Even drawing paths holding down the shift key will not always get our lines straight. The keyboard shortcut for Average is Command + Option + J on a Mac and Control + Alt + J on PC. Any lines that are supposed to be straight that for some reason are not, is just a second away from be so, but you have to remember the keyboard short cut to really make it worth while.

Another Keyboard shortcut to remember is Join. Command + J on a Mac and Control + J on PC, will be used over and over again to clean up stray points. Divide, Outline Stroke and other wonderful tools we have covered so far are great time savers but can put unwanted points in our paths. One of our objectives it to create Clean artwork. Extra points and text Miter spikes will not do, so a quick select with the Hollow Arrow, or Hollow Lasso, then Join, will clean those points up quickly.

Group and Layer as you go:
As discussed in Part 1 of the series, grouping is important in speeding up our work. It is much easier to grab a bunch of paths that have been grouped with the solid arrow, then selecting many paths to do a tweak. Many time you will be working on something else in the illustration and you will notice something you want to tweak something that was done previously. As you finish objects with multiple paths they should be grouped.

Distributing artwork in layer is a great way to create a groups too. The results of good groups is easy selection and/or isolation of parts of the illustration. Using Lock and Hide as well as layers are great ways to isolate our work.

Next - Illustrating In Illustrator 101 Part 3 of 5: Defining Shapes

For a better explanation of these tips, watch Illustrating in Illustrator, the Happy Frog video tutorial.

When a Flash/Flex app loads into a browser, abortion all urls for the swf are now relative to the file that is hosting the swf and not the location of the swf file itself. This can create issues between testing the swf locally and viewing it on the live site.

Case Study:
When building a demo to display on this blog I have to create one version with relative urls to distribute as source and a separate sample for preview using absolute urls. This is because of the setup of the blog, more about some files like the index page display from the root of the blog while all the article files have unique urls based on title and date.

In the process of developing web applications your files can be moved from a local dev environment, to a staging environment and then to a final live server. It is efficient to keep all your swfs and external files together, packaged in their own directory. During migration, directory structures of the hosting files may change causing your relative urls to break and your absolute urls to point to the wrong domain.

Solution:
In AS3's LoaderObject class there is a url property which will display the url of root swf. This is nice to know because now I can place files relative to the swf file and one version will work offline, in the testing environment, one the final server and best of all my blog.

The same property is available in AS2, see below.

How to make your relative urls work based on the swf url:
The "url" property returns the url to the root swf file. This is too much information, but with a little trimming we can get exactly what we need.

AS3 Method:

?View Code ACTIONSCRIPT
var swfURL:String = this.loaderInfo.url;
swfURL = swfURL.substr(0, swfURL.lastIndexOf("/") + 1)
trace(swfURL);

AS2 Method:

?View Code ACTIONSCRIPT
var swfURL:String = this._url;
swfURL = swfURL.substr(0,swfURL.lastIndexOf("/") + 1);
trace(swfURL);

Now add the swfURL variable as a prefix to all your urls like so:
var imgUrl:String = swfURL + "images/image1.jpg";

Tip:
To get the hosting domain url you can use this (AS2 & AS3):

?View Code ACTIONSCRIPT
var tempDom:Array = swfURL.split("/");
var domURL:String = tempDom.slice(0,3).join("/") + "/";
trace(domURL);

Adobe MAX 2008 kicks off with Shantanu Narayen, troche Adobe CEO.

I will do some live blogging from MAX. All post are being typed on my iPhone, due to my broken laptop, so do not expect a lot of details.

Over 5000 in attendence.

Followed by 2 more MAX conferences in europe and Asia.

Flash catalyst announced, previously Thurmo.

(Red) Wire announced, delivered on AIR. $5 a month.

Kevin Lynch on stage.

Cloud and client. Across multiple screens/devices.

Flash player 10 is awesome.
Audio waveform data, 3D, text engine, drawing API, pixel blender.
FAST realtime processing.

Max keynote is available online now. keynote

I cannot do it justice from my iPhone, pilule so check it out.

Updates:

Apparantly the keynote video does not live at the address I placed above, visit web that is what was on the big screen at the end of the keynote. sorry about that.
Here are a couple links of real live blogging (bet they had a laptop).
Liveblogging MAX 2008 Day 1 General Session Keynote

Adobe MAX 2008: Monday - Keynote

Tour de Flex on a 20' screen, shot by Greg Wilson. Tour de Flex on a 20 ft Screen
The first day of MAX has ended at 10:30 pm Monday night. East coast time is taking it's toll, sales but I know I am not the only one. I just finished moderating a video tips group that was full of drooping eyes.

Today was a success with 4 new t-shirts and a few new tips learned. All of the sessions are going to be available for free at Adobe TV. I have heard the Flash Catylist (thermo) sessions were really good, information pills the Flash Player Internals session had some nice insight on optimizing code, this my favorite one of the day. The Flex Tips session showed off some features of Flex Builder that I never new existed and now will not be able to live without.

MAX 2008 Sessions added to Adobe TV - 12/11/08

MAX 2008 on Adobe TV.

In a Birds-Of-A-Feather discussion group at Adobe MAX last week. No remarks were planned, search It was supposed to be a discussion, stuff we hoped to talk to other developers about what's new in using Flash video. We did not get a bunch of new information but we did get a lot of hard questions. Some of them were not fully answered and others were speculated upon. When I was asked my tips, I gave all I could think of at the time. Later that evening I remembered a couple more, some of my best ones.

So for those who went to MAX and those that did not, here are my official video tips for Flash and Flex.

Disclaimer: Technology changes on a regular basis, as of the date of this post I feel very comfortable with the statements made below. As new versions of software are released some of the comments may become outdated.

1. Your source file is king when it comes to getting good quality video. A good source file is the difference between hulu and youtube video. If you have control over your video source, make sure you get a good high-res lossless video file. They are huge and some clients do not know what you are talking about when you ask for it, but try your best to get a good source file.

2. Encode your own files. There are many flv encoders out there, some even your clients can use. But if you want good quality, then encode them yourselves. Of course some clients are pretty savvy when it comes to these things, in that case train them.

3. Use the Flash Video Encoder standalone application. *I have exported flv's from many other programs, but quality is more consistent with the Flash Video Encoder application. Plus the encoding speed is a lot better with the Flash Video Encoder. It does suck to encode something twice, once to a lossless file, then a second time to flv, but in my testing it has been worth it.
(*H.264 can be encoded from other applications with equal quality. I have not compared them yet, but it is a very standard codec.)

4. If you do not have Flash CS4, use on2 VP6 encoding, it is much better than the other codec options. H.264 is a great improvement even over on2 VP6. Mp4 files can use different codecs, so make sure you are using H.246 and mp3 audio if you are encoding with other applications.

5. Not all video files are the same. Video containing a lot of motion/action can not handle as much compression as a low motion, talking head video. You will have to test your video files and encode each file with different settings to get optimum performance, size and quality. Also if you have control over the editing of your source files, certain video transitions (cross dissolve) encode worse than others.

6. Do not change frame rate when encoding an flv. This will cause your a/v sync to drift. Any edits to frame rate needs to be made in your source file before you encode. This does not apply to video without sound.

7. Dropping FPS and lowering the Key Frame Interval can lower file size of the flv, but there are consequences. For lowering frame rate, see number 6. Lowering the frame rate interval will effect fast-forwarding and rewinding and may effect syncing between key frames. If you need smooth fast forward and rewind, then leave the key frame interval to automatic or raise it a little more. I believe it is set to 24 frames by default.

8. If you want to have good streaming performance, place your streaming files on a server setup for streaming content. There could be cross-domain security sandbox issues, if your files do not load, first check if you need a crossdomain.xml file.

9. Video has come along way from the timeline full of image sequences from pre Flash MX days. Video still has a large file size that can only be compressed so far. Video needs to buffer before playing and can consume a lot of CPU. If possible stop other animations, visual effects, and any processor intense code while your videos are playing.

10. There are still times when video is not the best solution. I still use image sequences if the job requires it, even though video can be the easier way to go in most cases. You may have to push your animation skills to pull off video type effects. Building your animation in Flash will give you more control over the size and quality of your project.

Using Random in Game Development, buy with strict guidelines, order can bring some variety to game play.

This sample is not a single solution but an approached I used in developing Whacky Voting - a politically smashing game. It uses random with some strict rules to get rid of sequences that some players can easily remember, yet keeping game play consistent from one game to the next.

This demo starts with a configuration section, used to set up how we want the game to act. The engine it self could be organized a little better to be more transportable. It is commented pretty well though, so it should be easy enough to understand the approach as well as practical usage. Random is used to shuffle all of the objects that appear on screen as well as what container the objects are associated with.

Configuration:
We use config data for each game so that we can easily tweak game-play without hacking our code later. We can use arrays, xml or other data sources. Plan ahead and build config options into your game as it is developed.

This array designates slots or containers to hold each appearing object. Use this to limit how many objects appear at a time and where they are placed on screen. this can represent MovieClips or other classes.

?View Code ACTIONSCRIPT
var objHolderArr:Array = [];
objHolderArr[0] = {obj:"object0",id:0,stat:false,timer:20,type:"",score:0,targ:null,xCoor:10};
objHolderArr[1] = {obj:"object1",id:1,stat:false,timer:20,type:"",score:0,targ:null,xCoor:90};
objHolderArr[2] = {obj:"object2",id:2,stat:false,timer:20,type:"",score:0,targ:null,xCoor:170};
objHolderArr[3] = {obj:"object3",id:3,stat:false,timer:20,type:"",score:0,targ:null,xCoor:250};
objHolderArr[4] = {obj:"object4",id:4,stat:false,timer:20,type:"",score:0,targ:null,xCoor:330};
objHolderArr[5] = {obj:"object5",id:5,stat:false,timer:20,type:"",score:0,targ:null,xCoor:410};

Next is an array of objects to appear, this is to control what type of objects appear and to make sure they are nicely distributed through out each level. You may have different scores, wilds and/or bonus score objects that need to get incorporated into the object list, but using random by it self will not allow them to be distributed appropriately for consistent game play.

?View Code ACTIONSCRIPT
var objSequenceArr:Array = [];
objSequenceArr[0] = {obj:"type0", count:20,score:100};
objSequenceArr[1] = {obj:"type1", count:15, score:150};
objSequenceArr[2] = {obj:"type2", count:5, score:500};
objSequenceArr[3] = {obj:"type3", count:5, score:1000};
objSequenceArr[4] = {obj:"null", count:5, score:0};
 
//timer increment for the engine to trigger an event
var timeInc:int = 500;
 
// integer to keep track of increment of game engine
var arrLoc:int = 0;
 
// random key
var randomKey:int = 1000;
 
// time for each object to stay visible;
var delay:int = 4;

It is good to set game status variables to allow games controls to be a little more intuitive. Sometimes I use a gameStatus string variable and a string to denote the current status. That way I can get more mileage out of one variable.

?View Code ACTIONSCRIPT
var gameOver:Boolean;
 
//or
 
var gameStatus:String = "_play";

Build Config Data for Engine:
The current level array built from config data above. The method then adds to the level array all the objects that we want to appear during the game.

?View Code ACTIONSCRIPT
var levelArr:Array = [];
 
function buildConfigData():void{
for(var p:String in objSequenceArr){
var loopCnt:int = objSequenceArr[p].count;
for(var i:uint = 0; i < loopCnt; i++){
var randNum:int = randomNumber(randomKey);
levelArr.push({obj:objSequenceArr[p].obj, score:objSequenceArr[p].score, key:randNum});
}
}
 
levelArr.sortOn("key",Array.NUMERIC || Array.DESCENDING);
}
buildConfigData();

Last, we sort the list so that it is shuffled which gives us the first random effect. All the objects are placed in the array in order of the sequence array, but we added a random number as the key to sort the array with. Now all of the objects will be randomly placed throughout the array and we will always have the right amount of objects for consistent game play.

Game Engine:
Now that we have our data, we are ready to start the engine.

1. Pull first random number

2. Loop until random number is not a slot that is already taken. We add a break and status variable to stop the loop if we can not find an available object. On a break, we will wait until the next TimerEvent and try again.

3. We have an active slot that is not already taken, we set it's status to true and show and configure our object.

4. Use this timer event to also run our Active Checker Method below. The more you can piggy-back off of single timers and EnterFrame events the better.

?View Code ACTIONSCRIPT
var timer:Timer = new Timer(timeInc,0);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
 
function timerHandler(ev:TimerEvent):void{
 
//1.
var randSlot:int = randomNumber(objHolderArr.length);
 
//2.
if(arrLoc < levelArr.length){
if(levelArr[arrLoc].obj != "null"){
var breakCnt:int
var breakStatus:Boolean;
while(objHolderArr[randSlot].stat == true){
randSlot = randomNumber(objHolderArr.length);
breakCnt ++;
if(breakCnt >= 100){
breakStatus = true;
break;
}
}
 
if(!breakStatus){
//3.
var slotObj:Object = objHolderArr[randSlot];
slotObj.stat = true;
slotObj.timer = delay;
slotObj.score = levelArr[arrLoc].score;
slotObj.type = levelArr[arrLoc].type;
 
//******* add code here to initiate your visual objects.
var tempBO:ballObj = new ballObj();
tempBO.x = slotObj.xCoor;
tempBO.y = 20;
tempBO.objIDStr = arrLoc.toString();
tempBO.objScoreStr = levelArr[arrLoc].score;
tempBO.objTypeStr = levelArr[arrLoc].obj;
addChild(tempBO);
 
//********* end visual code here.
 
slotObj.targ = tempBO;
activeObjArr.push(slotObj);
// we advance the array location variable.
arrLoc ++;
}
}
else{
arrLoc ++;
}
}
 
//4.
activeChecker();
}

After each object is initiated, we need to give them an amount of time to be active. This is the activeObject array, we will track the time, if the user does not score with the object then it will be removed by the timer.

1. Loop through the active array to decrease each object's timer.

2. If the timer is run out, remove the object from the array and reset the object's status.

?View Code ACTIONSCRIPT
var activeObjArr:Array = [];
 
function activeChecker():void{
for(var p:String in activeObjArr){
//1.
activeObjArr[p].timer --;
 
//2.
if(activeObjArr[p].timer <= 0){
activeObjArr[p].stat = false;
removeChild(activeObjArr[p].targ);
activeObjArr.splice(int(p),1);
 
if(arrLoc >= levelArr.length && activeObjArr.length == 0){
//game is over.
gameOver = true;
timer.stop();
btn.enabled = true;
btn.alpha = 1;
}
}
}
}

Here is where you can place your event handlers for a user interactive with an object. We have to remove and reset the object, shown above and add the objects score to the main score.

We will also need a method for when the game clears the last array object.

Utilities:
method to pull random numbers just so I do not need to write this same code more than once.

?View Code ACTIONSCRIPT
function randomNumber(limit:int):int{
var randNum:int = Math.random()*limit;
return randNum;
}

Controls:
A restart control availble when game is over

?View Code ACTIONSCRIPT
btn.addEventListener(MouseEvent.CLICK,clickHandler);
btn.enabled = false;
btn.alpha = 0.2;
function clickHandler(ev:MouseEvent):void{
if(gameOver){
// rebuild data to show off shuffling.
levelArr = [];
buildConfigData();
 
//reset game controls and game engine.
arrLoc = 0;
timer.start();
gameOver = false;
btn.enabled = false;
btn.alpha = 0.2;
}
}

The Ball Object:
The ball object is a simple class that displays the data for each object. You would normally place a button or some other way to capture user interaction and send it back to the engine to initiate scores and feedback.

?View Code ACTIONSCRIPT
package{
import flash.display.MovieClip;
import flash.text.TextField;
import flash.events.Event;
 
public class ballObj extends MovieClip{
 
public var objIDStr:String = "";
public var objTypeStr:String = "";
public var objScoreStr:String = "";
 
public function ballObj():void{
init();
stop();
}
 
private function init():void{
this.addEventListener(Event.ADDED,addedHandler);
}
 
private function addedHandler(ev:Event):void{
objID.text = objIDStr;
objScore.text = objScoreStr;
objType.text = objTypeStr;
 
}
}
}

Source Here
This is it, about it the very first bit of actionscript code I ever learned, site besides play() and gotoAndStop() of course. The lesson went down with an experienced programmer looking over my shoulder telling me what to type. After this little app was finished, approved my brain hurt only understanding a few of the lines we wrote. That code was referenced and/or modified on more then a few projects that came after, each time deciphering more and applying it to new functionalities.

The original script was back in the day of AS1, but I am going to present it to you in AS3. If you are a beginner to ActionScript then it is the perfect time to learn AS3.

We are going to start really remedial for a minute and go over the basics of the classes and objects we will be using. It is kind-of long, so if you already have the basics covered, you can skip to the Application code.

The Variable:
Remember Pre-Algebra? 2+x = y? Variables are used for more then just place holders in a math equation. Programming is a very literal language, variables are how we make it figurative. Now instead of addressing one object with a snippet of code, that code can be applied to the many objects and properties our variables represent.

To use a variable, we must declare it using these three letters "var". Then comes the creative part, we get to think of a name. This can be a lot of fun making up funny names for things until someone else has to figure out your code or you forget that you called the variable that is going to bring balance to your application "anakin", oops, or was that "luke"?

After naming the variable, we have to declare it's type. We really don't have to, but it is a good idea. This variable will be a Number, because we will need it to include decimals.

Here are some examples of how variables can be used. Think about if we were selling apples that costs 65¢ a peace. A person wants to buy 5 apples. so we build an equation to handle the transaction.

?View Code ACTIONSCRIPT
var totalCost:Number;
totalCost = 0.65 * 5; //3.25

Ok, so we went conservitive, using "totalCost" for the total of apples purchased. Now what do we do when someone wants to buy 4 apples, or 6, or 8? Now we should add a new variable to represent the amount of apples. This variables declaration is an "int" (integer) as we will not be selling fractions of apples.

?View Code ACTIONSCRIPT
var numApples:int = 5;
var totalCost:Number;
totalCost = 0.65 * numApples; // 3.25

Everyone is happy until next week when there is an apple shortage and the price increases to 85¢ a piece. Now you have to go through you app and change all the prices from 65¢ to 85¢. If we use variables we can easily modify the app when the price changes, better yet, now this same app could be used to handle bananas, grapefruit and pears which all have different prices.

?View Code ACTIONSCRIPT
var cost:Number = 0.85;
var numFruit = 5;
var totalCost:Numer;
totalCost = cost * numFruit; // $4.25

Array:
Array is one of the most powerful classes in Flash. It's power comes from the way an array holds a collection of information. Not only do we have access to the information, but we can loop through all the items in an array and monitor the length of the collection.

This is how we might set up some variables without arrays. If we add or take away an item, we have to update a separate variable to keep track of the total amount. Looping through this is information is possible, but tricky.

?View Code ACTIONSCRIPT
var fuit1:String = "apple";
var fruit2:String = "banana";
var fruit3:String = "pear";
var fruits:int = 3;
 
// Or we can do the same thing with an array.
 
var fruitArr:Array = ["apple","banana","pear"];
 
trace(fruitArr[0]); //"apple
trace(fruitArr.length); //3

One thing that you must remember when using arrays is that they are zero indexed, meaning the first position in the array is 0. This can cause a little confusion because we teach our children to start counting at 1, not 0. This will hopefully make more sense later or maybe more confusion, but at least you will know why you are confused.

Tip: instead of useing var fruitArr:Array = new Array(); which you may have seen before. Using the square braces will do same thing. var fruitArr:Array = [];

If we think of our application as if it were an engine, the data objects (arrays, XML) are the fuel. The part of the application that interates like loops, enter frame events and timers are the heart of the engine, like the pistons, cams and crank shaft. This engine starts once the app loads and runs until we stop everything or close the app.

for() Loop:
Interates or repeats a a specified amount allowing our engine to apply the same code to multiple objects. Loops will run and complete in between each frame, before each render. This means you will not visually see what the loop is doing until it completes and the stage renders.

?View Code ACTIONSCRIPT
// This is a loop using the array from above:
for(var p:String in fruitArr){
trace(fruitArr[p] + " | index = " + p);
}
 
output:
apple | index = 0
banana | index = 1
pear | index = 2

First we assign a variable to the item that is going to loop trough the array. p stands for property and is a string. Here you can see the output of "p" which is showing the index or location of each item in the array. Notice that "apple" is the first item, which has an index of 0. If we get the length of the array (fruitArr.length) it will return a 3 which is 1 more then the last index in the array (2). Length counts like we do, starting at #1, index counts like computers do, starting at 0.

Tip: The p variable outputs a number in this case. This number is not really a number, it is a string using number characters. If we tried to add these "numbers" up, we would get "012" instead of the sum of 3. This is one reason declaring variable types are important. The compiler will tell us immediately if we are passing a string into an equation where a number or integer should be. Many external data sources will pass numbers into Flash as strings. Declaring variable types adds integrity to our applications.

Function:
A function is like a little wrapper or snippet of code that we can call at a later time. They are like the transmission, servos, clutch and any other metaphorical mechanism that takes energy and makes stuff happen.

Functions can run with or without feedback, adding a few arguments they can become very flexible. Let's use our fruit price calculator equation as a sample. This function receives two arguments (quantity and price), does the calculation, then returns the price. Nothing happens when the script loads, only when the function is called, see below.

?View Code ACTIONSCRIPT
function chaChing(quantity:int, price:Number):Number{
var calc:Number = price * quantity;
return calc;
}
var totalCost:Number = chaChing(5, 0.85);
trace(totalCost); //$4.25
 
// Notice the declaration :Number after the close parenthases
// on the function name.
function chaChing():Number{
}
 
// This lets the compiler know that the function is returning
// a value when it is called. If we do not need to return a value
// when the funciton is called, we would use void.
 
function chaChing():void{
}

This is a really simple one line function, but even this is a valid use. If you ever use the same equation or sequence more then once in your application, wrap it in a function.

Tip: A variables declared inside of a function will not be accessable outside of that function, but variables decaleared outside of the function are visible to it.

Tip: The words method and function are interchangeable.

Tip: Most "Real" programmers will put the opening curly brace one the next line under the function name.

if / else Condition:
Basically a switch, if a cindition is met, do one thing, if not then do something different.

Event:
These enable our controls and is the triggering system for our functions. Events monitors the engine and user input, they can be considered part of the engines electrical system.

Finally the Application:
The simple application we are going to build is an image loader. We will build a custom button, the code will place a button on the stage for each image. We will then hook up these controls to dynamically load in each image.

The beginning of our app is the config area, this is where we set up all of our variables and any constants.

?View Code ACTIONSCRIPT
/*
* first is the array, this is a list of image urls.
* We are going to loop through this array to create the correct amount of buttons.
* When the buttons are pressed, we will use the array to pull to corresponding image url.
*/
var imageArr:Array = ["images/apple.jpg","images/banana.jpg","images/pear.jpg"];
 
 
/****************************************************
* variables
****************************************************/
// buffHeight: will be use this to calulate the y possition of each button.
// 22 is the y coordinate to start the first button.
var buffHeight:int = 22;
 
// loadX and loadY: This will place our image in the correct spot on the stage.
var loadX:int = 156;
var loady:int = 22;
 
/****************************************************
* the loop:
* Iterates through the array, adds a button for each item, adds event listeners,
* updates the buffHeight variable then stops when it reaches the end of the array.
*****************************************************/
 
// There are a few different types of loops, this one is based on the items of an array.
// The first part of the loop conditions is declaring a variable to represent the index
// as the loop iterates through the array.
 
for(var p:String in imageArr){
 
// create new ImageButton
var imgBtn:ImageButton = new ImageButton();
 
// add a button label
imgBtn.labelText.text = "Image " + p;
 
// give the button a id from "p" which references the index
// of the current item in the array.
imgBtn.id = int(p);
 
// set the y property using the buffHeight variable.
imgBtn.y = buffHeight;
imgBtn.x = 20;
 
// add the eventListener to capture the button clicks
imgBtn.addEventListener(MouseEvent.CLICK,clickHandler);
 
//add the button to the stage.
addChild(imgBtn);
 
//update the variable with the height of this button, so the next button's y position will be below it.
buffHeight += imgBtn.height + 5;
}
 
/****************************************************
* function clickHandler(MouseEvent)
* handler for the Click MouseEvent assigned to each button in the loop.
****************************************************/
function clickHandler(ev:MouseEvent):void{
 
// the event's target property tells which button fired the event, now we can get the correct id.
var id:int = ev.currentTarget.id;
 
//use the id and the imageArr to get the correct image url.
var url:String = imageArr[id];
 
//call the loadImage function with the url as an argument.
loadImage(url);
}
 
/****************************************************
* function loadImage(url:String)
* function for loading the images
****************************************************/
function loadImage(url:String):void{
 
// new variable of new loader object
var ldr:Loader = new Loader();
 
// new URLRequest using the url we passed in as an argument.
// this converts the string into a url request we can pass to the loader to load the image.
var req:URLRequest = new URLRequest(url);
 
//loading the image
ldr.load(req);
 
ldr.x = loadX;
ldr.y = loady;
 
// add loader to MovieClip referenced by loadTarget.
addChild(ldr);
}
 
stop();

Button code and instructions:
Make a new MovieClip. Inside this new MovieClip create some artwork to be used as the button background. Add a textField and variable declaration for id (we will pass in the id during the loop). Then check the Export to ActionScript option in the MovieClips *properties window.

*To get to the MovieClips property window, right-click on the MovieClip in the Library, then choose properties. You may need to click the advanced button to see all the options.

We are using a MovieClip instead of a button, so that we can pass in an id and control the text. So we are going to build a MovieClip to act as a button.

Source Here

Where to go from here:
1. Play with the application variables and the array. Expand the app by giving each button a better name. Maybe build the array using names in stead of urls, then you can create the new url string using "images/" + name + ".jpg". You could also create a name array in the same sequence or use slice on the url to pull the name out.

2. Expand the buttons, if you really want to get fancy, create an on-state for each button, so that you can tell which image is currently displayed.

3. Add the calculator code to display how much each item cost when you click a button and a loader.

Tip: The ldr function above places one item on top of another, this may cause an issue if you want to show something behind each image while it is loading.

Take the existing code and come up with another uses for it. If you come up with some cool ideas, post some links below. Also if you figure out any of the previous enhancement, post some code.

To put your code in a code block, you can wrap it in these tags. Take out the "[" and "]" ,square brackets.
[<]pre lang="actionscript"[>]
// all code goes here.
[<]/pre[>]

Construction

Wether I am illustrating an imaginary device or something I use everyday, mind it is good to understand how the object is or should be constructed. Other information like functionality, page and how these objects are interacted with are very important in making our illustrations more convincing.

Questions you could ask yourself are how much heft and mass does this object possess, What kids of materials are used to build this object? How does this information effect how light reflects/refracts off the object. These evaluations help us understand how the details should be rendered.

The object could be steel, but is it built assembled with welds, bolts or both? The object could be made from concrete, Styrofoam, wood, glass or plastic molds. Each material is assembled differently with different types of joints. The time when an object is built also will give us a clue as to the type of assembly would have been used. We should carry that information or hints of that information into our illustration.

We do not have to have an engineering degree to know that some buildings are made from glass and steal, brick/concrete block, or wood. A glass building would be smooth and shiny on the outside with little definition where each glass plate comes together. Brick buildings have thick walls so windows are inset into the wall. Wood buildings have window frames that are used to hold the window into the wall.

These are the types of things that should be going through our heads as we sketch, construct, color, and touch up our work. In the meantime we are building our forms in Illustrator, here are some techniques to speed up our work as we construct our illustrations with the provided tools.

Using divide and Unite:
Divide and Unite are two pathfinder tools I use the most. You should set these to actions with keyboard shortcuts.

Divide Tip 1:
Create a shadow, reflection, glare on a larger shape. One of the rules for quick illustration in Illustrator is to never draw the same line twice. Another rule is divide does not have to be destructive. If you have ever used Divide before on a shape and zoomed out, sometimes you will notice a little background seeping through where the Divide incision are applied.

Draw the path how you would like your incision, over lapping on both ends and making sure the path has no fill. Select the larger shape first, Copy and Paste in Front (Command + F / Cntr + F) then select the line you created for your incision. Apply the Divide to the shape and delete the unwanted piece.

This creates a smaller shape on top of the original shape, in seconds, with no gaps and non-destructive. If we do not like the way it looks, we can always delete it and start over with our original shape still intact.

Divide Tip 2:
Again Divide does not have to be destructive. If you have a few overlapping paths, Divide with create a joined shape and trim off the excess paths. This can come in handy when using a grid, copy the lines we want to use from the grid, and apply a Divide. You will now have a new shape that matches your guides without having to draw anything. We drew the lines once for the guide, we should not have to draw them a gain.

Divide Tip 3:
Overlap your paths with working with divide. It is much easier to make sure your division are complete if you see your incision paths are overlapping your original shape.

Unite Tip 1:
Sometimes Divide can have some unwelcome results, but they can be cleaned up quickly with Unite.

Unite Tip 2:
Unite goes hand with Outline Stroke. If you have a fill and a stroke, using Outline Stroke then Unite will convert a path into a new solid shape. I like to use this for making nice outlines or inking effects. Depending on your Illustrator Preference settings, paths will scale on one machine and not another. It is also a good idea to Outline & Unite paths if the size relationship is important.

Below is a simple funny faced frog made almost intierly with the oval tool and Outlined paths.

For a better explanation of these tips, watch Illustrating in Illustrator, the Happy Frog video tutorial.

Flash tip: Paths have never translated well to Flash, so try Outline & Unite before importing to Flash.

Offset Stroke:
Found in the Object:Path menu, is similar to Outline Stroke. In CS3 and before the new path is automatically grouped to the original path. So if you have a few paths being made from the Outline Stroke command, you will have to select all the pieces and Cut & Paste them out of the group to work with them easier. I still use it very often, mostly on simpler shapes.

In Illustrator CS4 Outline Stroke works much better and mimics the functionality mentioned in Unite Tip 2.

Duplicate and Transform:
There are many times while we are illustrating that we come across many objects that are similar like windows, bolts, or even spider eyes. By completing on object, then copying and distributing those copies around will make creating all these objects less redundant. Even if shapes, size, perspective differ, there may be parts that are reusable, or a quick transform can really help save time.

Drawing vs Editing:
We have discussed never drawing the same line twice and was to create new shapes from exiting ones. Also we went over duplicating shapes and objects to help speed things up. The rules in this series are just like most rules, there is very often an exception. If you are comfortable with the pen tool in Illustrator, it is almost always faster to draw a new line then it is to edit an existing one. If you are tweaking a couple points on an existing path, that is one thing, but if you copy an path with the intent on modifying many points, it is most likely faster to draw a whole new path. Or at least delete the points you would like to edit, and draw a new path in it's place.

Join and Average:
Even drawing paths holding down the shift key will not always get our lines straight. The keyboard shortcut for Average is Command + Option + J on a Mac and Control + Alt + J on PC. Any lines that are supposed to be straight that for some reason are not, is just a second away from be so, but you have to remember the keyboard short cut to really make it worth while.

Another Keyboard shortcut to remember is Join. Command + J on a Mac and Control + J on PC, will be used over and over again to clean up stray points. Divide, Outline Stroke and other wonderful tools we have covered so far are great time savers but can put unwanted points in our paths. One of our objectives it to create Clean artwork. Extra points and text Miter spikes will not do, so a quick select with the Hollow Arrow, or Hollow Lasso, then Join, will clean those points up quickly.

Group and Layer as you go:
As discussed in Part 1 of the series, grouping is important in speeding up our work. It is much easier to grab a bunch of paths that have been grouped with the solid arrow, then selecting many paths to do a tweak. Many time you will be working on something else in the illustration and you will notice something you want to tweak something that was done previously. As you finish objects with multiple paths they should be grouped.

Distributing artwork in layer is a great way to create a groups too. The results of good groups is easy selection and/or isolation of parts of the illustration. Using Lock and Hide as well as layers are great ways to isolate our work.

Next - Illustrating In Illustrator 101 Part 3 of 5: Defining Shapes

For a better explanation of these tips, watch Illustrating in Illustrator, the Happy Frog video tutorial.

When a Flash/Flex app loads into a browser, abortion all urls for the swf are now relative to the file that is hosting the swf and not the location of the swf file itself. This can create issues between testing the swf locally and viewing it on the live site.

Case Study:
When building a demo to display on this blog I have to create one version with relative urls to distribute as source and a separate sample for preview using absolute urls. This is because of the setup of the blog, more about some files like the index page display from the root of the blog while all the article files have unique urls based on title and date.

In the process of developing web applications your files can be moved from a local dev environment, to a staging environment and then to a final live server. It is efficient to keep all your swfs and external files together, packaged in their own directory. During migration, directory structures of the hosting files may change causing your relative urls to break and your absolute urls to point to the wrong domain.

Solution:
In AS3's LoaderObject class there is a url property which will display the url of root swf. This is nice to know because now I can place files relative to the swf file and one version will work offline, in the testing environment, one the final server and best of all my blog.

The same property is available in AS2, see below.

How to make your relative urls work based on the swf url:
The "url" property returns the url to the root swf file. This is too much information, but with a little trimming we can get exactly what we need.

AS3 Method:

?View Code ACTIONSCRIPT
var swfURL:String = this.loaderInfo.url;
swfURL = swfURL.substr(0, swfURL.lastIndexOf("/") + 1)
trace(swfURL);

AS2 Method:

?View Code ACTIONSCRIPT
var swfURL:String = this._url;
swfURL = swfURL.substr(0,swfURL.lastIndexOf("/") + 1);
trace(swfURL);

Now add the swfURL variable as a prefix to all your urls like so:
var imgUrl:String = swfURL + "images/image1.jpg";

Tip:
To get the hosting domain url you can use this (AS2 & AS3):

?View Code ACTIONSCRIPT
var tempDom:Array = swfURL.split("/");
var domURL:String = tempDom.slice(0,3).join("/") + "/";
trace(domURL);

Maintaining version control on project files can easily get out of control when saving multiple versions of the same file. One tip is covered in an earlier post about swf based relative urls for flash/flex files. This tip works even if the host file is moved to a different locations. This way we do not need to save a live version and a local build version.

Why would I care which Flash Player type is used?
Some projects, story like kiosks, approved will end up as a Flash Projector or AIR Application. Until the project is finalized and approved we may need to preview the project for our clients on the web. In AS3 some stage methods are only available to the standalone player. Instead of saving two versions of the same project, medicine one to test the Projector functionality and another for online approvals; we can build one multi-purpose file.

AS3 Method:

?View Code ACTIONSCRIPT
if(Capabilities.playerType == "StandAlone"){
stage.displayState = StageDisplayState.FULL_SCREEN;
 
// mouse hide and show for touchscreen kiosk: default (hide)
Mouse.hide();
}
trace(Capabilities.playerType); //StandAlone

AS2 Method:

?View Code ACTIONSCRIPT
trace(System.capabilities.playerType); //StandAlone

Here is a list of Flash Player type strings:
from Flash AS3 language reference
"ActiveX" for the Flash Player ActiveX control used by Microsoft Internet Explorer
"Desktop" for the Adobe AIR runtime (except for SWF content loaded by an HTML page, which has Capabilities.playerType set to "PlugIn" )
"External" for the external Flash Player or in test mode
"PlugIn" for the Flash Player browser plug-in (and for SWF content loaded by an HTML page in an AIR application)
"StandAlone" for the stand-alone Flash Player

If you need to know the player version number of the Flash Player use this code:
AS3:
trace(Capabilities.version); //MAC 10,0,2,54 or WIN 10,0,2,54

AS2:
trace(System.capabilities.version); //MAC 10,0,2,54 or WIN 10,0,2,54

tip 1: If your swf requires a newer Flash Player version, it is best to detect flash player versions using the Flash Version Detection option in the HTML publishing settings and require the user to download the newer player. SWFs published to newer Flash Player versions can be very unstable when running in older Players and can cause browser and system crashes.

tip 2:
Standalone and Desktop players are built into the executables so the Flash Player version will always be correct no matter what is currently installed on the system.

tip 3:
For a complete list of all the system capabilities you can learn about the system that is running your projects, look here.

Adobe MAX 2008 kicks off with Shantanu Narayen, troche Adobe CEO.

I will do some live blogging from MAX. All post are being typed on my iPhone, due to my broken laptop, so do not expect a lot of details.

Over 5000 in attendence.

Followed by 2 more MAX conferences in europe and Asia.

Flash catalyst announced, previously Thurmo.

(Red) Wire announced, delivered on AIR. $5 a month.

Kevin Lynch on stage.

Cloud and client. Across multiple screens/devices.

Flash player 10 is awesome.
Audio waveform data, 3D, text engine, drawing API, pixel blender.
FAST realtime processing.

Max keynote is available online now. keynote

I cannot do it justice from my iPhone, pilule so check it out.

Updates:

Apparantly the keynote video does not live at the address I placed above, visit web that is what was on the big screen at the end of the keynote. sorry about that.
Here are a couple links of real live blogging (bet they had a laptop).
Liveblogging MAX 2008 Day 1 General Session Keynote

Adobe MAX 2008: Monday - Keynote

Tour de Flex on a 20' screen, shot by Greg Wilson. Tour de Flex on a 20 ft Screen
The first day of MAX has ended at 10:30 pm Monday night. East coast time is taking it's toll, sales but I know I am not the only one. I just finished moderating a video tips group that was full of drooping eyes.

Today was a success with 4 new t-shirts and a few new tips learned. All of the sessions are going to be available for free at Adobe TV. I have heard the Flash Catylist (thermo) sessions were really good, information pills the Flash Player Internals session had some nice insight on optimizing code, this my favorite one of the day. The Flex Tips session showed off some features of Flex Builder that I never new existed and now will not be able to live without.

MAX 2008 Sessions added to Adobe TV - 12/11/08

MAX 2008 on Adobe TV.

In a Birds-Of-A-Feather discussion group at Adobe MAX last week. No remarks were planned, search It was supposed to be a discussion, stuff we hoped to talk to other developers about what's new in using Flash video. We did not get a bunch of new information but we did get a lot of hard questions. Some of them were not fully answered and others were speculated upon. When I was asked my tips, I gave all I could think of at the time. Later that evening I remembered a couple more, some of my best ones.

So for those who went to MAX and those that did not, here are my official video tips for Flash and Flex.

Disclaimer: Technology changes on a regular basis, as of the date of this post I feel very comfortable with the statements made below. As new versions of software are released some of the comments may become outdated.

1. Your source file is king when it comes to getting good quality video. A good source file is the difference between hulu and youtube video. If you have control over your video source, make sure you get a good high-res lossless video file. They are huge and some clients do not know what you are talking about when you ask for it, but try your best to get a good source file.

2. Encode your own files. There are many flv encoders out there, some even your clients can use. But if you want good quality, then encode them yourselves. Of course some clients are pretty savvy when it comes to these things, in that case train them.

3. Use the Flash Video Encoder standalone application. *I have exported flv's from many other programs, but quality is more consistent with the Flash Video Encoder application. Plus the encoding speed is a lot better with the Flash Video Encoder. It does suck to encode something twice, once to a lossless file, then a second time to flv, but in my testing it has been worth it.
(*H.264 can be encoded from other applications with equal quality. I have not compared them yet, but it is a very standard codec.)

4. If you do not have Flash CS4, use on2 VP6 encoding, it is much better than the other codec options. H.264 is a great improvement even over on2 VP6. Mp4 files can use different codecs, so make sure you are using H.246 and mp3 audio if you are encoding with other applications.

5. Not all video files are the same. Video containing a lot of motion/action can not handle as much compression as a low motion, talking head video. You will have to test your video files and encode each file with different settings to get optimum performance, size and quality. Also if you have control over the editing of your source files, certain video transitions (cross dissolve) encode worse than others.

6. Do not change frame rate when encoding an flv. This will cause your a/v sync to drift. Any edits to frame rate needs to be made in your source file before you encode. This does not apply to video without sound.

7. Dropping FPS and lowering the Key Frame Interval can lower file size of the flv, but there are consequences. For lowering frame rate, see number 6. Lowering the frame rate interval will effect fast-forwarding and rewinding and may effect syncing between key frames. If you need smooth fast forward and rewind, then leave the key frame interval to automatic or raise it a little more. I believe it is set to 24 frames by default.

8. If you want to have good streaming performance, place your streaming files on a server setup for streaming content. There could be cross-domain security sandbox issues, if your files do not load, first check if you need a crossdomain.xml file.

9. Video has come along way from the timeline full of image sequences from pre Flash MX days. Video still has a large file size that can only be compressed so far. Video needs to buffer before playing and can consume a lot of CPU. If possible stop other animations, visual effects, and any processor intense code while your videos are playing.

10. There are still times when video is not the best solution. I still use image sequences if the job requires it, even though video can be the easier way to go in most cases. You may have to push your animation skills to pull off video type effects. Building your animation in Flash will give you more control over the size and quality of your project.

Using Random in Game Development, buy with strict guidelines, order can bring some variety to game play.

This sample is not a single solution but an approached I used in developing Whacky Voting - a politically smashing game. It uses random with some strict rules to get rid of sequences that some players can easily remember, yet keeping game play consistent from one game to the next.

This demo starts with a configuration section, used to set up how we want the game to act. The engine it self could be organized a little better to be more transportable. It is commented pretty well though, so it should be easy enough to understand the approach as well as practical usage. Random is used to shuffle all of the objects that appear on screen as well as what container the objects are associated with.

Configuration:
We use config data for each game so that we can easily tweak game-play without hacking our code later. We can use arrays, xml or other data sources. Plan ahead and build config options into your game as it is developed.

This array designates slots or containers to hold each appearing object. Use this to limit how many objects appear at a time and where they are placed on screen. this can represent MovieClips or other classes.

?View Code ACTIONSCRIPT
var objHolderArr:Array = [];
objHolderArr[0] = {obj:"object0",id:0,stat:false,timer:20,type:"",score:0,targ:null,xCoor:10};
objHolderArr[1] = {obj:"object1",id:1,stat:false,timer:20,type:"",score:0,targ:null,xCoor:90};
objHolderArr[2] = {obj:"object2",id:2,stat:false,timer:20,type:"",score:0,targ:null,xCoor:170};
objHolderArr[3] = {obj:"object3",id:3,stat:false,timer:20,type:"",score:0,targ:null,xCoor:250};
objHolderArr[4] = {obj:"object4",id:4,stat:false,timer:20,type:"",score:0,targ:null,xCoor:330};
objHolderArr[5] = {obj:"object5",id:5,stat:false,timer:20,type:"",score:0,targ:null,xCoor:410};

Next is an array of objects to appear, this is to control what type of objects appear and to make sure they are nicely distributed through out each level. You may have different scores, wilds and/or bonus score objects that need to get incorporated into the object list, but using random by it self will not allow them to be distributed appropriately for consistent game play.

?View Code ACTIONSCRIPT
var objSequenceArr:Array = [];
objSequenceArr[0] = {obj:"type0", count:20,score:100};
objSequenceArr[1] = {obj:"type1", count:15, score:150};
objSequenceArr[2] = {obj:"type2", count:5, score:500};
objSequenceArr[3] = {obj:"type3", count:5, score:1000};
objSequenceArr[4] = {obj:"null", count:5, score:0};
 
//timer increment for the engine to trigger an event
var timeInc:int = 500;
 
// integer to keep track of increment of game engine
var arrLoc:int = 0;
 
// random key
var randomKey:int = 1000;
 
// time for each object to stay visible;
var delay:int = 4;

It is good to set game status variables to allow games controls to be a little more intuitive. Sometimes I use a gameStatus string variable and a string to denote the current status. That way I can get more mileage out of one variable.

?View Code ACTIONSCRIPT
var gameOver:Boolean;
 
//or
 
var gameStatus:String = "_play";

Build Config Data for Engine:
The current level array built from config data above. The method then adds to the level array all the objects that we want to appear during the game.

?View Code ACTIONSCRIPT
var levelArr:Array = [];
 
function buildConfigData():void{
for(var p:String in objSequenceArr){
var loopCnt:int = objSequenceArr[p].count;
for(var i:uint = 0; i < loopCnt; i++){
var randNum:int = randomNumber(randomKey);
levelArr.push({obj:objSequenceArr[p].obj, score:objSequenceArr[p].score, key:randNum});
}
}
 
levelArr.sortOn("key",Array.NUMERIC || Array.DESCENDING);
}
buildConfigData();

Last, we sort the list so that it is shuffled which gives us the first random effect. All the objects are placed in the array in order of the sequence array, but we added a random number as the key to sort the array with. Now all of the objects will be randomly placed throughout the array and we will always have the right amount of objects for consistent game play.

Game Engine:
Now that we have our data, we are ready to start the engine.

1. Pull first random number

2. Loop until random number is not a slot that is already taken. We add a break and status variable to stop the loop if we can not find an available object. On a break, we will wait until the next TimerEvent and try again.

3. We have an active slot that is not already taken, we set it's status to true and show and configure our object.

4. Use this timer event to also run our Active Checker Method below. The more you can piggy-back off of single timers and EnterFrame events the better.

?View Code ACTIONSCRIPT
var timer:Timer = new Timer(timeInc,0);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
 
function timerHandler(ev:TimerEvent):void{
 
//1.
var randSlot:int = randomNumber(objHolderArr.length);
 
//2.
if(arrLoc < levelArr.length){
if(levelArr[arrLoc].obj != "null"){
var breakCnt:int
var breakStatus:Boolean;
while(objHolderArr[randSlot].stat == true){
randSlot = randomNumber(objHolderArr.length);
breakCnt ++;
if(breakCnt >= 100){
breakStatus = true;
break;
}
}
 
if(!breakStatus){
//3.
var slotObj:Object = objHolderArr[randSlot];
slotObj.stat = true;
slotObj.timer = delay;
slotObj.score = levelArr[arrLoc].score;
slotObj.type = levelArr[arrLoc].type;
 
//******* add code here to initiate your visual objects.
var tempBO:ballObj = new ballObj();
tempBO.x = slotObj.xCoor;
tempBO.y = 20;
tempBO.objIDStr = arrLoc.toString();
tempBO.objScoreStr = levelArr[arrLoc].score;
tempBO.objTypeStr = levelArr[arrLoc].obj;
addChild(tempBO);
 
//********* end visual code here.
 
slotObj.targ = tempBO;
activeObjArr.push(slotObj);
// we advance the array location variable.
arrLoc ++;
}
}
else{
arrLoc ++;
}
}
 
//4.
activeChecker();
}

After each object is initiated, we need to give them an amount of time to be active. This is the activeObject array, we will track the time, if the user does not score with the object then it will be removed by the timer.

1. Loop through the active array to decrease each object's timer.

2. If the timer is run out, remove the object from the array and reset the object's status.

?View Code ACTIONSCRIPT
var activeObjArr:Array = [];
 
function activeChecker():void{
for(var p:String in activeObjArr){
//1.
activeObjArr[p].timer --;
 
//2.
if(activeObjArr[p].timer <= 0){
activeObjArr[p].stat = false;
removeChild(activeObjArr[p].targ);
activeObjArr.splice(int(p),1);
 
if(arrLoc >= levelArr.length && activeObjArr.length == 0){
//game is over.
gameOver = true;
timer.stop();
btn.enabled = true;
btn.alpha = 1;
}
}
}
}

Here is where you can place your event handlers for a user interactive with an object. We have to remove and reset the object, shown above and add the objects score to the main score.

We will also need a method for when the game clears the last array object.

Utilities:
method to pull random numbers just so I do not need to write this same code more than once.

?View Code ACTIONSCRIPT
function randomNumber(limit:int):int{
var randNum:int = Math.random()*limit;
return randNum;
}

Controls:
A restart control availble when game is over

?View Code ACTIONSCRIPT
btn.addEventListener(MouseEvent.CLICK,clickHandler);
btn.enabled = false;
btn.alpha = 0.2;
function clickHandler(ev:MouseEvent):void{
if(gameOver){
// rebuild data to show off shuffling.
levelArr = [];
buildConfigData();
 
//reset game controls and game engine.
arrLoc = 0;
timer.start();
gameOver = false;
btn.enabled = false;
btn.alpha = 0.2;
}
}

The Ball Object:
The ball object is a simple class that displays the data for each object. You would normally place a button or some other way to capture user interaction and send it back to the engine to initiate scores and feedback.

?View Code ACTIONSCRIPT
package{
import flash.display.MovieClip;
import flash.text.TextField;
import flash.events.Event;
 
public class ballObj extends MovieClip{
 
public var objIDStr:String = "";
public var objTypeStr:String = "";
public var objScoreStr:String = "";
 
public function ballObj():void{
init();
stop();
}
 
private function init():void{
this.addEventListener(Event.ADDED,addedHandler);
}
 
private function addedHandler(ev:Event):void{
objID.text = objIDStr;
objScore.text = objScoreStr;
objType.text = objTypeStr;
 
}
}
}

Source Here
This is it, about it the very first bit of actionscript code I ever learned, site besides play() and gotoAndStop() of course. The lesson went down with an experienced programmer looking over my shoulder telling me what to type. After this little app was finished, approved my brain hurt only understanding a few of the lines we wrote. That code was referenced and/or modified on more then a few projects that came after, each time deciphering more and applying it to new functionalities.

The original script was back in the day of AS1, but I am going to present it to you in AS3. If you are a beginner to ActionScript then it is the perfect time to learn AS3.

We are going to start really remedial for a minute and go over the basics of the classes and objects we will be using. It is kind-of long, so if you already have the basics covered, you can skip to the Application code.

The Variable:
Remember Pre-Algebra? 2+x = y? Variables are used for more then just place holders in a math equation. Programming is a very literal language, variables are how we make it figurative. Now instead of addressing one object with a snippet of code, that code can be applied to the many objects and properties our variables represent.

To use a variable, we must declare it using these three letters "var". Then comes the creative part, we get to think of a name. This can be a lot of fun making up funny names for things until someone else has to figure out your code or you forget that you called the variable that is going to bring balance to your application "anakin", oops, or was that "luke"?

After naming the variable, we have to declare it's type. We really don't have to, but it is a good idea. This variable will be a Number, because we will need it to include decimals.

Here are some examples of how variables can be used. Think about if we were selling apples that costs 65¢ a peace. A person wants to buy 5 apples. so we build an equation to handle the transaction.

?View Code ACTIONSCRIPT
var totalCost:Number;
totalCost = 0.65 * 5; //3.25

Ok, so we went conservitive, using "totalCost" for the total of apples purchased. Now what do we do when someone wants to buy 4 apples, or 6, or 8? Now we should add a new variable to represent the amount of apples. This variables declaration is an "int" (integer) as we will not be selling fractions of apples.

?View Code ACTIONSCRIPT
var numApples:int = 5;
var totalCost:Number;
totalCost = 0.65 * numApples; // 3.25

Everyone is happy until next week when there is an apple shortage and the price increases to 85¢ a piece. Now you have to go through you app and change all the prices from 65¢ to 85¢. If we use variables we can easily modify the app when the price changes, better yet, now this same app could be used to handle bananas, grapefruit and pears which all have different prices.

?View Code ACTIONSCRIPT
var cost:Number = 0.85;
var numFruit = 5;
var totalCost:Numer;
totalCost = cost * numFruit; // $4.25

Array:
Array is one of the most powerful classes in Flash. It's power comes from the way an array holds a collection of information. Not only do we have access to the information, but we can loop through all the items in an array and monitor the length of the collection.

This is how we might set up some variables without arrays. If we add or take away an item, we have to update a separate variable to keep track of the total amount. Looping through this is information is possible, but tricky.

?View Code ACTIONSCRIPT
var fuit1:String = "apple";
var fruit2:String = "banana";
var fruit3:String = "pear";
var fruits:int = 3;
 
// Or we can do the same thing with an array.
 
var fruitArr:Array = ["apple","banana","pear"];
 
trace(fruitArr[0]); //"apple
trace(fruitArr.length); //3

One thing that you must remember when using arrays is that they are zero indexed, meaning the first position in the array is 0. This can cause a little confusion because we teach our children to start counting at 1, not 0. This will hopefully make more sense later or maybe more confusion, but at least you will know why you are confused.

Tip: instead of useing var fruitArr:Array = new Array(); which you may have seen before. Using the square braces will do same thing. var fruitArr:Array = [];

If we think of our application as if it were an engine, the data objects (arrays, XML) are the fuel. The part of the application that interates like loops, enter frame events and timers are the heart of the engine, like the pistons, cams and crank shaft. This engine starts once the app loads and runs until we stop everything or close the app.

for() Loop:
Interates or repeats a a specified amount allowing our engine to apply the same code to multiple objects. Loops will run and complete in between each frame, before each render. This means you will not visually see what the loop is doing until it completes and the stage renders.

?View Code ACTIONSCRIPT
// This is a loop using the array from above:
for(var p:String in fruitArr){
trace(fruitArr[p] + " | index = " + p);
}
 
output:
apple | index = 0
banana | index = 1
pear | index = 2

First we assign a variable to the item that is going to loop trough the array. p stands for property and is a string. Here you can see the output of "p" which is showing the index or location of each item in the array. Notice that "apple" is the first item, which has an index of 0. If we get the length of the array (fruitArr.length) it will return a 3 which is 1 more then the last index in the array (2). Length counts like we do, starting at #1, index counts like computers do, starting at 0.

Tip: The p variable outputs a number in this case. This number is not really a number, it is a string using number characters. If we tried to add these "numbers" up, we would get "012" instead of the sum of 3. This is one reason declaring variable types are important. The compiler will tell us immediately if we are passing a string into an equation where a number or integer should be. Many external data sources will pass numbers into Flash as strings. Declaring variable types adds integrity to our applications.

Function:
A function is like a little wrapper or snippet of code that we can call at a later time. They are like the transmission, servos, clutch and any other metaphorical mechanism that takes energy and makes stuff happen.

Functions can run with or without feedback, adding a few arguments they can become very flexible. Let's use our fruit price calculator equation as a sample. This function receives two arguments (quantity and price), does the calculation, then returns the price. Nothing happens when the script loads, only when the function is called, see below.

?View Code ACTIONSCRIPT
function chaChing(quantity:int, price:Number):Number{
var calc:Number = price * quantity;
return calc;
}
var totalCost:Number = chaChing(5, 0.85);
trace(totalCost); //$4.25
 
// Notice the declaration :Number after the close parenthases
// on the function name.
function chaChing():Number{
}
 
// This lets the compiler know that the function is returning
// a value when it is called. If we do not need to return a value
// when the funciton is called, we would use void.
 
function chaChing():void{
}

This is a really simple one line function, but even this is a valid use. If you ever use the same equation or sequence more then once in your application, wrap it in a function.

Tip: A variables declared inside of a function will not be accessable outside of that function, but variables decaleared outside of the function are visible to it.

Tip: The words method and function are interchangeable.

Tip: Most "Real" programmers will put the opening curly brace one the next line under the function name.

if / else Condition:
Basically a switch, if a cindition is met, do one thing, if not then do something different.

Event:
These enable our controls and is the triggering system for our functions. Events monitors the engine and user input, they can be considered part of the engines electrical system.

Finally the Application:
The simple application we are going to build is an image loader. We will build a custom button, the code will place a button on the stage for each image. We will then hook up these controls to dynamically load in each image.

The beginning of our app is the config area, this is where we set up all of our variables and any constants.

?View Code ACTIONSCRIPT
/*
* first is the array, this is a list of image urls.
* We are going to loop through this array to create the correct amount of buttons.
* When the buttons are pressed, we will use the array to pull to corresponding image url.
*/
var imageArr:Array = ["images/apple.jpg","images/banana.jpg","images/pear.jpg"];
 
 
/****************************************************
* variables
****************************************************/
// buffHeight: will be use this to calulate the y possition of each button.
// 22 is the y coordinate to start the first button.
var buffHeight:int = 22;
 
// loadX and loadY: This will place our image in the correct spot on the stage.
var loadX:int = 156;
var loady:int = 22;
 
/****************************************************
* the loop:
* Iterates through the array, adds a button for each item, adds event listeners,
* updates the buffHeight variable then stops when it reaches the end of the array.
*****************************************************/
 
// There are a few different types of loops, this one is based on the items of an array.
// The first part of the loop conditions is declaring a variable to represent the index
// as the loop iterates through the array.
 
for(var p:String in imageArr){
 
// create new ImageButton
var imgBtn:ImageButton = new ImageButton();
 
// add a button label
imgBtn.labelText.text = "Image " + p;
 
// give the button a id from "p" which references the index
// of the current item in the array.
imgBtn.id = int(p);
 
// set the y property using the buffHeight variable.
imgBtn.y = buffHeight;
imgBtn.x = 20;
 
// add the eventListener to capture the button clicks
imgBtn.addEventListener(MouseEvent.CLICK,clickHandler);
 
//add the button to the stage.
addChild(imgBtn);
 
//update the variable with the height of this button, so the next button's y position will be below it.
buffHeight += imgBtn.height + 5;
}
 
/****************************************************
* function clickHandler(MouseEvent)
* handler for the Click MouseEvent assigned to each button in the loop.
****************************************************/
function clickHandler(ev:MouseEvent):void{
 
// the event's target property tells which button fired the event, now we can get the correct id.
var id:int = ev.currentTarget.id;
 
//use the id and the imageArr to get the correct image url.
var url:String = imageArr[id];
 
//call the loadImage function with the url as an argument.
loadImage(url);
}
 
/****************************************************
* function loadImage(url:String)
* function for loading the images
****************************************************/
function loadImage(url:String):void{
 
// new variable of new loader object
var ldr:Loader = new Loader();
 
// new URLRequest using the url we passed in as an argument.
// this converts the string into a url request we can pass to the loader to load the image.
var req:URLRequest = new URLRequest(url);
 
//loading the image
ldr.load(req);
 
ldr.x = loadX;
ldr.y = loady;
 
// add loader to MovieClip referenced by loadTarget.
addChild(ldr);
}
 
stop();

Button code and instructions:
Make a new MovieClip. Inside this new MovieClip create some artwork to be used as the button background. Add a textField and variable declaration for id (we will pass in the id during the loop). Then check the Export to ActionScript option in the MovieClips *properties window.

*To get to the MovieClips property window, right-click on the MovieClip in the Library, then choose properties. You may need to click the advanced button to see all the options.

We are using a MovieClip instead of a button, so that we can pass in an id and control the text. So we are going to build a MovieClip to act as a button.

Source Here

Where to go from here:
1. Play with the application variables and the array. Expand the app by giving each button a better name. Maybe build the array using names in stead of urls, then you can create the new url string using "images/" + name + ".jpg". You could also create a name array in the same sequence or use slice on the url to pull the name out.

2. Expand the buttons, if you really want to get fancy, create an on-state for each button, so that you can tell which image is currently displayed.

3. Add the calculator code to display how much each item cost when you click a button and a loader.

Tip: The ldr function above places one item on top of another, this may cause an issue if you want to show something behind each image while it is loading.

Take the existing code and come up with another uses for it. If you come up with some cool ideas, post some links below. Also if you figure out any of the previous enhancement, post some code.

To put your code in a code block, you can wrap it in these tags. Take out the "[" and "]" ,square brackets.
[<]pre lang="actionscript"[>]
// all code goes here.
[<]/pre[>]

Construction

Wether I am illustrating an imaginary device or something I use everyday, mind it is good to understand how the object is or should be constructed. Other information like functionality, page and how these objects are interacted with are very important in making our illustrations more convincing.

Questions you could ask yourself are how much heft and mass does this object possess, What kids of materials are used to build this object? How does this information effect how light reflects/refracts off the object. These evaluations help us understand how the details should be rendered.

The object could be steel, but is it built assembled with welds, bolts or both? The object could be made from concrete, Styrofoam, wood, glass or plastic molds. Each material is assembled differently with different types of joints. The time when an object is built also will give us a clue as to the type of assembly would have been used. We should carry that information or hints of that information into our illustration.

We do not have to have an engineering degree to know that some buildings are made from glass and steal, brick/concrete block, or wood. A glass building would be smooth and shiny on the outside with little definition where each glass plate comes together. Brick buildings have thick walls so windows are inset into the wall. Wood buildings have window frames that are used to hold the window into the wall.

These are the types of things that should be going through our heads as we sketch, construct, color, and touch up our work. In the meantime we are building our forms in Illustrator, here are some techniques to speed up our work as we construct our illustrations with the provided tools.

Using divide and Unite:
Divide and Unite are two pathfinder tools I use the most. You should set these to actions with keyboard shortcuts.

Divide Tip 1:
Create a shadow, reflection, glare on a larger shape. One of the rules for quick illustration in Illustrator is to never draw the same line twice. Another rule is divide does not have to be destructive. If you have ever used Divide before on a shape and zoomed out, sometimes you will notice a little background seeping through where the Divide incision are applied.

Draw the path how you would like your incision, over lapping on both ends and making sure the path has no fill. Select the larger shape first, Copy and Paste in Front (Command + F / Cntr + F) then select the line you created for your incision. Apply the Divide to the shape and delete the unwanted piece.

This creates a smaller shape on top of the original shape, in seconds, with no gaps and non-destructive. If we do not like the way it looks, we can always delete it and start over with our original shape still intact.

Divide Tip 2:
Again Divide does not have to be destructive. If you have a few overlapping paths, Divide with create a joined shape and trim off the excess paths. This can come in handy when using a grid, copy the lines we want to use from the grid, and apply a Divide. You will now have a new shape that matches your guides without having to draw anything. We drew the lines once for the guide, we should not have to draw them a gain.

Divide Tip 3:
Overlap your paths with working with divide. It is much easier to make sure your division are complete if you see your incision paths are overlapping your original shape.

Unite Tip 1:
Sometimes Divide can have some unwelcome results, but they can be cleaned up quickly with Unite.

Unite Tip 2:
Unite goes hand with Outline Stroke. If you have a fill and a stroke, using Outline Stroke then Unite will convert a path into a new solid shape. I like to use this for making nice outlines or inking effects. Depending on your Illustrator Preference settings, paths will scale on one machine and not another. It is also a good idea to Outline & Unite paths if the size relationship is important.

Below is a simple funny faced frog made almost intierly with the oval tool and Outlined paths.

For a better explanation of these tips, watch Illustrating in Illustrator, the Happy Frog video tutorial.

Flash tip: Paths have never translated well to Flash, so try Outline & Unite before importing to Flash.

Offset Stroke:
Found in the Object:Path menu, is similar to Outline Stroke. In CS3 and before the new path is automatically grouped to the original path. So if you have a few paths being made from the Outline Stroke command, you will have to select all the pieces and Cut & Paste them out of the group to work with them easier. I still use it very often, mostly on simpler shapes.

In Illustrator CS4 Outline Stroke works much better and mimics the functionality mentioned in Unite Tip 2.

Duplicate and Transform:
There are many times while we are illustrating that we come across many objects that are similar like windows, bolts, or even spider eyes. By completing on object, then copying and distributing those copies around will make creating all these objects less redundant. Even if shapes, size, perspective differ, there may be parts that are reusable, or a quick transform can really help save time.

Drawing vs Editing:
We have discussed never drawing the same line twice and was to create new shapes from exiting ones. Also we went over duplicating shapes and objects to help speed things up. The rules in this series are just like most rules, there is very often an exception. If you are comfortable with the pen tool in Illustrator, it is almost always faster to draw a new line then it is to edit an existing one. If you are tweaking a couple points on an existing path, that is one thing, but if you copy an path with the intent on modifying many points, it is most likely faster to draw a whole new path. Or at least delete the points you would like to edit, and draw a new path in it's place.

Join and Average:
Even drawing paths holding down the shift key will not always get our lines straight. The keyboard shortcut for Average is Command + Option + J on a Mac and Control + Alt + J on PC. Any lines that are supposed to be straight that for some reason are not, is just a second away from be so, but you have to remember the keyboard short cut to really make it worth while.

Another Keyboard shortcut to remember is Join. Command + J on a Mac and Control + J on PC, will be used over and over again to clean up stray points. Divide, Outline Stroke and other wonderful tools we have covered so far are great time savers but can put unwanted points in our paths. One of our objectives it to create Clean artwork. Extra points and text Miter spikes will not do, so a quick select with the Hollow Arrow, or Hollow Lasso, then Join, will clean those points up quickly.

Group and Layer as you go:
As discussed in Part 1 of the series, grouping is important in speeding up our work. It is much easier to grab a bunch of paths that have been grouped with the solid arrow, then selecting many paths to do a tweak. Many time you will be working on something else in the illustration and you will notice something you want to tweak something that was done previously. As you finish objects with multiple paths they should be grouped.

Distributing artwork in layer is a great way to create a groups too. The results of good groups is easy selection and/or isolation of parts of the illustration. Using Lock and Hide as well as layers are great ways to isolate our work.

Next - Illustrating In Illustrator 101 Part 3 of 5: Defining Shapes

For a better explanation of these tips, watch Illustrating in Illustrator, the Happy Frog video tutorial.

When a Flash/Flex app loads into a browser, abortion all urls for the swf are now relative to the file that is hosting the swf and not the location of the swf file itself. This can create issues between testing the swf locally and viewing it on the live site.

Case Study:
When building a demo to display on this blog I have to create one version with relative urls to distribute as source and a separate sample for preview using absolute urls. This is because of the setup of the blog, more about some files like the index page display from the root of the blog while all the article files have unique urls based on title and date.

In the process of developing web applications your files can be moved from a local dev environment, to a staging environment and then to a final live server. It is efficient to keep all your swfs and external files together, packaged in their own directory. During migration, directory structures of the hosting files may change causing your relative urls to break and your absolute urls to point to the wrong domain.

Solution:
In AS3's LoaderObject class there is a url property which will display the url of root swf. This is nice to know because now I can place files relative to the swf file and one version will work offline, in the testing environment, one the final server and best of all my blog.

The same property is available in AS2, see below.

How to make your relative urls work based on the swf url:
The "url" property returns the url to the root swf file. This is too much information, but with a little trimming we can get exactly what we need.

AS3 Method:

?View Code ACTIONSCRIPT
var swfURL:String = this.loaderInfo.url;
swfURL = swfURL.substr(0, swfURL.lastIndexOf("/") + 1)
trace(swfURL);

AS2 Method:

?View Code ACTIONSCRIPT
var swfURL:String = this._url;
swfURL = swfURL.substr(0,swfURL.lastIndexOf("/") + 1);
trace(swfURL);

Now add the swfURL variable as a prefix to all your urls like so:
var imgUrl:String = swfURL + "images/image1.jpg";

Tip:
To get the hosting domain url you can use this (AS2 & AS3):

?View Code ACTIONSCRIPT
var tempDom:Array = swfURL.split("/");
var domURL:String = tempDom.slice(0,3).join("/") + "/";
trace(domURL);

Maintaining version control on project files can easily get out of control when saving multiple versions of the same file. One tip is covered in an earlier post about swf based relative urls for flash/flex files. This tip works even if the host file is moved to a different locations. This way we do not need to save a live version and a local build version.

Why would I care which Flash Player type is used?
Some projects, story like kiosks, approved will end up as a Flash Projector or AIR Application. Until the project is finalized and approved we may need to preview the project for our clients on the web. In AS3 some stage methods are only available to the standalone player. Instead of saving two versions of the same project, medicine one to test the Projector functionality and another for online approvals; we can build one multi-purpose file.

AS3 Method:

?View Code ACTIONSCRIPT
if(Capabilities.playerType == "StandAlone"){
stage.displayState = StageDisplayState.FULL_SCREEN;
 
// mouse hide and show for touchscreen kiosk: default (hide)
Mouse.hide();
}
trace(Capabilities.playerType); //StandAlone

AS2 Method:

?View Code ACTIONSCRIPT
trace(System.capabilities.playerType); //StandAlone

Here is a list of Flash Player type strings:
from Flash AS3 language reference
"ActiveX" for the Flash Player ActiveX control used by Microsoft Internet Explorer
"Desktop" for the Adobe AIR runtime (except for SWF content loaded by an HTML page, which has Capabilities.playerType set to "PlugIn" )
"External" for the external Flash Player or in test mode
"PlugIn" for the Flash Player browser plug-in (and for SWF content loaded by an HTML page in an AIR application)
"StandAlone" for the stand-alone Flash Player

If you need to know the player version number of the Flash Player use this code:
AS3:
trace(Capabilities.version); //MAC 10,0,2,54 or WIN 10,0,2,54

AS2:
trace(System.capabilities.version); //MAC 10,0,2,54 or WIN 10,0,2,54

tip 1: If your swf requires a newer Flash Player version, it is best to detect flash player versions using the Flash Version Detection option in the HTML publishing settings and require the user to download the newer player. SWFs published to newer Flash Player versions can be very unstable when running in older Players and can cause browser and system crashes.

tip 2:
Standalone and Desktop players are built into the executables so the Flash Player version will always be correct no matter what is currently installed on the system.

tip 3:
For a complete list of all the system capabilities you can learn about the system that is running your projects, look here.

Converting AS3 to Cocoa Touch:
The iPhone is another interest of mine because it is just so cool. I would love to build apps for the iphone but do not know when I would have time to learn cocoa touch. That is why I am very interested in Andy Jacobs' Blog and his tutorials on AS3 to Cocoa Touch. Now if I can just find the time, sildenafil these tutorials definitely make understanding cocoa conventions much easier for an AS programmer.

AS3 Reference iPhone Application:
So what is the next best thing to having Flash on the iPhone? How about an Action Script 3 reference documentation application for the iPhone? Not sure when I would use it. Perhaps when they port the Flex SDK to the iPhone, help otherwise I would rather use the online version with a huge monitor, full keyboard and mouse. I do not know why I still had to get the app, It is just one of those things that sound so good.
Adobe MAX 2008 kicks off with Shantanu Narayen, troche Adobe CEO.

I will do some live blogging from MAX. All post are being typed on my iPhone, due to my broken laptop, so do not expect a lot of details.

Over 5000 in attendence.

Followed by 2 more MAX conferences in europe and Asia.

Flash catalyst announced, previously Thurmo.

(Red) Wire announced, delivered on AIR. $5 a month.

Kevin Lynch on stage.

Cloud and client. Across multiple screens/devices.

Flash player 10 is awesome.
Audio waveform data, 3D, text engine, drawing API, pixel blender.
FAST realtime processing.

Max keynote is available online now. keynote

I cannot do it justice from my iPhone, pilule so check it out.

Updates:

Apparantly the keynote video does not live at the address I placed above, visit web that is what was on the big screen at the end of the keynote. sorry about that.
Here are a couple links of real live blogging (bet they had a laptop).
Liveblogging MAX 2008 Day 1 General Session Keynote

Adobe MAX 2008: Monday - Keynote

Tour de Flex on a 20' screen, shot by Greg Wilson. Tour de Flex on a 20 ft Screen
The first day of MAX has ended at 10:30 pm Monday night. East coast time is taking it's toll, sales but I know I am not the only one. I just finished moderating a video tips group that was full of drooping eyes.

Today was a success with 4 new t-shirts and a few new tips learned. All of the sessions are going to be available for free at Adobe TV. I have heard the Flash Catylist (thermo) sessions were really good, information pills the Flash Player Internals session had some nice insight on optimizing code, this my favorite one of the day. The Flex Tips session showed off some features of Flex Builder that I never new existed and now will not be able to live without.

MAX 2008 Sessions added to Adobe TV - 12/11/08

MAX 2008 on Adobe TV.

In a Birds-Of-A-Feather discussion group at Adobe MAX last week. No remarks were planned, search It was supposed to be a discussion, stuff we hoped to talk to other developers about what's new in using Flash video. We did not get a bunch of new information but we did get a lot of hard questions. Some of them were not fully answered and others were speculated upon. When I was asked my tips, I gave all I could think of at the time. Later that evening I remembered a couple more, some of my best ones.

So for those who went to MAX and those that did not, here are my official video tips for Flash and Flex.

Disclaimer: Technology changes on a regular basis, as of the date of this post I feel very comfortable with the statements made below. As new versions of software are released some of the comments may become outdated.

1. Your source file is king when it comes to getting good quality video. A good source file is the difference between hulu and youtube video. If you have control over your video source, make sure you get a good high-res lossless video file. They are huge and some clients do not know what you are talking about when you ask for it, but try your best to get a good source file.

2. Encode your own files. There are many flv encoders out there, some even your clients can use. But if you want good quality, then encode them yourselves. Of course some clients are pretty savvy when it comes to these things, in that case train them.

3. Use the Flash Video Encoder standalone application. *I have exported flv's from many other programs, but quality is more consistent with the Flash Video Encoder application. Plus the encoding speed is a lot better with the Flash Video Encoder. It does suck to encode something twice, once to a lossless file, then a second time to flv, but in my testing it has been worth it.
(*H.264 can be encoded from other applications with equal quality. I have not compared them yet, but it is a very standard codec.)

4. If you do not have Flash CS4, use on2 VP6 encoding, it is much better than the other codec options. H.264 is a great improvement even over on2 VP6. Mp4 files can use different codecs, so make sure you are using H.246 and mp3 audio if you are encoding with other applications.

5. Not all video files are the same. Video containing a lot of motion/action can not handle as much compression as a low motion, talking head video. You will have to test your video files and encode each file with different settings to get optimum performance, size and quality. Also if you have control over the editing of your source files, certain video transitions (cross dissolve) encode worse than others.

6. Do not change frame rate when encoding an flv. This will cause your a/v sync to drift. Any edits to frame rate needs to be made in your source file before you encode. This does not apply to video without sound.

7. Dropping FPS and lowering the Key Frame Interval can lower file size of the flv, but there are consequences. For lowering frame rate, see number 6. Lowering the frame rate interval will effect fast-forwarding and rewinding and may effect syncing between key frames. If you need smooth fast forward and rewind, then leave the key frame interval to automatic or raise it a little more. I believe it is set to 24 frames by default.

8. If you want to have good streaming performance, place your streaming files on a server setup for streaming content. There could be cross-domain security sandbox issues, if your files do not load, first check if you need a crossdomain.xml file.

9. Video has come along way from the timeline full of image sequences from pre Flash MX days. Video still has a large file size that can only be compressed so far. Video needs to buffer before playing and can consume a lot of CPU. If possible stop other animations, visual effects, and any processor intense code while your videos are playing.

10. There are still times when video is not the best solution. I still use image sequences if the job requires it, even though video can be the easier way to go in most cases. You may have to push your animation skills to pull off video type effects. Building your animation in Flash will give you more control over the size and quality of your project.

Using Random in Game Development, buy with strict guidelines, order can bring some variety to game play.

This sample is not a single solution but an approached I used in developing Whacky Voting - a politically smashing game. It uses random with some strict rules to get rid of sequences that some players can easily remember, yet keeping game play consistent from one game to the next.

This demo starts with a configuration section, used to set up how we want the game to act. The engine it self could be organized a little better to be more transportable. It is commented pretty well though, so it should be easy enough to understand the approach as well as practical usage. Random is used to shuffle all of the objects that appear on screen as well as what container the objects are associated with.

Configuration:
We use config data for each game so that we can easily tweak game-play without hacking our code later. We can use arrays, xml or other data sources. Plan ahead and build config options into your game as it is developed.

This array designates slots or containers to hold each appearing object. Use this to limit how many objects appear at a time and where they are placed on screen. this can represent MovieClips or other classes.

?View Code ACTIONSCRIPT
var objHolderArr:Array = [];
objHolderArr[0] = {obj:"object0",id:0,stat:false,timer:20,type:"",score:0,targ:null,xCoor:10};
objHolderArr[1] = {obj:"object1",id:1,stat:false,timer:20,type:"",score:0,targ:null,xCoor:90};
objHolderArr[2] = {obj:"object2",id:2,stat:false,timer:20,type:"",score:0,targ:null,xCoor:170};
objHolderArr[3] = {obj:"object3",id:3,stat:false,timer:20,type:"",score:0,targ:null,xCoor:250};
objHolderArr[4] = {obj:"object4",id:4,stat:false,timer:20,type:"",score:0,targ:null,xCoor:330};
objHolderArr[5] = {obj:"object5",id:5,stat:false,timer:20,type:"",score:0,targ:null,xCoor:410};

Next is an array of objects to appear, this is to control what type of objects appear and to make sure they are nicely distributed through out each level. You may have different scores, wilds and/or bonus score objects that need to get incorporated into the object list, but using random by it self will not allow them to be distributed appropriately for consistent game play.

?View Code ACTIONSCRIPT
var objSequenceArr:Array = [];
objSequenceArr[0] = {obj:"type0", count:20,score:100};
objSequenceArr[1] = {obj:"type1", count:15, score:150};
objSequenceArr[2] = {obj:"type2", count:5, score:500};
objSequenceArr[3] = {obj:"type3", count:5, score:1000};
objSequenceArr[4] = {obj:"null", count:5, score:0};
 
//timer increment for the engine to trigger an event
var timeInc:int = 500;
 
// integer to keep track of increment of game engine
var arrLoc:int = 0;
 
// random key
var randomKey:int = 1000;
 
// time for each object to stay visible;
var delay:int = 4;

It is good to set game status variables to allow games controls to be a little more intuitive. Sometimes I use a gameStatus string variable and a string to denote the current status. That way I can get more mileage out of one variable.

?View Code ACTIONSCRIPT
var gameOver:Boolean;
 
//or
 
var gameStatus:String = "_play";

Build Config Data for Engine:
The current level array built from config data above. The method then adds to the level array all the objects that we want to appear during the game.

?View Code ACTIONSCRIPT
var levelArr:Array = [];
 
function buildConfigData():void{
for(var p:String in objSequenceArr){
var loopCnt:int = objSequenceArr[p].count;
for(var i:uint = 0; i < loopCnt; i++){
var randNum:int = randomNumber(randomKey);
levelArr.push({obj:objSequenceArr[p].obj, score:objSequenceArr[p].score, key:randNum});
}
}
 
levelArr.sortOn("key",Array.NUMERIC || Array.DESCENDING);
}
buildConfigData();

Last, we sort the list so that it is shuffled which gives us the first random effect. All the objects are placed in the array in order of the sequence array, but we added a random number as the key to sort the array with. Now all of the objects will be randomly placed throughout the array and we will always have the right amount of objects for consistent game play.

Game Engine:
Now that we have our data, we are ready to start the engine.

1. Pull first random number

2. Loop until random number is not a slot that is already taken. We add a break and status variable to stop the loop if we can not find an available object. On a break, we will wait until the next TimerEvent and try again.

3. We have an active slot that is not already taken, we set it's status to true and show and configure our object.

4. Use this timer event to also run our Active Checker Method below. The more you can piggy-back off of single timers and EnterFrame events the better.

?View Code ACTIONSCRIPT
var timer:Timer = new Timer(timeInc,0);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
 
function timerHandler(ev:TimerEvent):void{
 
//1.
var randSlot:int = randomNumber(objHolderArr.length);
 
//2.
if(arrLoc < levelArr.length){
if(levelArr[arrLoc].obj != "null"){
var breakCnt:int
var breakStatus:Boolean;
while(objHolderArr[randSlot].stat == true){
randSlot = randomNumber(objHolderArr.length);
breakCnt ++;
if(breakCnt >= 100){
breakStatus = true;
break;
}
}
 
if(!breakStatus){
//3.
var slotObj:Object = objHolderArr[randSlot];
slotObj.stat = true;
slotObj.timer = delay;
slotObj.score = levelArr[arrLoc].score;
slotObj.type = levelArr[arrLoc].type;
 
//******* add code here to initiate your visual objects.
var tempBO:ballObj = new ballObj();
tempBO.x = slotObj.xCoor;
tempBO.y = 20;
tempBO.objIDStr = arrLoc.toString();
tempBO.objScoreStr = levelArr[arrLoc].score;
tempBO.objTypeStr = levelArr[arrLoc].obj;
addChild(tempBO);
 
//********* end visual code here.
 
slotObj.targ = tempBO;
activeObjArr.push(slotObj);
// we advance the array location variable.
arrLoc ++;
}
}
else{
arrLoc ++;
}
}
 
//4.
activeChecker();
}

After each object is initiated, we need to give them an amount of time to be active. This is the activeObject array, we will track the time, if the user does not score with the object then it will be removed by the timer.

1. Loop through the active array to decrease each object's timer.

2. If the timer is run out, remove the object from the array and reset the object's status.

?View Code ACTIONSCRIPT
var activeObjArr:Array = [];
 
function activeChecker():void{
for(var p:String in activeObjArr){
//1.
activeObjArr[p].timer --;
 
//2.
if(activeObjArr[p].timer <= 0){
activeObjArr[p].stat = false;
removeChild(activeObjArr[p].targ);
activeObjArr.splice(int(p),1);
 
if(arrLoc >= levelArr.length && activeObjArr.length == 0){
//game is over.
gameOver = true;
timer.stop();
btn.enabled = true;
btn.alpha = 1;
}
}
}
}

Here is where you can place your event handlers for a user interactive with an object. We have to remove and reset the object, shown above and add the objects score to the main score.

We will also need a method for when the game clears the last array object.

Utilities:
method to pull random numbers just so I do not need to write this same code more than once.

?View Code ACTIONSCRIPT
function randomNumber(limit:int):int{
var randNum:int = Math.random()*limit;
return randNum;
}

Controls:
A restart control availble when game is over

?View Code ACTIONSCRIPT
btn.addEventListener(MouseEvent.CLICK,clickHandler);
btn.enabled = false;
btn.alpha = 0.2;
function clickHandler(ev:MouseEvent):void{
if(gameOver){
// rebuild data to show off shuffling.
levelArr = [];
buildConfigData();
 
//reset game controls and game engine.
arrLoc = 0;
timer.start();
gameOver = false;
btn.enabled = false;
btn.alpha = 0.2;
}
}

The Ball Object:
The ball object is a simple class that displays the data for each object. You would normally place a button or some other way to capture user interaction and send it back to the engine to initiate scores and feedback.

?View Code ACTIONSCRIPT
package{
import flash.display.MovieClip;
import flash.text.TextField;
import flash.events.Event;
 
public class ballObj extends MovieClip{
 
public var objIDStr:String = "";
public var objTypeStr:String = "";
public var objScoreStr:String = "";
 
public function ballObj():void{
init();
stop();
}
 
private function init():void{
this.addEventListener(Event.ADDED,addedHandler);
}
 
private function addedHandler(ev:Event):void{
objID.text = objIDStr;
objScore.text = objScoreStr;
objType.text = objTypeStr;
 
}
}
}

Source Here
This is it, about it the very first bit of actionscript code I ever learned, site besides play() and gotoAndStop() of course. The lesson went down with an experienced programmer looking over my shoulder telling me what to type. After this little app was finished, approved my brain hurt only understanding a few of the lines we wrote. That code was referenced and/or modified on more then a few projects that came after, each time deciphering more and applying it to new functionalities.

The original script was back in the day of AS1, but I am going to present it to you in AS3. If you are a beginner to ActionScript then it is the perfect time to learn AS3.

We are going to start really remedial for a minute and go over the basics of the classes and objects we will be using. It is kind-of long, so if you already have the basics covered, you can skip to the Application code.

The Variable:
Remember Pre-Algebra? 2+x = y? Variables are used for more then just place holders in a math equation. Programming is a very literal language, variables are how we make it figurative. Now instead of addressing one object with a snippet of code, that code can be applied to the many objects and properties our variables represent.

To use a variable, we must declare it using these three letters "var". Then comes the creative part, we get to think of a name. This can be a lot of fun making up funny names for things until someone else has to figure out your code or you forget that you called the variable that is going to bring balance to your application "anakin", oops, or was that "luke"?

After naming the variable, we have to declare it's type. We really don't have to, but it is a good idea. This variable will be a Number, because we will need it to include decimals.

Here are some examples of how variables can be used. Think about if we were selling apples that costs 65¢ a peace. A person wants to buy 5 apples. so we build an equation to handle the transaction.

?View Code ACTIONSCRIPT
var totalCost:Number;
totalCost = 0.65 * 5; //3.25

Ok, so we went conservitive, using "totalCost" for the total of apples purchased. Now what do we do when someone wants to buy 4 apples, or 6, or 8? Now we should add a new variable to represent the amount of apples. This variables declaration is an "int" (integer) as we will not be selling fractions of apples.

?View Code ACTIONSCRIPT
var numApples:int = 5;
var totalCost:Number;
totalCost = 0.65 * numApples; // 3.25

Everyone is happy until next week when there is an apple shortage and the price increases to 85¢ a piece. Now you have to go through you app and change all the prices from 65¢ to 85¢. If we use variables we can easily modify the app when the price changes, better yet, now this same app could be used to handle bananas, grapefruit and pears which all have different prices.

?View Code ACTIONSCRIPT
var cost:Number = 0.85;
var numFruit = 5;
var totalCost:Numer;
totalCost = cost * numFruit; // $4.25

Array:
Array is one of the most powerful classes in Flash. It's power comes from the way an array holds a collection of information. Not only do we have access to the information, but we can loop through all the items in an array and monitor the length of the collection.

This is how we might set up some variables without arrays. If we add or take away an item, we have to update a separate variable to keep track of the total amount. Looping through this is information is possible, but tricky.

?View Code ACTIONSCRIPT
var fuit1:String = "apple";
var fruit2:String = "banana";
var fruit3:String = "pear";
var fruits:int = 3;
 
// Or we can do the same thing with an array.
 
var fruitArr:Array = ["apple","banana","pear"];
 
trace(fruitArr[0]); //"apple
trace(fruitArr.length); //3

One thing that you must remember when using arrays is that they are zero indexed, meaning the first position in the array is 0. This can cause a little confusion because we teach our children to start counting at 1, not 0. This will hopefully make more sense later or maybe more confusion, but at least you will know why you are confused.

Tip: instead of useing var fruitArr:Array = new Array(); which you may have seen before. Using the square braces will do same thing. var fruitArr:Array = [];

If we think of our application as if it were an engine, the data objects (arrays, XML) are the fuel. The part of the application that interates like loops, enter frame events and timers are the heart of the engine, like the pistons, cams and crank shaft. This engine starts once the app loads and runs until we stop everything or close the app.

for() Loop:
Interates or repeats a a specified amount allowing our engine to apply the same code to multiple objects. Loops will run and complete in between each frame, before each render. This means you will not visually see what the loop is doing until it completes and the stage renders.

?View Code ACTIONSCRIPT
// This is a loop using the array from above:
for(var p:String in fruitArr){
trace(fruitArr[p] + " | index = " + p);
}
 
output:
apple | index = 0
banana | index = 1
pear | index = 2

First we assign a variable to the item that is going to loop trough the array. p stands for property and is a string. Here you can see the output of "p" which is showing the index or location of each item in the array. Notice that "apple" is the first item, which has an index of 0. If we get the length of the array (fruitArr.length) it will return a 3 which is 1 more then the last index in the array (2). Length counts like we do, starting at #1, index counts like computers do, starting at 0.

Tip: The p variable outputs a number in this case. This number is not really a number, it is a string using number characters. If we tried to add these "numbers" up, we would get "012" instead of the sum of 3. This is one reason declaring variable types are important. The compiler will tell us immediately if we are passing a string into an equation where a number or integer should be. Many external data sources will pass numbers into Flash as strings. Declaring variable types adds integrity to our applications.

Function:
A function is like a little wrapper or snippet of code that we can call at a later time. They are like the transmission, servos, clutch and any other metaphorical mechanism that takes energy and makes stuff happen.

Functions can run with or without feedback, adding a few arguments they can become very flexible. Let's use our fruit price calculator equation as a sample. This function receives two arguments (quantity and price), does the calculation, then returns the price. Nothing happens when the script loads, only when the function is called, see below.

?View Code ACTIONSCRIPT
function chaChing(quantity:int, price:Number):Number{
var calc:Number = price * quantity;
return calc;
}
var totalCost:Number = chaChing(5, 0.85);
trace(totalCost); //$4.25
 
// Notice the declaration :Number after the close parenthases
// on the function name.
function chaChing():Number{
}
 
// This lets the compiler know that the function is returning
// a value when it is called. If we do not need to return a value
// when the funciton is called, we would use void.
 
function chaChing():void{
}

This is a really simple one line function, but even this is a valid use. If you ever use the same equation or sequence more then once in your application, wrap it in a function.

Tip: A variables declared inside of a function will not be accessable outside of that function, but variables decaleared outside of the function are visible to it.

Tip: The words method and function are interchangeable.

Tip: Most "Real" programmers will put the opening curly brace one the next line under the function name.

if / else Condition:
Basically a switch, if a cindition is met, do one thing, if not then do something different.

Event:
These enable our controls and is the triggering system for our functions. Events monitors the engine and user input, they can be considered part of the engines electrical system.

Finally the Application:
The simple application we are going to build is an image loader. We will build a custom button, the code will place a button on the stage for each image. We will then hook up these controls to dynamically load in each image.

The beginning of our app is the config area, this is where we set up all of our variables and any constants.

?View Code ACTIONSCRIPT
/*
* first is the array, this is a list of image urls.
* We are going to loop through this array to create the correct amount of buttons.
* When the buttons are pressed, we will use the array to pull to corresponding image url.
*/
var imageArr:Array = ["images/apple.jpg","images/banana.jpg","images/pear.jpg"];
 
 
/****************************************************
* variables
****************************************************/
// buffHeight: will be use this to calulate the y possition of each button.
// 22 is the y coordinate to start the first button.
var buffHeight:int = 22;
 
// loadX and loadY: This will place our image in the correct spot on the stage.
var loadX:int = 156;
var loady:int = 22;
 
/****************************************************
* the loop:
* Iterates through the array, adds a button for each item, adds event listeners,
* updates the buffHeight variable then stops when it reaches the end of the array.
*****************************************************/
 
// There are a few different types of loops, this one is based on the items of an array.
// The first part of the loop conditions is declaring a variable to represent the index
// as the loop iterates through the array.
 
for(var p:String in imageArr){
 
// create new ImageButton
var imgBtn:ImageButton = new ImageButton();
 
// add a button label
imgBtn.labelText.text = "Image " + p;
 
// give the button a id from "p" which references the index
// of the current item in the array.
imgBtn.id = int(p);
 
// set the y property using the buffHeight variable.
imgBtn.y = buffHeight;
imgBtn.x = 20;
 
// add the eventListener to capture the button clicks
imgBtn.addEventListener(MouseEvent.CLICK,clickHandler);
 
//add the button to the stage.
addChild(imgBtn);
 
//update the variable with the height of this button, so the next button's y position will be below it.
buffHeight += imgBtn.height + 5;
}
 
/****************************************************
* function clickHandler(MouseEvent)
* handler for the Click MouseEvent assigned to each button in the loop.
****************************************************/
function clickHandler(ev:MouseEvent):void{
 
// the event's target property tells which button fired the event, now we can get the correct id.
var id:int = ev.currentTarget.id;
 
//use the id and the imageArr to get the correct image url.
var url:String = imageArr[id];
 
//call the loadImage function with the url as an argument.
loadImage(url);
}
 
/****************************************************
* function loadImage(url:String)
* function for loading the images
****************************************************/
function loadImage(url:String):void{
 
// new variable of new loader object
var ldr:Loader = new Loader();
 
// new URLRequest using the url we passed in as an argument.
// this converts the string into a url request we can pass to the loader to load the image.
var req:URLRequest = new URLRequest(url);
 
//loading the image
ldr.load(req);
 
ldr.x = loadX;
ldr.y = loady;
 
// add loader to MovieClip referenced by loadTarget.
addChild(ldr);
}
 
stop();

Button code and instructions:
Make a new MovieClip. Inside this new MovieClip create some artwork to be used as the button background. Add a textField and variable declaration for id (we will pass in the id during the loop). Then check the Export to ActionScript option in the MovieClips *properties window.

*To get to the MovieClips property window, right-click on the MovieClip in the Library, then choose properties. You may need to click the advanced button to see all the options.

We are using a MovieClip instead of a button, so that we can pass in an id and control the text. So we are going to build a MovieClip to act as a button.

Source Here

Where to go from here:
1. Play with the application variables and the array. Expand the app by giving each button a better name. Maybe build the array using names in stead of urls, then you can create the new url string using "images/" + name + ".jpg". You could also create a name array in the same sequence or use slice on the url to pull the name out.

2. Expand the buttons, if you really want to get fancy, create an on-state for each button, so that you can tell which image is currently displayed.

3. Add the calculator code to display how much each item cost when you click a button and a loader.

Tip: The ldr function above places one item on top of another, this may cause an issue if you want to show something behind each image while it is loading.

Take the existing code and come up with another uses for it. If you come up with some cool ideas, post some links below. Also if you figure out any of the previous enhancement, post some code.

To put your code in a code block, you can wrap it in these tags. Take out the "[" and "]" ,square brackets.
[<]pre lang="actionscript"[>]
// all code goes here.
[<]/pre[>]

Construction

Wether I am illustrating an imaginary device or something I use everyday, mind it is good to understand how the object is or should be constructed. Other information like functionality, page and how these objects are interacted with are very important in making our illustrations more convincing.

Questions you could ask yourself are how much heft and mass does this object possess, What kids of materials are used to build this object? How does this information effect how light reflects/refracts off the object. These evaluations help us understand how the details should be rendered.

The object could be steel, but is it built assembled with welds, bolts or both? The object could be made from concrete, Styrofoam, wood, glass or plastic molds. Each material is assembled differently with different types of joints. The time when an object is built also will give us a clue as to the type of assembly would have been used. We should carry that information or hints of that information into our illustration.

We do not have to have an engineering degree to know that some buildings are made from glass and steal, brick/concrete block, or wood. A glass building would be smooth and shiny on the outside with little definition where each glass plate comes together. Brick buildings have thick walls so windows are inset into the wall. Wood buildings have window frames that are used to hold the window into the wall.

These are the types of things that should be going through our heads as we sketch, construct, color, and touch up our work. In the meantime we are building our forms in Illustrator, here are some techniques to speed up our work as we construct our illustrations with the provided tools.

Using divide and Unite:
Divide and Unite are two pathfinder tools I use the most. You should set these to actions with keyboard shortcuts.

Divide Tip 1:
Create a shadow, reflection, glare on a larger shape. One of the rules for quick illustration in Illustrator is to never draw the same line twice. Another rule is divide does not have to be destructive. If you have ever used Divide before on a shape and zoomed out, sometimes you will notice a little background seeping through where the Divide incision are applied.

Draw the path how you would like your incision, over lapping on both ends and making sure the path has no fill. Select the larger shape first, Copy and Paste in Front (Command + F / Cntr + F) then select the line you created for your incision. Apply the Divide to the shape and delete the unwanted piece.

This creates a smaller shape on top of the original shape, in seconds, with no gaps and non-destructive. If we do not like the way it looks, we can always delete it and start over with our original shape still intact.

Divide Tip 2:
Again Divide does not have to be destructive. If you have a few overlapping paths, Divide with create a joined shape and trim off the excess paths. This can come in handy when using a grid, copy the lines we want to use from the grid, and apply a Divide. You will now have a new shape that matches your guides without having to draw anything. We drew the lines once for the guide, we should not have to draw them a gain.

Divide Tip 3:
Overlap your paths with working with divide. It is much easier to make sure your division are complete if you see your incision paths are overlapping your original shape.

Unite Tip 1:
Sometimes Divide can have some unwelcome results, but they can be cleaned up quickly with Unite.

Unite Tip 2:
Unite goes hand with Outline Stroke. If you have a fill and a stroke, using Outline Stroke then Unite will convert a path into a new solid shape. I like to use this for making nice outlines or inking effects. Depending on your Illustrator Preference settings, paths will scale on one machine and not another. It is also a good idea to Outline & Unite paths if the size relationship is important.

Below is a simple funny faced frog made almost intierly with the oval tool and Outlined paths.

For a better explanation of these tips, watch Illustrating in Illustrator, the Happy Frog video tutorial.

Flash tip: Paths have never translated well to Flash, so try Outline & Unite before importing to Flash.

Offset Stroke:
Found in the Object:Path menu, is similar to Outline Stroke. In CS3 and before the new path is automatically grouped to the original path. So if you have a few paths being made from the Outline Stroke command, you will have to select all the pieces and Cut & Paste them out of the group to work with them easier. I still use it very often, mostly on simpler shapes.

In Illustrator CS4 Outline Stroke works much better and mimics the functionality mentioned in Unite Tip 2.

Duplicate and Transform:
There are many times while we are illustrating that we come across many objects that are similar like windows, bolts, or even spider eyes. By completing on object, then copying and distributing those copies around will make creating all these objects less redundant. Even if shapes, size, perspective differ, there may be parts that are reusable, or a quick transform can really help save time.

Drawing vs Editing:
We have discussed never drawing the same line twice and was to create new shapes from exiting ones. Also we went over duplicating shapes and objects to help speed things up. The rules in this series are just like most rules, there is very often an exception. If you are comfortable with the pen tool in Illustrator, it is almost always faster to draw a new line then it is to edit an existing one. If you are tweaking a couple points on an existing path, that is one thing, but if you copy an path with the intent on modifying many points, it is most likely faster to draw a whole new path. Or at least delete the points you would like to edit, and draw a new path in it's place.

Join and Average:
Even drawing paths holding down the shift key will not always get our lines straight. The keyboard shortcut for Average is Command + Option + J on a Mac and Control + Alt + J on PC. Any lines that are supposed to be straight that for some reason are not, is just a second away from be so, but you have to remember the keyboard short cut to really make it worth while.

Another Keyboard shortcut to remember is Join. Command + J on a Mac and Control + J on PC, will be used over and over again to clean up stray points. Divide, Outline Stroke and other wonderful tools we have covered so far are great time savers but can put unwanted points in our paths. One of our objectives it to create Clean artwork. Extra points and text Miter spikes will not do, so a quick select with the Hollow Arrow, or Hollow Lasso, then Join, will clean those points up quickly.

Group and Layer as you go:
As discussed in Part 1 of the series, grouping is important in speeding up our work. It is much easier to grab a bunch of paths that have been grouped with the solid arrow, then selecting many paths to do a tweak. Many time you will be working on something else in the illustration and you will notice something you want to tweak something that was done previously. As you finish objects with multiple paths they should be grouped.

Distributing artwork in layer is a great way to create a groups too. The results of good groups is easy selection and/or isolation of parts of the illustration. Using Lock and Hide as well as layers are great ways to isolate our work.

Next - Illustrating In Illustrator 101 Part 3 of 5: Defining Shapes

For a better explanation of these tips, watch Illustrating in Illustrator, the Happy Frog video tutorial.

When a Flash/Flex app loads into a browser, abortion all urls for the swf are now relative to the file that is hosting the swf and not the location of the swf file itself. This can create issues between testing the swf locally and viewing it on the live site.

Case Study:
When building a demo to display on this blog I have to create one version with relative urls to distribute as source and a separate sample for preview using absolute urls. This is because of the setup of the blog, more about some files like the index page display from the root of the blog while all the article files have unique urls based on title and date.

In the process of developing web applications your files can be moved from a local dev environment, to a staging environment and then to a final live server. It is efficient to keep all your swfs and external files together, packaged in their own directory. During migration, directory structures of the hosting files may change causing your relative urls to break and your absolute urls to point to the wrong domain.

Solution:
In AS3's LoaderObject class there is a url property which will display the url of root swf. This is nice to know because now I can place files relative to the swf file and one version will work offline, in the testing environment, one the final server and best of all my blog.

The same property is available in AS2, see below.

How to make your relative urls work based on the swf url:
The "url" property returns the url to the root swf file. This is too much information, but with a little trimming we can get exactly what we need.

AS3 Method:

?View Code ACTIONSCRIPT
var swfURL:String = this.loaderInfo.url;
swfURL = swfURL.substr(0, swfURL.lastIndexOf("/") + 1)
trace(swfURL);

AS2 Method:

?View Code ACTIONSCRIPT
var swfURL:String = this._url;
swfURL = swfURL.substr(0,swfURL.lastIndexOf("/") + 1);
trace(swfURL);

Now add the swfURL variable as a prefix to all your urls like so:
var imgUrl:String = swfURL + "images/image1.jpg";

Tip:
To get the hosting domain url you can use this (AS2 & AS3):

?View Code ACTIONSCRIPT
var tempDom:Array = swfURL.split("/");
var domURL:String = tempDom.slice(0,3).join("/") + "/";
trace(domURL);

Maintaining version control on project files can easily get out of control when saving multiple versions of the same file. One tip is covered in an earlier post about swf based relative urls for flash/flex files. This tip works even if the host file is moved to a different locations. This way we do not need to save a live version and a local build version.

Why would I care which Flash Player type is used?
Some projects, story like kiosks, approved will end up as a Flash Projector or AIR Application. Until the project is finalized and approved we may need to preview the project for our clients on the web. In AS3 some stage methods are only available to the standalone player. Instead of saving two versions of the same project, medicine one to test the Projector functionality and another for online approvals; we can build one multi-purpose file.

AS3 Method:

?View Code ACTIONSCRIPT
if(Capabilities.playerType == "StandAlone"){
stage.displayState = StageDisplayState.FULL_SCREEN;
 
// mouse hide and show for touchscreen kiosk: default (hide)
Mouse.hide();
}
trace(Capabilities.playerType); //StandAlone

AS2 Method:

?View Code ACTIONSCRIPT
trace(System.capabilities.playerType); //StandAlone

Here is a list of Flash Player type strings:
from Flash AS3 language reference
"ActiveX" for the Flash Player ActiveX control used by Microsoft Internet Explorer
"Desktop" for the Adobe AIR runtime (except for SWF content loaded by an HTML page, which has Capabilities.playerType set to "PlugIn" )
"External" for the external Flash Player or in test mode
"PlugIn" for the Flash Player browser plug-in (and for SWF content loaded by an HTML page in an AIR application)
"StandAlone" for the stand-alone Flash Player

If you need to know the player version number of the Flash Player use this code:
AS3:
trace(Capabilities.version); //MAC 10,0,2,54 or WIN 10,0,2,54

AS2:
trace(System.capabilities.version); //MAC 10,0,2,54 or WIN 10,0,2,54

tip 1: If your swf requires a newer Flash Player version, it is best to detect flash player versions using the Flash Version Detection option in the HTML publishing settings and require the user to download the newer player. SWFs published to newer Flash Player versions can be very unstable when running in older Players and can cause browser and system crashes.

tip 2:
Standalone and Desktop players are built into the executables so the Flash Player version will always be correct no matter what is currently installed on the system.

tip 3:
For a complete list of all the system capabilities you can learn about the system that is running your projects, look here.

Converting AS3 to Cocoa Touch:
The iPhone is another interest of mine because it is just so cool. I would love to build apps for the iphone but do not know when I would have time to learn cocoa touch. That is why I am very interested in Andy Jacobs' Blog and his tutorials on AS3 to Cocoa Touch. Now if I can just find the time, sildenafil these tutorials definitely make understanding cocoa conventions much easier for an AS programmer.

AS3 Reference iPhone Application:
So what is the next best thing to having Flash on the iPhone? How about an Action Script 3 reference documentation application for the iPhone? Not sure when I would use it. Perhaps when they port the Flex SDK to the iPhone, help otherwise I would rather use the online version with a huge monitor, full keyboard and mouse. I do not know why I still had to get the app, It is just one of those things that sound so good.
Was anyone else thrown for a loop as much as I was about Flash CS4s animation system? I knew the basics and played around with the new animation tools before, buy but then I had my first real animation job with it. Wow! that really sucked.

It is hard to say if the new tools are better then before, ambulance that all depends on your needs. If you want to do a quick animation, diagnosis then stick with the classic tweens. If you want higher quality animation with some real fine tuning then the new tools are for you. I have to admit, if I had written this post just one day earlier, my option of the new animation tools would have been completely 180° opposite. Now I think they are great, so if you are frustrated now, read on and take a deep breath.

Forgetting How to Animate:
My first hurdle was to forget how I animated in the past. Instead of placing a keyframe on the timeline everywhere you want the x, y or z property to change in value, you keyframe the two extremes of your your animation. Everything in-between and easing is handled by custom tween curves.

In this demo we will do a bouncing ball, but this one will animate and bounce off all four sides of the stage. Previously we would place our ball on the stage where we want the ball to hit the sides, maybe add a motion guide for some nice arks to simulate gravity, then tweak the tweens between each keyframe until we have something that looks believable. Now a single tween last the entire length of our animation, so adding those extra keyframes on the timeline will mess up your tween.

Extremes:
We just start with two keyframes, one at each extreme of where we want the ball to travel.
Then with the ball selected, open the motion editor. Here we see our x and y curves, well they are just strait lines. If you apply a tween you will just get a change in the motion dynamics between the two keyframes. Instead scroll down to the Eases row, this is where all the real animation happens now. Click on the plus icon and select custom from the bottom of the list. Do this twice. I hate that we are not able to name our custom tweens, maybe next release, anyway, create one for the x axis and one for the y axis.

By default each curve starts at 0% on the left and goes to 100% on the right. On the right side of the curve, change the value to 0%. Now slide back up to the x and y tween drop downs and select the custom tween you wan to apply to each property. I chose "1-custom" for x and "2-custom" for y. Now slide back down and lets get to work.

If you test out the animation now, nothing will happen, not even the diagonal movement we had before.

Custom Curves:
On each custom curve place four keyframes. Now with the individual keyframes selected, slide the values of each tween until you get the desired placement of the ball on each axis. Now we can mess with the curves to effect the dynamics of how the ball bounces from one side to the next. We can even create nice arc effects to really pull off a convincing animation.

We only need to do this for the x, y and z properties. The other properties like scale, color and filters allow you to apply curves directly in their tween rows. The three "statual" properties do not allow any curves to be applied directly, all you can do is apply an existing tween from the tweens section of the Motion Editor. If you try to keyframe your x and y properties on the timeline and apply a tween, you will notice the tween is applied across all frames and you will not get the desired result. The movement will work, but the easing will not.

I finished off the animation with some blur and a shadow animation. I just copied the ball tween, added an advanced color setting, broadened the x and y extremes and tweaked the blur.

Tip:
Though you cannot save tween curves, (they do this in photoshop, so hopefully on next release) you can copy curves from one object's Motion Editor to another. Once you have an animation in the can, you can save it as a motion preset. This is really powerful, it even saves the blank keyframe I place at the end of my tweans for tidiness.

Other Pros to the Motion Editor:
You can stretch or condense the animation by dragging the last frame and all the keyframes adjust proportionally. You also can change instance properties like the instance type MovieClip to Graphic, instance name and loop properties once then it applies across the whole tween.

There may be a better way of doing this but if you want to continue an animation and start where the previous tween ended. It may be best to start a new tween instead of stretching things out and adjusting your tween curves inside the Motion Editor to make room. The best way I have figured out how to do this is to grab the tween on the timeline, hold down option (Mac) or alt (PC) as you drag it to an empty spot on the timeline, which will make a copy. Convert the tween to Frame by Frame Animation. Now you can remove all the frames but the last one which is right where the previous tween left off. It would be nice it this was available as a one step command too.

In the sample below, I keyframed the x and y extremes, though I wanted the animation to start a little to the right of extreme left. I understand the tweens start and 0 (extreme left) and end at 100 (extreme right), but these are not really just tweens anymore, are they? To make this work without making two animations, I set frame 1 to the desired x coordinate and the alpha on the previous frame to 0. I then copied the tween, using the method above, and pulled out the second frame to place over the first frame on the timeline.

The new tweening tools are very powerful and will help us produce better quality animations, I am glad they still have the option of a classic tween as I still use that from time to time for really simple stuff (it is just faster) along with shape tweens. I do not look at this as a replacement of the tools I am used to using, but a new really powerful option when animating. You do have to plan ahead a little and it will take a extra time setting up custom tween and tweaking things to look right. We had to do a lot of animation slight-of-hand tricks to get things to look right before, so you have to admit this is cool. Just remember with great power comes great responsibility (Ben Parker).

Download Source
Adobe MAX 2008 kicks off with Shantanu Narayen, troche Adobe CEO.

I will do some live blogging from MAX. All post are being typed on my iPhone, due to my broken laptop, so do not expect a lot of details.

Over 5000 in attendence.

Followed by 2 more MAX conferences in europe and Asia.

Flash catalyst announced, previously Thurmo.

(Red) Wire announced, delivered on AIR. $5 a month.

Kevin Lynch on stage.

Cloud and client. Across multiple screens/devices.

Flash player 10 is awesome.
Audio waveform data, 3D, text engine, drawing API, pixel blender.
FAST realtime processing.

Max keynote is available online now. keynote

I cannot do it justice from my iPhone, pilule so check it out.

Updates:

Apparantly the keynote video does not live at the address I placed above, visit web that is what was on the big screen at the end of the keynote. sorry about that.
Here are a couple links of real live blogging (bet they had a laptop).
Liveblogging MAX 2008 Day 1 General Session Keynote

Adobe MAX 2008: Monday - Keynote

Tour de Flex on a 20' screen, shot by Greg Wilson. Tour de Flex on a 20 ft Screen
The first day of MAX has ended at 10:30 pm Monday night. East coast time is taking it's toll, sales but I know I am not the only one. I just finished moderating a video tips group that was full of drooping eyes.

Today was a success with 4 new t-shirts and a few new tips learned. All of the sessions are going to be available for free at Adobe TV. I have heard the Flash Catylist (thermo) sessions were really good, information pills the Flash Player Internals session had some nice insight on optimizing code, this my favorite one of the day. The Flex Tips session showed off some features of Flex Builder that I never new existed and now will not be able to live without.

MAX 2008 Sessions added to Adobe TV - 12/11/08

MAX 2008 on Adobe TV.

In a Birds-Of-A-Feather discussion group at Adobe MAX last week. No remarks were planned, search It was supposed to be a discussion, stuff we hoped to talk to other developers about what's new in using Flash video. We did not get a bunch of new information but we did get a lot of hard questions. Some of them were not fully answered and others were speculated upon. When I was asked my tips, I gave all I could think of at the time. Later that evening I remembered a couple more, some of my best ones.

So for those who went to MAX and those that did not, here are my official video tips for Flash and Flex.

Disclaimer: Technology changes on a regular basis, as of the date of this post I feel very comfortable with the statements made below. As new versions of software are released some of the comments may become outdated.

1. Your source file is king when it comes to getting good quality video. A good source file is the difference between hulu and youtube video. If you have control over your video source, make sure you get a good high-res lossless video file. They are huge and some clients do not know what you are talking about when you ask for it, but try your best to get a good source file.

2. Encode your own files. There are many flv encoders out there, some even your clients can use. But if you want good quality, then encode them yourselves. Of course some clients are pretty savvy when it comes to these things, in that case train them.

3. Use the Flash Video Encoder standalone application. *I have exported flv's from many other programs, but quality is more consistent with the Flash Video Encoder application. Plus the encoding speed is a lot better with the Flash Video Encoder. It does suck to encode something twice, once to a lossless file, then a second time to flv, but in my testing it has been worth it.
(*H.264 can be encoded from other applications with equal quality. I have not compared them yet, but it is a very standard codec.)

4. If you do not have Flash CS4, use on2 VP6 encoding, it is much better than the other codec options. H.264 is a great improvement even over on2 VP6. Mp4 files can use different codecs, so make sure you are using H.246 and mp3 audio if you are encoding with other applications.

5. Not all video files are the same. Video containing a lot of motion/action can not handle as much compression as a low motion, talking head video. You will have to test your video files and encode each file with different settings to get optimum performance, size and quality. Also if you have control over the editing of your source files, certain video transitions (cross dissolve) encode worse than others.

6. Do not change frame rate when encoding an flv. This will cause your a/v sync to drift. Any edits to frame rate needs to be made in your source file before you encode. This does not apply to video without sound.

7. Dropping FPS and lowering the Key Frame Interval can lower file size of the flv, but there are consequences. For lowering frame rate, see number 6. Lowering the frame rate interval will effect fast-forwarding and rewinding and may effect syncing between key frames. If you need smooth fast forward and rewind, then leave the key frame interval to automatic or raise it a little more. I believe it is set to 24 frames by default.

8. If you want to have good streaming performance, place your streaming files on a server setup for streaming content. There could be cross-domain security sandbox issues, if your files do not load, first check if you need a crossdomain.xml file.

9. Video has come along way from the timeline full of image sequences from pre Flash MX days. Video still has a large file size that can only be compressed so far. Video needs to buffer before playing and can consume a lot of CPU. If possible stop other animations, visual effects, and any processor intense code while your videos are playing.

10. There are still times when video is not the best solution. I still use image sequences if the job requires it, even though video can be the easier way to go in most cases. You may have to push your animation skills to pull off video type effects. Building your animation in Flash will give you more control over the size and quality of your project.

Using Random in Game Development, buy with strict guidelines, order can bring some variety to game play.

This sample is not a single solution but an approached I used in developing Whacky Voting - a politically smashing game. It uses random with some strict rules to get rid of sequences that some players can easily remember, yet keeping game play consistent from one game to the next.

This demo starts with a configuration section, used to set up how we want the game to act. The engine it self could be organized a little better to be more transportable. It is commented pretty well though, so it should be easy enough to understand the approach as well as practical usage. Random is used to shuffle all of the objects that appear on screen as well as what container the objects are associated with.

Configuration:
We use config data for each game so that we can easily tweak game-play without hacking our code later. We can use arrays, xml or other data sources. Plan ahead and build config options into your game as it is developed.

This array designates slots or containers to hold each appearing object. Use this to limit how many objects appear at a time and where they are placed on screen. this can represent MovieClips or other classes.

?View Code ACTIONSCRIPT
var objHolderArr:Array = [];
objHolderArr[0] = {obj:"object0",id:0,stat:false,timer:20,type:"",score:0,targ:null,xCoor:10};
objHolderArr[1] = {obj:"object1",id:1,stat:false,timer:20,type:"",score:0,targ:null,xCoor:90};
objHolderArr[2] = {obj:"object2",id:2,stat:false,timer:20,type:"",score:0,targ:null,xCoor:170};
objHolderArr[3] = {obj:"object3",id:3,stat:false,timer:20,type:"",score:0,targ:null,xCoor:250};
objHolderArr[4] = {obj:"object4",id:4,stat:false,timer:20,type:"",score:0,targ:null,xCoor:330};
objHolderArr[5] = {obj:"object5",id:5,stat:false,timer:20,type:"",score:0,targ:null,xCoor:410};

Next is an array of objects to appear, this is to control what type of objects appear and to make sure they are nicely distributed through out each level. You may have different scores, wilds and/or bonus score objects that need to get incorporated into the object list, but using random by it self will not allow them to be distributed appropriately for consistent game play.

?View Code ACTIONSCRIPT
var objSequenceArr:Array = [];
objSequenceArr[0] = {obj:"type0", count:20,score:100};
objSequenceArr[1] = {obj:"type1", count:15, score:150};
objSequenceArr[2] = {obj:"type2", count:5, score:500};
objSequenceArr[3] = {obj:"type3", count:5, score:1000};
objSequenceArr[4] = {obj:"null", count:5, score:0};
 
//timer increment for the engine to trigger an event
var timeInc:int = 500;
 
// integer to keep track of increment of game engine
var arrLoc:int = 0;
 
// random key
var randomKey:int = 1000;
 
// time for each object to stay visible;
var delay:int = 4;

It is good to set game status variables to allow games controls to be a little more intuitive. Sometimes I use a gameStatus string variable and a string to denote the current status. That way I can get more mileage out of one variable.

?View Code ACTIONSCRIPT
var gameOver:Boolean;
 
//or
 
var gameStatus:String = "_play";

Build Config Data for Engine:
The current level array built from config data above. The method then adds to the level array all the objects that we want to appear during the game.

?View Code ACTIONSCRIPT
var levelArr:Array = [];
 
function buildConfigData():void{
for(var p:String in objSequenceArr){
var loopCnt:int = objSequenceArr[p].count;
for(var i:uint = 0; i < loopCnt; i++){
var randNum:int = randomNumber(randomKey);
levelArr.push({obj:objSequenceArr[p].obj, score:objSequenceArr[p].score, key:randNum});
}
}
 
levelArr.sortOn("key",Array.NUMERIC || Array.DESCENDING);
}
buildConfigData();

Last, we sort the list so that it is shuffled which gives us the first random effect. All the objects are placed in the array in order of the sequence array, but we added a random number as the key to sort the array with. Now all of the objects will be randomly placed throughout the array and we will always have the right amount of objects for consistent game play.

Game Engine:
Now that we have our data, we are ready to start the engine.

1. Pull first random number

2. Loop until random number is not a slot that is already taken. We add a break and status variable to stop the loop if we can not find an available object. On a break, we will wait until the next TimerEvent and try again.

3. We have an active slot that is not already taken, we set it's status to true and show and configure our object.

4. Use this timer event to also run our Active Checker Method below. The more you can piggy-back off of single timers and EnterFrame events the better.

?View Code ACTIONSCRIPT
var timer:Timer = new Timer(timeInc,0);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
 
function timerHandler(ev:TimerEvent):void{
 
//1.
var randSlot:int = randomNumber(objHolderArr.length);
 
//2.
if(arrLoc < levelArr.length){
if(levelArr[arrLoc].obj != "null"){
var breakCnt:int
var breakStatus:Boolean;
while(objHolderArr[randSlot].stat == true){
randSlot = randomNumber(objHolderArr.length);
breakCnt ++;
if(breakCnt >= 100){
breakStatus = true;
break;
}
}
 
if(!breakStatus){
//3.
var slotObj:Object = objHolderArr[randSlot];
slotObj.stat = true;
slotObj.timer = delay;
slotObj.score = levelArr[arrLoc].score;
slotObj.type = levelArr[arrLoc].type;
 
//******* add code here to initiate your visual objects.
var tempBO:ballObj = new ballObj();
tempBO.x = slotObj.xCoor;
tempBO.y = 20;
tempBO.objIDStr = arrLoc.toString();
tempBO.objScoreStr = levelArr[arrLoc].score;
tempBO.objTypeStr = levelArr[arrLoc].obj;
addChild(tempBO);
 
//********* end visual code here.
 
slotObj.targ = tempBO;
activeObjArr.push(slotObj);
// we advance the array location variable.
arrLoc ++;
}
}
else{
arrLoc ++;
}
}
 
//4.
activeChecker();
}

After each object is initiated, we need to give them an amount of time to be active. This is the activeObject array, we will track the time, if the user does not score with the object then it will be removed by the timer.

1. Loop through the active array to decrease each object's timer.

2. If the timer is run out, remove the object from the array and reset the object's status.

?View Code ACTIONSCRIPT
var activeObjArr:Array = [];
 
function activeChecker():void{
for(var p:String in activeObjArr){
//1.
activeObjArr[p].timer --;
 
//2.
if(activeObjArr[p].timer <= 0){
activeObjArr[p].stat = false;
removeChild(activeObjArr[p].targ);
activeObjArr.splice(int(p),1);
 
if(arrLoc >= levelArr.length && activeObjArr.length == 0){
//game is over.
gameOver = true;
timer.stop();
btn.enabled = true;
btn.alpha = 1;
}
}
}
}

Here is where you can place your event handlers for a user interactive with an object. We have to remove and reset the object, shown above and add the objects score to the main score.

We will also need a method for when the game clears the last array object.

Utilities:
method to pull random numbers just so I do not need to write this same code more than once.

?View Code ACTIONSCRIPT
function randomNumber(limit:int):int{
var randNum:int = Math.random()*limit;
return randNum;
}

Controls:
A restart control availble when game is over

?View Code ACTIONSCRIPT
btn.addEventListener(MouseEvent.CLICK,clickHandler);
btn.enabled = false;
btn.alpha = 0.2;
function clickHandler(ev:MouseEvent):void{
if(gameOver){
// rebuild data to show off shuffling.
levelArr = [];
buildConfigData();
 
//reset game controls and game engine.
arrLoc = 0;
timer.start();
gameOver = false;
btn.enabled = false;
btn.alpha = 0.2;
}
}

The Ball Object:
The ball object is a simple class that displays the data for each object. You would normally place a button or some other way to capture user interaction and send it back to the engine to initiate scores and feedback.

?View Code ACTIONSCRIPT
package{
import flash.display.MovieClip;
import flash.text.TextField;
import flash.events.Event;
 
public class ballObj extends MovieClip{
 
public var objIDStr:String = "";
public var objTypeStr:String = "";
public var objScoreStr:String = "";
 
public function ballObj():void{
init();
stop();
}
 
private function init():void{
this.addEventListener(Event.ADDED,addedHandler);
}
 
private function addedHandler(ev:Event):void{
objID.text = objIDStr;
objScore.text = objScoreStr;
objType.text = objTypeStr;
 
}
}
}

Source Here
This is it, about it the very first bit of actionscript code I ever learned, site besides play() and gotoAndStop() of course. The lesson went down with an experienced programmer looking over my shoulder telling me what to type. After this little app was finished, approved my brain hurt only understanding a few of the lines we wrote. That code was referenced and/or modified on more then a few projects that came after, each time deciphering more and applying it to new functionalities.

The original script was back in the day of AS1, but I am going to present it to you in AS3. If you are a beginner to ActionScript then it is the perfect time to learn AS3.

We are going to start really remedial for a minute and go over the basics of the classes and objects we will be using. It is kind-of long, so if you already have the basics covered, you can skip to the Application code.

The Variable:
Remember Pre-Algebra? 2+x = y? Variables are used for more then just place holders in a math equation. Programming is a very literal language, variables are how we make it figurative. Now instead of addressing one object with a snippet of code, that code can be applied to the many objects and properties our variables represent.

To use a variable, we must declare it using these three letters "var". Then comes the creative part, we get to think of a name. This can be a lot of fun making up funny names for things until someone else has to figure out your code or you forget that you called the variable that is going to bring balance to your application "anakin", oops, or was that "luke"?

After naming the variable, we have to declare it's type. We really don't have to, but it is a good idea. This variable will be a Number, because we will need it to include decimals.

Here are some examples of how variables can be used. Think about if we were selling apples that costs 65¢ a peace. A person wants to buy 5 apples. so we build an equation to handle the transaction.

?View Code ACTIONSCRIPT
var totalCost:Number;
totalCost = 0.65 * 5; //3.25

Ok, so we went conservitive, using "totalCost" for the total of apples purchased. Now what do we do when someone wants to buy 4 apples, or 6, or 8? Now we should add a new variable to represent the amount of apples. This variables declaration is an "int" (integer) as we will not be selling fractions of apples.

?View Code ACTIONSCRIPT
var numApples:int = 5;
var totalCost:Number;
totalCost = 0.65 * numApples; // 3.25

Everyone is happy until next week when there is an apple shortage and the price increases to 85¢ a piece. Now you have to go through you app and change all the prices from 65¢ to 85¢. If we use variables we can easily modify the app when the price changes, better yet, now this same app could be used to handle bananas, grapefruit and pears which all have different prices.

?View Code ACTIONSCRIPT
var cost:Number = 0.85;
var numFruit = 5;
var totalCost:Numer;
totalCost = cost * numFruit; // $4.25

Array:
Array is one of the most powerful classes in Flash. It's power comes from the way an array holds a collection of information. Not only do we have access to the information, but we can loop through all the items in an array and monitor the length of the collection.

This is how we might set up some variables without arrays. If we add or take away an item, we have to update a separate variable to keep track of the total amount. Looping through this is information is possible, but tricky.

?View Code ACTIONSCRIPT
var fuit1:String = "apple";
var fruit2:String = "banana";
var fruit3:String = "pear";
var fruits:int = 3;
 
// Or we can do the same thing with an array.
 
var fruitArr:Array = ["apple","banana","pear"];
 
trace(fruitArr[0]); //"apple
trace(fruitArr.length); //3

One thing that you must remember when using arrays is that they are zero indexed, meaning the first position in the array is 0. This can cause a little confusion because we teach our children to start counting at 1, not 0. This will hopefully make more sense later or maybe more confusion, but at least you will know why you are confused.

Tip: instead of useing var fruitArr:Array = new Array(); which you may have seen before. Using the square braces will do same thing. var fruitArr:Array = [];

If we think of our application as if it were an engine, the data objects (arrays, XML) are the fuel. The part of the application that interates like loops, enter frame events and timers are the heart of the engine, like the pistons, cams and crank shaft. This engine starts once the app loads and runs until we stop everything or close the app.

for() Loop:
Interates or repeats a a specified amount allowing our engine to apply the same code to multiple objects. Loops will run and complete in between each frame, before each render. This means you will not visually see what the loop is doing until it completes and the stage renders.

?View Code ACTIONSCRIPT
// This is a loop using the array from above:
for(var p:String in fruitArr){
trace(fruitArr[p] + " | index = " + p);
}
 
output:
apple | index = 0
banana | index = 1
pear | index = 2

First we assign a variable to the item that is going to loop trough the array. p stands for property and is a string. Here you can see the output of "p" which is showing the index or location of each item in the array. Notice that "apple" is the first item, which has an index of 0. If we get the length of the array (fruitArr.length) it will return a 3 which is 1 more then the last index in the array (2). Length counts like we do, starting at #1, index counts like computers do, starting at 0.

Tip: The p variable outputs a number in this case. This number is not really a number, it is a string using number characters. If we tried to add these "numbers" up, we would get "012" instead of the sum of 3. This is one reason declaring variable types are important. The compiler will tell us immediately if we are passing a string into an equation where a number or integer should be. Many external data sources will pass numbers into Flash as strings. Declaring variable types adds integrity to our applications.

Function:
A function is like a little wrapper or snippet of code that we can call at a later time. They are like the transmission, servos, clutch and any other metaphorical mechanism that takes energy and makes stuff happen.

Functions can run with or without feedback, adding a few arguments they can become very flexible. Let's use our fruit price calculator equation as a sample. This function receives two arguments (quantity and price), does the calculation, then returns the price. Nothing happens when the script loads, only when the function is called, see below.

?View Code ACTIONSCRIPT
function chaChing(quantity:int, price:Number):Number{
var calc:Number = price * quantity;
return calc;
}
var totalCost:Number = chaChing(5, 0.85);
trace(totalCost); //$4.25
 
// Notice the declaration :Number after the close parenthases
// on the function name.
function chaChing():Number{
}
 
// This lets the compiler know that the function is returning
// a value when it is called. If we do not need to return a value
// when the funciton is called, we would use void.
 
function chaChing():void{
}

This is a really simple one line function, but even this is a valid use. If you ever use the same equation or sequence more then once in your application, wrap it in a function.

Tip: A variables declared inside of a function will not be accessable outside of that function, but variables decaleared outside of the function are visible to it.

Tip: The words method and function are interchangeable.

Tip: Most "Real" programmers will put the opening curly brace one the next line under the function name.

if / else Condition:
Basically a switch, if a cindition is met, do one thing, if not then do something different.

Event:
These enable our controls and is the triggering system for our functions. Events monitors the engine and user input, they can be considered part of the engines electrical system.

Finally the Application:
The simple application we are going to build is an image loader. We will build a custom button, the code will place a button on the stage for each image. We will then hook up these controls to dynamically load in each image.

The beginning of our app is the config area, this is where we set up all of our variables and any constants.

?View Code ACTIONSCRIPT
/*
* first is the array, this is a list of image urls.
* We are going to loop through this array to create the correct amount of buttons.
* When the buttons are pressed, we will use the array to pull to corresponding image url.
*/
var imageArr:Array = ["images/apple.jpg","images/banana.jpg","images/pear.jpg"];
 
 
/****************************************************
* variables
****************************************************/
// buffHeight: will be use this to calulate the y possition of each button.
// 22 is the y coordinate to start the first button.
var buffHeight:int = 22;
 
// loadX and loadY: This will place our image in the correct spot on the stage.
var loadX:int = 156;
var loady:int = 22;
 
/****************************************************
* the loop:
* Iterates through the array, adds a button for each item, adds event listeners,
* updates the buffHeight variable then stops when it reaches the end of the array.
*****************************************************/
 
// There are a few different types of loops, this one is based on the items of an array.
// The first part of the loop conditions is declaring a variable to represent the index
// as the loop iterates through the array.
 
for(var p:String in imageArr){
 
// create new ImageButton
var imgBtn:ImageButton = new ImageButton();
 
// add a button label
imgBtn.labelText.text = "Image " + p;
 
// give the button a id from "p" which references the index
// of the current item in the array.
imgBtn.id = int(p);
 
// set the y property using the buffHeight variable.
imgBtn.y = buffHeight;
imgBtn.x = 20;
 
// add the eventListener to capture the button clicks
imgBtn.addEventListener(MouseEvent.CLICK,clickHandler);
 
//add the button to the stage.
addChild(imgBtn);
 
//update the variable with the height of this button, so the next button's y position will be below it.
buffHeight += imgBtn.height + 5;
}
 
/****************************************************
* function clickHandler(MouseEvent)
* handler for the Click MouseEvent assigned to each button in the loop.
****************************************************/
function clickHandler(ev:MouseEvent):void{
 
// the event's target property tells which button fired the event, now we can get the correct id.
var id:int = ev.currentTarget.id;
 
//use the id and the imageArr to get the correct image url.
var url:String = imageArr[id];
 
//call the loadImage function with the url as an argument.
loadImage(url);
}
 
/****************************************************
* function loadImage(url:String)
* function for loading the images
****************************************************/
function loadImage(url:String):void{
 
// new variable of new loader object
var ldr:Loader = new Loader();
 
// new URLRequest using the url we passed in as an argument.
// this converts the string into a url request we can pass to the loader to load the image.
var req:URLRequest = new URLRequest(url);
 
//loading the image
ldr.load(req);
 
ldr.x = loadX;
ldr.y = loady;
 
// add loader to MovieClip referenced by loadTarget.
addChild(ldr);
}
 
stop();

Button code and instructions:
Make a new MovieClip. Inside this new MovieClip create some artwork to be used as the button background. Add a textField and variable declaration for id (we will pass in the id during the loop). Then check the Export to ActionScript option in the MovieClips *properties window.

*To get to the MovieClips property window, right-click on the MovieClip in the Library, then choose properties. You may need to click the advanced button to see all the options.

We are using a MovieClip instead of a button, so that we can pass in an id and control the text. So we are going to build a MovieClip to act as a button.

Source Here

Where to go from here:
1. Play with the application variables and the array. Expand the app by giving each button a better name. Maybe build the array using names in stead of urls, then you can create the new url string using "images/" + name + ".jpg". You could also create a name array in the same sequence or use slice on the url to pull the name out.

2. Expand the buttons, if you really want to get fancy, create an on-state for each button, so that you can tell which image is currently displayed.

3. Add the calculator code to display how much each item cost when you click a button and a loader.

Tip: The ldr function above places one item on top of another, this may cause an issue if you want to show something behind each image while it is loading.

Take the existing code and come up with another uses for it. If you come up with some cool ideas, post some links below. Also if you figure out any of the previous enhancement, post some code.

To put your code in a code block, you can wrap it in these tags. Take out the "[" and "]" ,square brackets.
[<]pre lang="actionscript"[>]
// all code goes here.
[<]/pre[>]

Construction

Wether I am illustrating an imaginary device or something I use everyday, mind it is good to understand how the object is or should be constructed. Other information like functionality, page and how these objects are interacted with are very important in making our illustrations more convincing.

Questions you could ask yourself are how much heft and mass does this object possess, What kids of materials are used to build this object? How does this information effect how light reflects/refracts off the object. These evaluations help us understand how the details should be rendered.

The object could be steel, but is it built assembled with welds, bolts or both? The object could be made from concrete, Styrofoam, wood, glass or plastic molds. Each material is assembled differently with different types of joints. The time when an object is built also will give us a clue as to the type of assembly would have been used. We should carry that information or hints of that information into our illustration.

We do not have to have an engineering degree to know that some buildings are made from glass and steal, brick/concrete block, or wood. A glass building would be smooth and shiny on the outside with little definition where each glass plate comes together. Brick buildings have thick walls so windows are inset into the wall. Wood buildings have window frames that are used to hold the window into the wall.

These are the types of things that should be going through our heads as we sketch, construct, color, and touch up our work. In the meantime we are building our forms in Illustrator, here are some techniques to speed up our work as we construct our illustrations with the provided tools.

Using divide and Unite:
Divide and Unite are two pathfinder tools I use the most. You should set these to actions with keyboard shortcuts.

Divide Tip 1:
Create a shadow, reflection, glare on a larger shape. One of the rules for quick illustration in Illustrator is to never draw the same line twice. Another rule is divide does not have to be destructive. If you have ever used Divide before on a shape and zoomed out, sometimes you will notice a little background seeping through where the Divide incision are applied.

Draw the path how you would like your incision, over lapping on both ends and making sure the path has no fill. Select the larger shape first, Copy and Paste in Front (Command + F / Cntr + F) then select the line you created for your incision. Apply the Divide to the shape and delete the unwanted piece.

This creates a smaller shape on top of the original shape, in seconds, with no gaps and non-destructive. If we do not like the way it looks, we can always delete it and start over with our original shape still intact.

Divide Tip 2:
Again Divide does not have to be destructive. If you have a few overlapping paths, Divide with create a joined shape and trim off the excess paths. This can come in handy when using a grid, copy the lines we want to use from the grid, and apply a Divide. You will now have a new shape that matches your guides without having to draw anything. We drew the lines once for the guide, we should not have to draw them a gain.

Divide Tip 3:
Overlap your paths with working with divide. It is much easier to make sure your division are complete if you see your incision paths are overlapping your original shape.

Unite Tip 1:
Sometimes Divide can have some unwelcome results, but they can be cleaned up quickly with Unite.

Unite Tip 2:
Unite goes hand with Outline Stroke. If you have a fill and a stroke, using Outline Stroke then Unite will convert a path into a new solid shape. I like to use this for making nice outlines or inking effects. Depending on your Illustrator Preference settings, paths will scale on one machine and not another. It is also a good idea to Outline & Unite paths if the size relationship is important.

Below is a simple funny faced frog made almost intierly with the oval tool and Outlined paths.

For a better explanation of these tips, watch Illustrating in Illustrator, the Happy Frog video tutorial.

Flash tip: Paths have never translated well to Flash, so try Outline & Unite before importing to Flash.

Offset Stroke:
Found in the Object:Path menu, is similar to Outline Stroke. In CS3 and before the new path is automatically grouped to the original path. So if you have a few paths being made from the Outline Stroke command, you will have to select all the pieces and Cut & Paste them out of the group to work with them easier. I still use it very often, mostly on simpler shapes.

In Illustrator CS4 Outline Stroke works much better and mimics the functionality mentioned in Unite Tip 2.

Duplicate and Transform:
There are many times while we are illustrating that we come across many objects that are similar like windows, bolts, or even spider eyes. By completing on object, then copying and distributing those copies around will make creating all these objects less redundant. Even if shapes, size, perspective differ, there may be parts that are reusable, or a quick transform can really help save time.

Drawing vs Editing:
We have discussed never drawing the same line twice and was to create new shapes from exiting ones. Also we went over duplicating shapes and objects to help speed things up. The rules in this series are just like most rules, there is very often an exception. If you are comfortable with the pen tool in Illustrator, it is almost always faster to draw a new line then it is to edit an existing one. If you are tweaking a couple points on an existing path, that is one thing, but if you copy an path with the intent on modifying many points, it is most likely faster to draw a whole new path. Or at least delete the points you would like to edit, and draw a new path in it's place.

Join and Average:
Even drawing paths holding down the shift key will not always get our lines straight. The keyboard shortcut for Average is Command + Option + J on a Mac and Control + Alt + J on PC. Any lines that are supposed to be straight that for some reason are not, is just a second away from be so, but you have to remember the keyboard short cut to really make it worth while.

Another Keyboard shortcut to remember is Join. Command + J on a Mac and Control + J on PC, will be used over and over again to clean up stray points. Divide, Outline Stroke and other wonderful tools we have covered so far are great time savers but can put unwanted points in our paths. One of our objectives it to create Clean artwork. Extra points and text Miter spikes will not do, so a quick select with the Hollow Arrow, or Hollow Lasso, then Join, will clean those points up quickly.

Group and Layer as you go:
As discussed in Part 1 of the series, grouping is important in speeding up our work. It is much easier to grab a bunch of paths that have been grouped with the solid arrow, then selecting many paths to do a tweak. Many time you will be working on something else in the illustration and you will notice something you want to tweak something that was done previously. As you finish objects with multiple paths they should be grouped.

Distributing artwork in layer is a great way to create a groups too. The results of good groups is easy selection and/or isolation of parts of the illustration. Using Lock and Hide as well as layers are great ways to isolate our work.

Next - Illustrating In Illustrator 101 Part 3 of 5: Defining Shapes

For a better explanation of these tips, watch Illustrating in Illustrator, the Happy Frog video tutorial.

When a Flash/Flex app loads into a browser, abortion all urls for the swf are now relative to the file that is hosting the swf and not the location of the swf file itself. This can create issues between testing the swf locally and viewing it on the live site.

Case Study:
When building a demo to display on this blog I have to create one version with relative urls to distribute as source and a separate sample for preview using absolute urls. This is because of the setup of the blog, more about some files like the index page display from the root of the blog while all the article files have unique urls based on title and date.

In the process of developing web applications your files can be moved from a local dev environment, to a staging environment and then to a final live server. It is efficient to keep all your swfs and external files together, packaged in their own directory. During migration, directory structures of the hosting files may change causing your relative urls to break and your absolute urls to point to the wrong domain.

Solution:
In AS3's LoaderObject class there is a url property which will display the url of root swf. This is nice to know because now I can place files relative to the swf file and one version will work offline, in the testing environment, one the final server and best of all my blog.

The same property is available in AS2, see below.

How to make your relative urls work based on the swf url:
The "url" property returns the url to the root swf file. This is too much information, but with a little trimming we can get exactly what we need.

AS3 Method:

?View Code ACTIONSCRIPT
var swfURL:String = this.loaderInfo.url;
swfURL = swfURL.substr(0, swfURL.lastIndexOf("/") + 1)
trace(swfURL);

AS2 Method:

?View Code ACTIONSCRIPT
var swfURL:String = this._url;
swfURL = swfURL.substr(0,swfURL.lastIndexOf("/") + 1);
trace(swfURL);

Now add the swfURL variable as a prefix to all your urls like so:
var imgUrl:String = swfURL + "images/image1.jpg";

Tip:
To get the hosting domain url you can use this (AS2 & AS3):

?View Code ACTIONSCRIPT
var tempDom:Array = swfURL.split("/");
var domURL:String = tempDom.slice(0,3).join("/") + "/";
trace(domURL);

Maintaining version control on project files can easily get out of control when saving multiple versions of the same file. One tip is covered in an earlier post about swf based relative urls for flash/flex files. This tip works even if the host file is moved to a different locations. This way we do not need to save a live version and a local build version.

Why would I care which Flash Player type is used?
Some projects, story like kiosks, approved will end up as a Flash Projector or AIR Application. Until the project is finalized and approved we may need to preview the project for our clients on the web. In AS3 some stage methods are only available to the standalone player. Instead of saving two versions of the same project, medicine one to test the Projector functionality and another for online approvals; we can build one multi-purpose file.

AS3 Method:

?View Code ACTIONSCRIPT
if(Capabilities.playerType == "StandAlone"){
stage.displayState = StageDisplayState.FULL_SCREEN;
 
// mouse hide and show for touchscreen kiosk: default (hide)
Mouse.hide();
}
trace(Capabilities.playerType); //StandAlone

AS2 Method:

?View Code ACTIONSCRIPT
trace(System.capabilities.playerType); //StandAlone

Here is a list of Flash Player type strings:
from Flash AS3 language reference
"ActiveX" for the Flash Player ActiveX control used by Microsoft Internet Explorer
"Desktop" for the Adobe AIR runtime (except for SWF content loaded by an HTML page, which has Capabilities.playerType set to "PlugIn" )
"External" for the external Flash Player or in test mode
"PlugIn" for the Flash Player browser plug-in (and for SWF content loaded by an HTML page in an AIR application)
"StandAlone" for the stand-alone Flash Player

If you need to know the player version number of the Flash Player use this code:
AS3:
trace(Capabilities.version); //MAC 10,0,2,54 or WIN 10,0,2,54

AS2:
trace(System.capabilities.version); //MAC 10,0,2,54 or WIN 10,0,2,54

tip 1: If your swf requires a newer Flash Player version, it is best to detect flash player versions using the Flash Version Detection option in the HTML publishing settings and require the user to download the newer player. SWFs published to newer Flash Player versions can be very unstable when running in older Players and can cause browser and system crashes.

tip 2:
Standalone and Desktop players are built into the executables so the Flash Player version will always be correct no matter what is currently installed on the system.

tip 3:
For a complete list of all the system capabilities you can learn about the system that is running your projects, look here.

Converting AS3 to Cocoa Touch:
The iPhone is another interest of mine because it is just so cool. I would love to build apps for the iphone but do not know when I would have time to learn cocoa touch. That is why I am very interested in Andy Jacobs' Blog and his tutorials on AS3 to Cocoa Touch. Now if I can just find the time, sildenafil these tutorials definitely make understanding cocoa conventions much easier for an AS programmer.

AS3 Reference iPhone Application:
So what is the next best thing to having Flash on the iPhone? How about an Action Script 3 reference documentation application for the iPhone? Not sure when I would use it. Perhaps when they port the Flex SDK to the iPhone, help otherwise I would rather use the online version with a huge monitor, full keyboard and mouse. I do not know why I still had to get the app, It is just one of those things that sound so good.
Was anyone else thrown for a loop as much as I was about Flash CS4s animation system? I knew the basics and played around with the new animation tools before, buy but then I had my first real animation job with it. Wow! that really sucked.

It is hard to say if the new tools are better then before, ambulance that all depends on your needs. If you want to do a quick animation, diagnosis then stick with the classic tweens. If you want higher quality animation with some real fine tuning then the new tools are for you. I have to admit, if I had written this post just one day earlier, my option of the new animation tools would have been completely 180° opposite. Now I think they are great, so if you are frustrated now, read on and take a deep breath.

Forgetting How to Animate:
My first hurdle was to forget how I animated in the past. Instead of placing a keyframe on the timeline everywhere you want the x, y or z property to change in value, you keyframe the two extremes of your your animation. Everything in-between and easing is handled by custom tween curves.

In this demo we will do a bouncing ball, but this one will animate and bounce off all four sides of the stage. Previously we would place our ball on the stage where we want the ball to hit the sides, maybe add a motion guide for some nice arks to simulate gravity, then tweak the tweens between each keyframe until we have something that looks believable. Now a single tween last the entire length of our animation, so adding those extra keyframes on the timeline will mess up your tween.

Extremes:
We just start with two keyframes, one at each extreme of where we want the ball to travel.
Then with the ball selected, open the motion editor. Here we see our x and y curves, well they are just strait lines. If you apply a tween you will just get a change in the motion dynamics between the two keyframes. Instead scroll down to the Eases row, this is where all the real animation happens now. Click on the plus icon and select custom from the bottom of the list. Do this twice. I hate that we are not able to name our custom tweens, maybe next release, anyway, create one for the x axis and one for the y axis.

By default each curve starts at 0% on the left and goes to 100% on the right. On the right side of the curve, change the value to 0%. Now slide back up to the x and y tween drop downs and select the custom tween you wan to apply to each property. I chose "1-custom" for x and "2-custom" for y. Now slide back down and lets get to work.

If you test out the animation now, nothing will happen, not even the diagonal movement we had before.

Custom Curves:
On each custom curve place four keyframes. Now with the individual keyframes selected, slide the values of each tween until you get the desired placement of the ball on each axis. Now we can mess with the curves to effect the dynamics of how the ball bounces from one side to the next. We can even create nice arc effects to really pull off a convincing animation.

We only need to do this for the x, y and z properties. The other properties like scale, color and filters allow you to apply curves directly in their tween rows. The three "statual" properties do not allow any curves to be applied directly, all you can do is apply an existing tween from the tweens section of the Motion Editor. If you try to keyframe your x and y properties on the timeline and apply a tween, you will notice the tween is applied across all frames and you will not get the desired result. The movement will work, but the easing will not.

I finished off the animation with some blur and a shadow animation. I just copied the ball tween, added an advanced color setting, broadened the x and y extremes and tweaked the blur.

Tip:
Though you cannot save tween curves, (they do this in photoshop, so hopefully on next release) you can copy curves from one object's Motion Editor to another. Once you have an animation in the can, you can save it as a motion preset. This is really powerful, it even saves the blank keyframe I place at the end of my tweans for tidiness.

Other Pros to the Motion Editor:
You can stretch or condense the animation by dragging the last frame and all the keyframes adjust proportionally. You also can change instance properties like the instance type MovieClip to Graphic, instance name and loop properties once then it applies across the whole tween.

There may be a better way of doing this but if you want to continue an animation and start where the previous tween ended. It may be best to start a new tween instead of stretching things out and adjusting your tween curves inside the Motion Editor to make room. The best way I have figured out how to do this is to grab the tween on the timeline, hold down option (Mac) or alt (PC) as you drag it to an empty spot on the timeline, which will make a copy. Convert the tween to Frame by Frame Animation. Now you can remove all the frames but the last one which is right where the previous tween left off. It would be nice it this was available as a one step command too.

In the sample below, I keyframed the x and y extremes, though I wanted the animation to start a little to the right of extreme left. I understand the tweens start and 0 (extreme left) and end at 100 (extreme right), but these are not really just tweens anymore, are they? To make this work without making two animations, I set frame 1 to the desired x coordinate and the alpha on the previous frame to 0. I then copied the tween, using the method above, and pulled out the second frame to place over the first frame on the timeline.

The new tweening tools are very powerful and will help us produce better quality animations, I am glad they still have the option of a classic tween as I still use that from time to time for really simple stuff (it is just faster) along with shape tweens. I do not look at this as a replacement of the tools I am used to using, but a new really powerful option when animating. You do have to plan ahead a little and it will take a extra time setting up custom tween and tweaking things to look right. We had to do a lot of animation slight-of-hand tricks to get things to look right before, so you have to admit this is cool. Just remember with great power comes great responsibility (Ben Parker).

Download Source
This is a two in one post, ask the first half will demonstrate how to build a small but powerful animation engine. The second half is a demo and source for an expanded version of the same animation engine.

The goals for our engine are:
1. Light Weight - We do not want to apply an onEnterFrame event handler on every MovieClip. Each instance of an onEnterFrame event increases processor usage, health so we will use one onEnterFrame event to process all animation.

2. Robust - Issues can arise with you try daisy chain onEnterFrame events, garbage collection and rendering sequences can cause the chain to break. So we need a powerful management system.

3. Flexible - Some projects we only need to animate _alpha, others will need to tween _x, _y, _rotation, _xScale or a combination of them all. With a little extra code we can make this animation engine process most MovieClip Properties.

When I program something new, I make a list of all the features I need for the app. Below are the notes for this engine, now we can add the variables and methods to support each feature.

?View Code ACTIONSCRIPT
// data, array and object management.
 
// data handler, add data to array
 
// remove data from array
 
// enter frame event
 
// process animation and make tweens happen

The Array:
First is data, we will use an array to hold all the data for each animation while the engine runs. Keeping all the data in a central location means less issues caused by garbage collection and objects being added to and removed from the stage.

Arrays are super powerful, you may be familiar with an array that looks like this:

?View Code ACTIONSCRIPT
var tempArr:Array = new Array("red","blue","green","yellow");
trace(tempArr[0]); // "red"
 
//or
 
var tempArr:Array = [];
tempArr[0] = "red";
tempArr[1] = "blue";
tempArr[2] = "green";
tempArr[3] = "yellow";
trace(tempArr[1]); // "blue"

This engine will require much more information that is tightly organized. For this we will add a data object to each element of the array. A data object can look similar to an array, that is because they can be indexed like an array.

?View Code ACTIONSCRIPT
var tempObj:Object = new Object();
tempObj[0] = "hello";
trace(tempObj[0]); // "hello"

Property type variables can also be set on a data object.

?View Code ACTIONSCRIPT
tempObj.mess = "world";
 
trace(tempObj[0] + " " + tempObj.mess); // "hello world"

By combining a data object and an array we can keep a ton of data that is easily retrieved while the engine runs. First we need to declare our array. This is a short hand version of setting a new array.

?View Code ACTIONSCRIPT
// data, array and object management.
 
var animationArr:Array  = [];

Adding Data To The Array:
That was too easy, but don't worry, it will get a little more complicated in a minute. Now we need to add data to our array, so this section will cover a method to do just that. The function will need to receive the following information as arguments then add the data to the array.

1. obj:Object - This will reference the object (MovieClip) to be animated. Object can also reference TextFields and Buttons.

2. prop:String - the property ("_x") of the object we want to animate. To animate multiple properties for the same object, we need to call this method one time for each property. It may seem like extra work, but gives the engine greater flexibility.

3. val:Number - the value we desire the object property to be when the animation has finished.

4. ease:Number - The amount of ease to apply to the object property as it changes over time. Easing can require complicated equations, but we will keep things as simple as possible. If a positive number, the tween will have no ease and process the property changes over the amount of frames specified linearly. If a negative number, we will use that value in a simple easing equation that will cause an ease effect by incrementing the property value less and less as it gets closer to it's destination value.

5. end:Function - To allow daisy chaining, we will be able to call a function when each animation has ended.

This method will execute the following:
A. Send data to the removeTween method to make sure we are not duplicating an animation of any property animations, that would be bad. We will pass the object and the property string, so the removeTween method can validate and remove the correct element if it exists.

B. Find the tween increment amount (jump) to adjust the object property each frame.

C. Enter the new data as an object into the array using push. To do this we will use the curly brackets { } to designate an object. similar to how square brackets [ ] designate an array. Inside the curly brackets we will assign each variable (variable name, colon (:), variable value). A comma separates each element in the object list, similar to an array.

?View Code ACTIONSCRIPT
// data handler, add data to array
function insertTween(obj:Object, prop:String, val:Number, ease:Number, end:Function){
//A. manage duplicates in the array
removeTween(obj, prop);
 
//B. figure out the tween increment for the frames specified.
// target value minus the current value, as a positive number, divided by the number of frames.
var dif:Number = Math.abs(obj[prop] - val) / ease;
 
//C. add data to the animation array
animationArr.push({ aniObj: obj, propStr: prop, propValue: val, jump: dif, aniEase: ease, endFunction: end });
 
}

Remove Element or Duplicates:
We need to make sure that that the same object property is not trying to be animated twice. Say you have an animation connected to a button that slides something up, then when the button is clicked again, it slides back down. If the button is pressed before the object tween is complete we need to end the first animation, then we need to start the tween back down starting at it's current location.

This method will loop through the animationArr and look for any duplicates, if one is found, then it is removed. We will also use this method when a tween is complete to remove the animation from the array.

We need two arguments to validate a tween match, the object and the property to be animated. There may be two instances of the object in the array as long as they are for different properties.

1. obj:Object - Object to be animated

2. prop:String - The property of the object to be animated.

As we loop through the array, we will compare the obj in the argument to the aniObject of each element. If we get a match on the Object and the property, then the element will be removed using Array.splice(), then we will stop the loop. As long as duplicates are always checked before data is entered into the array, there should never be an instance of more than one element matching.

?View Code ACTIONSCRIPT
// remove data from array
function removeTween(obj:Object, prop:String){
for(var p:String in animationArr ){
if(animationArr[p].obj == targObj && animationArr[p].prop == prop){
animationArr.splice(Number(p),1);
break;
}
}
}

To keep things running fast, we only want to use one onEnterFrame event to run everything. You may also add other method calls to this event listener to power other features in your application.

We will use another for loop to pass the object from each array element to the animation handler method. That is where all the real magic happens.

?View Code ACTIONSCRIPT
// enter frame event
this.onEnterFrame = function(){
for(var p:String in animationArr){
animationHandler(animationArr[p]);
}
}

Finally making things move, this method will receive a data object and increment the object properties to be tweened.
1. obj:Object - This is the data object from addTween method, it has references to the visible objects to be animated as well as the property and easing information.

A. Set the current property value to "tempVal"

B. Find out if the value is increasing or decreasing.

C. If the value is increasing, we need addition.

D. Let's talk about easing, if the ease value is above 0, we are going to use the animation increment (jump) we made in the addTween method. This is super easy but makes for boring animation. If the value of ease is less then 0, we will use a simple easing equation. ((t - c )/ e) 1. We get the difference of the current value and the target value (t-c). 2. Then divide that value by ease amount. We are only using the negative value to differentiate if we want an ease or linear animation, so we need to convert the ease value to a positive number using Math.abs(ease). Every time the object property value moves closer to target value the difference is divided by much smaller numbers. This causes the tween to move slower as the target value is reached creating a very accentuated ease effect.

The only catch is if you have a function call set to go off at the end of this animation, the ease ,if set too high, can cause the animation to take an extra second to finish before the function is called.

E. Check to see if the destination has been reached or over shot, if so, set the value manually to the target value, remove the tween and fire off the function call if present.

F. Now do the same thing as above, but use subtraction this time.

?View Code ACTIONSCRIPT
// process animation
function animationHandler(obj){
 
//A. get current value of object property.
var tempVal:Number = obj.aniObj[obj.propStr];
 
//B. check if value should go up or down.
var dir:Boolean;
tempVal < obj.propValue ? dir = true: dir = false;
 
//C. if value needs to increase we add.
if(dir){
 
//D. check for an ease value, if linear, increase using jump amount, else use the ease equation.
obj.aniEase > 0 ? tempVal += obj.jump:  tempVal += (obj.propValue - tempVal) / Math.abs(obj.aniEase);
 
//E. if destination has been reached, remove tween from array and call function.
if(Math.round(tempVal) >= obj.propValue){
tempVal = obj.propValue;
 
//remove tween
removeTween(obj.aniObj, obj.propStr);
 
//call end function if present
if(obj.endFunction != null){
obj.endFunction();
}
}
// apply the tempVal to the object property. By setting the value in this way,
// we are able to tween any property using the same code
// Example: (boxMC["_x"] = 200; will set the _x property of a MovieClip instance
// called "boxMC" to 200.
obj.aniObj[obj.propStr] = tempVal;
}
else{ // same as above except using subtraction.
obj.aniEase > 0 ? tempVal -= obj.jump: tempVal -= (tempVal - obj.propValue) / Math.abs(obj.aniEase);
if(Math.round(tempVal) <= obj.propValue){
tempVal = obj.propValue;
 
//remove tween
removeTween(obj.aniObj, obj.propStr);
 
if(obj.endFunction != null){
obj.endFunction();
}
}
obj.aniObj[obj.propStr] = tempVal;
}
}

Now that all the stuff is done, we can initiate the engine with one line of code.

?View Code ACTIONSCRIPT
insertTween(boxMC, "_x", 360, 10, null);

To animate more properties of an object we need to add a call for each property to be animated. The following example will animate the _x, _y, and _alpha properties of a MovieClip instance called "boxMC" over 15 frames. You can change the ease values to create more interesting animations.

?View Code ACTIONSCRIPT
insertTween(boxMC, "_x", 360, 15, null);
insertTween(boxMC, "_y", 300, 15, null);
insertTween(boxMC, "_alpha", 0, 15, null);

The New Animation Class:
This was originally built in 2002, but it was too complicated to use with most projects. It has been revised a few times over the years into the latest, simpler incarnation. There are more powerful solutions out there like Tweener, but I think this is simple and light enough for most of my needs.

Features:
1. Tweens all common properties for MovieClip like: _x, _y, _width, _height, _xScale, _yScale, _rotation and _alpha.

2. Easing is not perfect code-wise, but looks and works pretty nice. Includes a Tweens class with Super Ease, ease in and ease out.

3. Simple to use.

4. Multiple instances of this class can run at the same time, not that you should need to, but it is possible.

5. This class uses an interval instead of onEnterFrame form more consistent animation across projects that are set to different frame rates. Based on 24 fps.

This version adds an argument for speed. With expanded ease functionality we needed an extra argument.

Class Usage:
The following sample will animate the _x property of a MovieClip instance named "boxMC" over twenty frames with a ease value of 80.

?View Code ACTIONSCRIPT
// import and register the Animation class.
import com.hdi.as2.Animation;
var ae:Animation = new Animation();
 
// sample call to Animation class to initiate a tween.
ae.setTrans(boxMC,350,"_x",20,80,null);
//Arguments:
//ae.setTrans(objMC:Object, propValue:Number, property:String, speed:Number, ease:Number, endFunction:Function);

In the demo below you can change the property, value, speed and ease values of each tween by updating the input fields and pressing the tween button. Ease values between 0 - 100 and -1 and -100 produce similar tweens to the standard Flash tween. Ease Values between greater than 100 and less than -100 will produce a super tween and the speed value will be ignored. Super Ease values between 103 - 120 and -103 - -120 produce the best results.

Demo

Download Source

Adobe MAX 2008 kicks off with Shantanu Narayen, troche Adobe CEO.

I will do some live blogging from MAX. All post are being typed on my iPhone, due to my broken laptop, so do not expect a lot of details.

Over 5000 in attendence.

Followed by 2 more MAX conferences in europe and Asia.

Flash catalyst announced, previously Thurmo.

(Red) Wire announced, delivered on AIR. $5 a month.

Kevin Lynch on stage.

Cloud and client. Across multiple screens/devices.

Flash player 10 is awesome.
Audio waveform data, 3D, text engine, drawing API, pixel blender.
FAST realtime processing.

Max keynote is available online now. keynote

I cannot do it justice from my iPhone, pilule so check it out.

Updates:

Apparantly the keynote video does not live at the address I placed above, visit web that is what was on the big screen at the end of the keynote. sorry about that.
Here are a couple links of real live blogging (bet they had a laptop).
Liveblogging MAX 2008 Day 1 General Session Keynote

Adobe MAX 2008: Monday - Keynote

Tour de Flex on a 20' screen, shot by Greg Wilson. Tour de Flex on a 20 ft Screen
The first day of MAX has ended at 10:30 pm Monday night. East coast time is taking it's toll, sales but I know I am not the only one. I just finished moderating a video tips group that was full of drooping eyes.

Today was a success with 4 new t-shirts and a few new tips learned. All of the sessions are going to be available for free at Adobe TV. I have heard the Flash Catylist (thermo) sessions were really good, information pills the Flash Player Internals session had some nice insight on optimizing code, this my favorite one of the day. The Flex Tips session showed off some features of Flex Builder that I never new existed and now will not be able to live without.

MAX 2008 Sessions added to Adobe TV - 12/11/08

MAX 2008 on Adobe TV.

In a Birds-Of-A-Feather discussion group at Adobe MAX last week. No remarks were planned, search It was supposed to be a discussion, stuff we hoped to talk to other developers about what's new in using Flash video. We did not get a bunch of new information but we did get a lot of hard questions. Some of them were not fully answered and others were speculated upon. When I was asked my tips, I gave all I could think of at the time. Later that evening I remembered a couple more, some of my best ones.

So for those who went to MAX and those that did not, here are my official video tips for Flash and Flex.

Disclaimer: Technology changes on a regular basis, as of the date of this post I feel very comfortable with the statements made below. As new versions of software are released some of the comments may become outdated.

1. Your source file is king when it comes to getting good quality video. A good source file is the difference between hulu and youtube video. If you have control over your video source, make sure you get a good high-res lossless video file. They are huge and some clients do not know what you are talking about when you ask for it, but try your best to get a good source file.

2. Encode your own files. There are many flv encoders out there, some even your clients can use. But if you want good quality, then encode them yourselves. Of course some clients are pretty savvy when it comes to these things, in that case train them.

3. Use the Flash Video Encoder standalone application. *I have exported flv's from many other programs, but quality is more consistent with the Flash Video Encoder application. Plus the encoding speed is a lot better with the Flash Video Encoder. It does suck to encode something twice, once to a lossless file, then a second time to flv, but in my testing it has been worth it.
(*H.264 can be encoded from other applications with equal quality. I have not compared them yet, but it is a very standard codec.)

4. If you do not have Flash CS4, use on2 VP6 encoding, it is much better than the other codec options. H.264 is a great improvement even over on2 VP6. Mp4 files can use different codecs, so make sure you are using H.246 and mp3 audio if you are encoding with other applications.

5. Not all video files are the same. Video containing a lot of motion/action can not handle as much compression as a low motion, talking head video. You will have to test your video files and encode each file with different settings to get optimum performance, size and quality. Also if you have control over the editing of your source files, certain video transitions (cross dissolve) encode worse than others.

6. Do not change frame rate when encoding an flv. This will cause your a/v sync to drift. Any edits to frame rate needs to be made in your source file before you encode. This does not apply to video without sound.

7. Dropping FPS and lowering the Key Frame Interval can lower file size of the flv, but there are consequences. For lowering frame rate, see number 6. Lowering the frame rate interval will effect fast-forwarding and rewinding and may effect syncing between key frames. If you need smooth fast forward and rewind, then leave the key frame interval to automatic or raise it a little more. I believe it is set to 24 frames by default.

8. If you want to have good streaming performance, place your streaming files on a server setup for streaming content. There could be cross-domain security sandbox issues, if your files do not load, first check if you need a crossdomain.xml file.

9. Video has come along way from the timeline full of image sequences from pre Flash MX days. Video still has a large file size that can only be compressed so far. Video needs to buffer before playing and can consume a lot of CPU. If possible stop other animations, visual effects, and any processor intense code while your videos are playing.

10. There are still times when video is not the best solution. I still use image sequences if the job requires it, even though video can be the easier way to go in most cases. You may have to push your animation skills to pull off video type effects. Building your animation in Flash will give you more control over the size and quality of your project.

Using Random in Game Development, buy with strict guidelines, order can bring some variety to game play.

This sample is not a single solution but an approached I used in developing Whacky Voting - a politically smashing game. It uses random with some strict rules to get rid of sequences that some players can easily remember, yet keeping game play consistent from one game to the next.

This demo starts with a configuration section, used to set up how we want the game to act. The engine it self could be organized a little better to be more transportable. It is commented pretty well though, so it should be easy enough to understand the approach as well as practical usage. Random is used to shuffle all of the objects that appear on screen as well as what container the objects are associated with.

Configuration:
We use config data for each game so that we can easily tweak game-play without hacking our code later. We can use arrays, xml or other data sources. Plan ahead and build config options into your game as it is developed.

This array designates slots or containers to hold each appearing object. Use this to limit how many objects appear at a time and where they are placed on screen. this can represent MovieClips or other classes.

?View Code ACTIONSCRIPT
var objHolderArr:Array = [];
objHolderArr[0] = {obj:"object0",id:0,stat:false,timer:20,type:"",score:0,targ:null,xCoor:10};
objHolderArr[1] = {obj:"object1",id:1,stat:false,timer:20,type:"",score:0,targ:null,xCoor:90};
objHolderArr[2] = {obj:"object2",id:2,stat:false,timer:20,type:"",score:0,targ:null,xCoor:170};
objHolderArr[3] = {obj:"object3",id:3,stat:false,timer:20,type:"",score:0,targ:null,xCoor:250};
objHolderArr[4] = {obj:"object4",id:4,stat:false,timer:20,type:"",score:0,targ:null,xCoor:330};
objHolderArr[5] = {obj:"object5",id:5,stat:false,timer:20,type:"",score:0,targ:null,xCoor:410};

Next is an array of objects to appear, this is to control what type of objects appear and to make sure they are nicely distributed through out each level. You may have different scores, wilds and/or bonus score objects that need to get incorporated into the object list, but using random by it self will not allow them to be distributed appropriately for consistent game play.

?View Code ACTIONSCRIPT
var objSequenceArr:Array = [];
objSequenceArr[0] = {obj:"type0", count:20,score:100};
objSequenceArr[1] = {obj:"type1", count:15, score:150};
objSequenceArr[2] = {obj:"type2", count:5, score:500};
objSequenceArr[3] = {obj:"type3", count:5, score:1000};
objSequenceArr[4] = {obj:"null", count:5, score:0};
 
//timer increment for the engine to trigger an event
var timeInc:int = 500;
 
// integer to keep track of increment of game engine
var arrLoc:int = 0;
 
// random key
var randomKey:int = 1000;
 
// time for each object to stay visible;
var delay:int = 4;

It is good to set game status variables to allow games controls to be a little more intuitive. Sometimes I use a gameStatus string variable and a string to denote the current status. That way I can get more mileage out of one variable.

?View Code ACTIONSCRIPT
var gameOver:Boolean;
 
//or
 
var gameStatus:String = "_play";

Build Config Data for Engine:
The current level array built from config data above. The method then adds to the level array all the objects that we want to appear during the game.

?View Code ACTIONSCRIPT
var levelArr:Array = [];
 
function buildConfigData():void{
for(var p:String in objSequenceArr){
var loopCnt:int = objSequenceArr[p].count;
for(var i:uint = 0; i < loopCnt; i++){
var randNum:int = randomNumber(randomKey);
levelArr.push({obj:objSequenceArr[p].obj, score:objSequenceArr[p].score, key:randNum});
}
}
 
levelArr.sortOn("key",Array.NUMERIC || Array.DESCENDING);
}
buildConfigData();

Last, we sort the list so that it is shuffled which gives us the first random effect. All the objects are placed in the array in order of the sequence array, but we added a random number as the key to sort the array with. Now all of the objects will be randomly placed throughout the array and we will always have the right amount of objects for consistent game play.

Game Engine:
Now that we have our data, we are ready to start the engine.

1. Pull first random number

2. Loop until random number is not a slot that is already taken. We add a break and status variable to stop the loop if we can not find an available object. On a break, we will wait until the next TimerEvent and try again.

3. We have an active slot that is not already taken, we set it's status to true and show and configure our object.

4. Use this timer event to also run our Active Checker Method below. The more you can piggy-back off of single timers and EnterFrame events the better.

?View Code ACTIONSCRIPT
var timer:Timer = new Timer(timeInc,0);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
 
function timerHandler(ev:TimerEvent):void{
 
//1.
var randSlot:int = randomNumber(objHolderArr.length);
 
//2.
if(arrLoc < levelArr.length){
if(levelArr[arrLoc].obj != "null"){
var breakCnt:int
var breakStatus:Boolean;
while(objHolderArr[randSlot].stat == true){
randSlot = randomNumber(objHolderArr.length);
breakCnt ++;
if(breakCnt >= 100){
breakStatus = true;
break;
}
}
 
if(!breakStatus){
//3.
var slotObj:Object = objHolderArr[randSlot];
slotObj.stat = true;
slotObj.timer = delay;
slotObj.score = levelArr[arrLoc].score;
slotObj.type = levelArr[arrLoc].type;
 
//******* add code here to initiate your visual objects.
var tempBO:ballObj = new ballObj();
tempBO.x = slotObj.xCoor;
tempBO.y = 20;
tempBO.objIDStr = arrLoc.toString();
tempBO.objScoreStr = levelArr[arrLoc].score;
tempBO.objTypeStr = levelArr[arrLoc].obj;
addChild(tempBO);
 
//********* end visual code here.
 
slotObj.targ = tempBO;
activeObjArr.push(slotObj);
// we advance the array location variable.
arrLoc ++;
}
}
else{
arrLoc ++;
}
}
 
//4.
activeChecker();
}

After each object is initiated, we need to give them an amount of time to be active. This is the activeObject array, we will track the time, if the user does not score with the object then it will be removed by the timer.

1. Loop through the active array to decrease each object's timer.

2. If the timer is run out, remove the object from the array and reset the object's status.

?View Code ACTIONSCRIPT
var activeObjArr:Array = [];
 
function activeChecker():void{
for(var p:String in activeObjArr){
//1.
activeObjArr[p].timer --;
 
//2.
if(activeObjArr[p].timer <= 0){
activeObjArr[p].stat = false;
removeChild(activeObjArr[p].targ);
activeObjArr.splice(int(p),1);
 
if(arrLoc >= levelArr.length && activeObjArr.length == 0){
//game is over.
gameOver = true;
timer.stop();
btn.enabled = true;
btn.alpha = 1;
}
}
}
}

Here is where you can place your event handlers for a user interactive with an object. We have to remove and reset the object, shown above and add the objects score to the main score.

We will also need a method for when the game clears the last array object.

Utilities:
method to pull random numbers just so I do not need to write this same code more than once.

?View Code ACTIONSCRIPT
function randomNumber(limit:int):int{
var randNum:int = Math.random()*limit;
return randNum;
}

Controls:
A restart control availble when game is over

?View Code ACTIONSCRIPT
btn.addEventListener(MouseEvent.CLICK,clickHandler);
btn.enabled = false;
btn.alpha = 0.2;
function clickHandler(ev:MouseEvent):void{
if(gameOver){
// rebuild data to show off shuffling.
levelArr = [];
buildConfigData();
 
//reset game controls and game engine.
arrLoc = 0;
timer.start();
gameOver = false;
btn.enabled = false;
btn.alpha = 0.2;
}
}

The Ball Object:
The ball object is a simple class that displays the data for each object. You would normally place a button or some other way to capture user interaction and send it back to the engine to initiate scores and feedback.

?View Code ACTIONSCRIPT
package{
import flash.display.MovieClip;
import flash.text.TextField;
import flash.events.Event;
 
public class ballObj extends MovieClip{
 
public var objIDStr:String = "";
public var objTypeStr:String = "";
public var objScoreStr:String = "";
 
public function ballObj():void{
init();
stop();
}
 
private function init():void{
this.addEventListener(Event.ADDED,addedHandler);
}
 
private function addedHandler(ev:Event):void{
objID.text = objIDStr;
objScore.text = objScoreStr;
objType.text = objTypeStr;
 
}
}
}

Source Here
This is it, about it the very first bit of actionscript code I ever learned, site besides play() and gotoAndStop() of course. The lesson went down with an experienced programmer looking over my shoulder telling me what to type. After this little app was finished, approved my brain hurt only understanding a few of the lines we wrote. That code was referenced and/or modified on more then a few projects that came after, each time deciphering more and applying it to new functionalities.

The original script was back in the day of AS1, but I am going to present it to you in AS3. If you are a beginner to ActionScript then it is the perfect time to learn AS3.

We are going to start really remedial for a minute and go over the basics of the classes and objects we will be using. It is kind-of long, so if you already have the basics covered, you can skip to the Application code.

The Variable:
Remember Pre-Algebra? 2+x = y? Variables are used for more then just place holders in a math equation. Programming is a very literal language, variables are how we make it figurative. Now instead of addressing one object with a snippet of code, that code can be applied to the many objects and properties our variables represent.

To use a variable, we must declare it using these three letters "var". Then comes the creative part, we get to think of a name. This can be a lot of fun making up funny names for things until someone else has to figure out your code or you forget that you called the variable that is going to bring balance to your application "anakin", oops, or was that "luke"?

After naming the variable, we have to declare it's type. We really don't have to, but it is a good idea. This variable will be a Number, because we will need it to include decimals.

Here are some examples of how variables can be used. Think about if we were selling apples that costs 65¢ a peace. A person wants to buy 5 apples. so we build an equation to handle the transaction.

?View Code ACTIONSCRIPT
var totalCost:Number;
totalCost = 0.65 * 5; //3.25

Ok, so we went conservitive, using "totalCost" for the total of apples purchased. Now what do we do when someone wants to buy 4 apples, or 6, or 8? Now we should add a new variable to represent the amount of apples. This variables declaration is an "int" (integer) as we will not be selling fractions of apples.

?View Code ACTIONSCRIPT
var numApples:int = 5;
var totalCost:Number;
totalCost = 0.65 * numApples; // 3.25

Everyone is happy until next week when there is an apple shortage and the price increases to 85¢ a piece. Now you have to go through you app and change all the prices from 65¢ to 85¢. If we use variables we can easily modify the app when the price changes, better yet, now this same app could be used to handle bananas, grapefruit and pears which all have different prices.

?View Code ACTIONSCRIPT
var cost:Number = 0.85;
var numFruit = 5;
var totalCost:Numer;
totalCost = cost * numFruit; // $4.25

Array:
Array is one of the most powerful classes in Flash. It's power comes from the way an array holds a collection of information. Not only do we have access to the information, but we can loop through all the items in an array and monitor the length of the collection.

This is how we might set up some variables without arrays. If we add or take away an item, we have to update a separate variable to keep track of the total amount. Looping through this is information is possible, but tricky.

?View Code ACTIONSCRIPT
var fuit1:String = "apple";
var fruit2:String = "banana";
var fruit3:String = "pear";
var fruits:int = 3;
 
// Or we can do the same thing with an array.
 
var fruitArr:Array = ["apple","banana","pear"];
 
trace(fruitArr[0]); //"apple
trace(fruitArr.length); //3

One thing that you must remember when using arrays is that they are zero indexed, meaning the first position in the array is 0. This can cause a little confusion because we teach our children to start counting at 1, not 0. This will hopefully make more sense later or maybe more confusion, but at least you will know why you are confused.

Tip: instead of useing var fruitArr:Array = new Array(); which you may have seen before. Using the square braces will do same thing. var fruitArr:Array = [];

If we think of our application as if it were an engine, the data objects (arrays, XML) are the fuel. The part of the application that interates like loops, enter frame events and timers are the heart of the engine, like the pistons, cams and crank shaft. This engine starts once the app loads and runs until we stop everything or close the app.

for() Loop:
Interates or repeats a a specified amount allowing our engine to apply the same code to multiple objects. Loops will run and complete in between each frame, before each render. This means you will not visually see what the loop is doing until it completes and the stage renders.

?View Code ACTIONSCRIPT
// This is a loop using the array from above:
for(var p:String in fruitArr){
trace(fruitArr[p] + " | index = " + p);
}
 
output:
apple | index = 0
banana | index = 1
pear | index = 2

First we assign a variable to the item that is going to loop trough the array. p stands for property and is a string. Here you can see the output of "p" which is showing the index or location of each item in the array. Notice that "apple" is the first item, which has an index of 0. If we get the length of the array (fruitArr.length) it will return a 3 which is 1 more then the last index in the array (2). Length counts like we do, starting at #1, index counts like computers do, starting at 0.

Tip: The p variable outputs a number in this case. This number is not really a number, it is a string using number characters. If we tried to add these "numbers" up, we would get "012" instead of the sum of 3. This is one reason declaring variable types are important. The compiler will tell us immediately if we are passing a string into an equation where a number or integer should be. Many external data sources will pass numbers into Flash as strings. Declaring variable types adds integrity to our applications.

Function:
A function is like a little wrapper or snippet of code that we can call at a later time. They are like the transmission, servos, clutch and any other metaphorical mechanism that takes energy and makes stuff happen.

Functions can run with or without feedback, adding a few arguments they can become very flexible. Let's use our fruit price calculator equation as a sample. This function receives two arguments (quantity and price), does the calculation, then returns the price. Nothing happens when the script loads, only when the function is called, see below.

?View Code ACTIONSCRIPT
function chaChing(quantity:int, price:Number):Number{
var calc:Number = price * quantity;
return calc;
}
var totalCost:Number = chaChing(5, 0.85);
trace(totalCost); //$4.25
 
// Notice the declaration :Number after the close parenthases
// on the function name.
function chaChing():Number{
}
 
// This lets the compiler know that the function is returning
// a value when it is called. If we do not need to return a value
// when the funciton is called, we would use void.
 
function chaChing():void{
}

This is a really simple one line function, but even this is a valid use. If you ever use the same equation or sequence more then once in your application, wrap it in a function.

Tip: A variables declared inside of a function will not be accessable outside of that function, but variables decaleared outside of the function are visible to it.

Tip: The words method and function are interchangeable.

Tip: Most "Real" programmers will put the opening curly brace one the next line under the function name.

if / else Condition:
Basically a switch, if a cindition is met, do one thing, if not then do something different.

Event:
These enable our controls and is the triggering system for our functions. Events monitors the engine and user input, they can be considered part of the engines electrical system.

Finally the Application:
The simple application we are going to build is an image loader. We will build a custom button, the code will place a button on the stage for each image. We will then hook up these controls to dynamically load in each image.

The beginning of our app is the config area, this is where we set up all of our variables and any constants.

?View Code ACTIONSCRIPT
/*
* first is the array, this is a list of image urls.
* We are going to loop through this array to create the correct amount of buttons.
* When the buttons are pressed, we will use the array to pull to corresponding image url.
*/
var imageArr:Array = ["images/apple.jpg","images/banana.jpg","images/pear.jpg"];
 
 
/****************************************************
* variables
****************************************************/
// buffHeight: will be use this to calulate the y possition of each button.
// 22 is the y coordinate to start the first button.
var buffHeight:int = 22;
 
// loadX and loadY: This will place our image in the correct spot on the stage.
var loadX:int = 156;
var loady:int = 22;
 
/****************************************************
* the loop:
* Iterates through the array, adds a button for each item, adds event listeners,
* updates the buffHeight variable then stops when it reaches the end of the array.
*****************************************************/
 
// There are a few different types of loops, this one is based on the items of an array.
// The first part of the loop conditions is declaring a variable to represent the index
// as the loop iterates through the array.
 
for(var p:String in imageArr){
 
// create new ImageButton
var imgBtn:ImageButton = new ImageButton();
 
// add a button label
imgBtn.labelText.text = "Image " + p;
 
// give the button a id from "p" which references the index
// of the current item in the array.
imgBtn.id = int(p);
 
// set the y property using the buffHeight variable.
imgBtn.y = buffHeight;
imgBtn.x = 20;
 
// add the eventListener to capture the button clicks
imgBtn.addEventListener(MouseEvent.CLICK,clickHandler);
 
//add the button to the stage.
addChild(imgBtn);
 
//update the variable with the height of this button, so the next button's y position will be below it.
buffHeight += imgBtn.height + 5;
}
 
/****************************************************
* function clickHandler(MouseEvent)
* handler for the Click MouseEvent assigned to each button in the loop.
****************************************************/
function clickHandler(ev:MouseEvent):void{
 
// the event's target property tells which button fired the event, now we can get the correct id.
var id:int = ev.currentTarget.id;
 
//use the id and the imageArr to get the correct image url.
var url:String = imageArr[id];
 
//call the loadImage function with the url as an argument.
loadImage(url);
}
 
/****************************************************
* function loadImage(url:String)
* function for loading the images
****************************************************/
function loadImage(url:String):void{
 
// new variable of new loader object
var ldr:Loader = new Loader();
 
// new URLRequest using the url we passed in as an argument.
// this converts the string into a url request we can pass to the loader to load the image.
var req:URLRequest = new URLRequest(url);
 
//loading the image
ldr.load(req);
 
ldr.x = loadX;
ldr.y = loady;
 
// add loader to MovieClip referenced by loadTarget.
addChild(ldr);
}
 
stop();

Button code and instructions:
Make a new MovieClip. Inside this new MovieClip create some artwork to be used as the button background. Add a textField and variable declaration for id (we will pass in the id during the loop). Then check the Export to ActionScript option in the MovieClips *properties window.

*To get to the MovieClips property window, right-click on the MovieClip in the Library, then choose properties. You may need to click the advanced button to see all the options.

We are using a MovieClip instead of a button, so that we can pass in an id and control the text. So we are going to build a MovieClip to act as a button.

Source Here

Where to go from here:
1. Play with the application variables and the array. Expand the app by giving each button a better name. Maybe build the array using names in stead of urls, then you can create the new url string using "images/" + name + ".jpg". You could also create a name array in the same sequence or use slice on the url to pull the name out.

2. Expand the buttons, if you really want to get fancy, create an on-state for each button, so that you can tell which image is currently displayed.

3. Add the calculator code to display how much each item cost when you click a button and a loader.

Tip: The ldr function above places one item on top of another, this may cause an issue if you want to show something behind each image while it is loading.

Take the existing code and come up with another uses for it. If you come up with some cool ideas, post some links below. Also if you figure out any of the previous enhancement, post some code.

To put your code in a code block, you can wrap it in these tags. Take out the "[" and "]" ,square brackets.
[<]pre lang="actionscript"[>]
// all code goes here.
[<]/pre[>]

Construction

Wether I am illustrating an imaginary device or something I use everyday, mind it is good to understand how the object is or should be constructed. Other information like functionality, page and how these objects are interacted with are very important in making our illustrations more convincing.

Questions you could ask yourself are how much heft and mass does this object possess, What kids of materials are used to build this object? How does this information effect how light reflects/refracts off the object. These evaluations help us understand how the details should be rendered.

The object could be steel, but is it built assembled with welds, bolts or both? The object could be made from concrete, Styrofoam, wood, glass or plastic molds. Each material is assembled differently with different types of joints. The time when an object is built also will give us a clue as to the type of assembly would have been used. We should carry that information or hints of that information into our illustration.

We do not have to have an engineering degree to know that some buildings are made from glass and steal, brick/concrete block, or wood. A glass building would be smooth and shiny on the outside with little definition where each glass plate comes together. Brick buildings have thick walls so windows are inset into the wall. Wood buildings have window frames that are used to hold the window into the wall.

These are the types of things that should be going through our heads as we sketch, construct, color, and touch up our work. In the meantime we are building our forms in Illustrator, here are some techniques to speed up our work as we construct our illustrations with the provided tools.

Using divide and Unite:
Divide and Unite are two pathfinder tools I use the most. You should set these to actions with keyboard shortcuts.

Divide Tip 1:
Create a shadow, reflection, glare on a larger shape. One of the rules for quick illustration in Illustrator is to never draw the same line twice. Another rule is divide does not have to be destructive. If you have ever used Divide before on a shape and zoomed out, sometimes you will notice a little background seeping through where the Divide incision are applied.

Draw the path how you would like your incision, over lapping on both ends and making sure the path has no fill. Select the larger shape first, Copy and Paste in Front (Command + F / Cntr + F) then select the line you created for your incision. Apply the Divide to the shape and delete the unwanted piece.

This creates a smaller shape on top of the original shape, in seconds, with no gaps and non-destructive. If we do not like the way it looks, we can always delete it and start over with our original shape still intact.

Divide Tip 2:
Again Divide does not have to be destructive. If you have a few overlapping paths, Divide with create a joined shape and trim off the excess paths. This can come in handy when using a grid, copy the lines we want to use from the grid, and apply a Divide. You will now have a new shape that matches your guides without having to draw anything. We drew the lines once for the guide, we should not have to draw them a gain.

Divide Tip 3:
Overlap your paths with working with divide. It is much easier to make sure your division are complete if you see your incision paths are overlapping your original shape.

Unite Tip 1:
Sometimes Divide can have some unwelcome results, but they can be cleaned up quickly with Unite.

Unite Tip 2:
Unite goes hand with Outline Stroke. If you have a fill and a stroke, using Outline Stroke then Unite will convert a path into a new solid shape. I like to use this for making nice outlines or inking effects. Depending on your Illustrator Preference settings, paths will scale on one machine and not another. It is also a good idea to Outline & Unite paths if the size relationship is important.

Below is a simple funny faced frog made almost intierly with the oval tool and Outlined paths.

For a better explanation of these tips, watch Illustrating in Illustrator, the Happy Frog video tutorial.

Flash tip: Paths have never translated well to Flash, so try Outline & Unite before importing to Flash.

Offset Stroke:
Found in the Object:Path menu, is similar to Outline Stroke. In CS3 and before the new path is automatically grouped to the original path. So if you have a few paths being made from the Outline Stroke command, you will have to select all the pieces and Cut & Paste them out of the group to work with them easier. I still use it very often, mostly on simpler shapes.

In Illustrator CS4 Outline Stroke works much better and mimics the functionality mentioned in Unite Tip 2.

Duplicate and Transform:
There are many times while we are illustrating that we come across many objects that are similar like windows, bolts, or even spider eyes. By completing on object, then copying and distributing those copies around will make creating all these objects less redundant. Even if shapes, size, perspective differ, there may be parts that are reusable, or a quick transform can really help save time.

Drawing vs Editing:
We have discussed never drawing the same line twice and was to create new shapes from exiting ones. Also we went over duplicating shapes and objects to help speed things up. The rules in this series are just like most rules, there is very often an exception. If you are comfortable with the pen tool in Illustrator, it is almost always faster to draw a new line then it is to edit an existing one. If you are tweaking a couple points on an existing path, that is one thing, but if you copy an path with the intent on modifying many points, it is most likely faster to draw a whole new path. Or at least delete the points you would like to edit, and draw a new path in it's place.

Join and Average:
Even drawing paths holding down the shift key will not always get our lines straight. The keyboard shortcut for Average is Command + Option + J on a Mac and Control + Alt + J on PC. Any lines that are supposed to be straight that for some reason are not, is just a second away from be so, but you have to remember the keyboard short cut to really make it worth while.

Another Keyboard shortcut to remember is Join. Command + J on a Mac and Control + J on PC, will be used over and over again to clean up stray points. Divide, Outline Stroke and other wonderful tools we have covered so far are great time savers but can put unwanted points in our paths. One of our objectives it to create Clean artwork. Extra points and text Miter spikes will not do, so a quick select with the Hollow Arrow, or Hollow Lasso, then Join, will clean those points up quickly.

Group and Layer as you go:
As discussed in Part 1 of the series, grouping is important in speeding up our work. It is much easier to grab a bunch of paths that have been grouped with the solid arrow, then selecting many paths to do a tweak. Many time you will be working on something else in the illustration and you will notice something you want to tweak something that was done previously. As you finish objects with multiple paths they should be grouped.

Distributing artwork in layer is a great way to create a groups too. The results of good groups is easy selection and/or isolation of parts of the illustration. Using Lock and Hide as well as layers are great ways to isolate our work.

Next - Illustrating In Illustrator 101 Part 3 of 5: Defining Shapes

For a better explanation of these tips, watch Illustrating in Illustrator, the Happy Frog video tutorial.

When a Flash/Flex app loads into a browser, abortion all urls for the swf are now relative to the file that is hosting the swf and not the location of the swf file itself. This can create issues between testing the swf locally and viewing it on the live site.

Case Study:
When building a demo to display on this blog I have to create one version with relative urls to distribute as source and a separate sample for preview using absolute urls. This is because of the setup of the blog, more about some files like the index page display from the root of the blog while all the article files have unique urls based on title and date.

In the process of developing web applications your files can be moved from a local dev environment, to a staging environment and then to a final live server. It is efficient to keep all your swfs and external files together, packaged in their own directory. During migration, directory structures of the hosting files may change causing your relative urls to break and your absolute urls to point to the wrong domain.

Solution:
In AS3's LoaderObject class there is a url property which will display the url of root swf. This is nice to know because now I can place files relative to the swf file and one version will work offline, in the testing environment, one the final server and best of all my blog.

The same property is available in AS2, see below.

How to make your relative urls work based on the swf url:
The "url" property returns the url to the root swf file. This is too much information, but with a little trimming we can get exactly what we need.

AS3 Method:

?View Code ACTIONSCRIPT
var swfURL:String = this.loaderInfo.url;
swfURL = swfURL.substr(0, swfURL.lastIndexOf("/") + 1)
trace(swfURL);

AS2 Method:

?View Code ACTIONSCRIPT
var swfURL:String = this._url;
swfURL = swfURL.substr(0,swfURL.lastIndexOf("/") + 1);
trace(swfURL);

Now add the swfURL variable as a prefix to all your urls like so:
var imgUrl:String = swfURL + "images/image1.jpg";

Tip:
To get the hosting domain url you can use this (AS2 & AS3):

?View Code ACTIONSCRIPT
var tempDom:Array = swfURL.split("/");
var domURL:String = tempDom.slice(0,3).join("/") + "/";
trace(domURL);

Maintaining version control on project files can easily get out of control when saving multiple versions of the same file. One tip is covered in an earlier post about swf based relative urls for flash/flex files. This tip works even if the host file is moved to a different locations. This way we do not need to save a live version and a local build version.

Why would I care which Flash Player type is used?
Some projects, story like kiosks, approved will end up as a Flash Projector or AIR Application. Until the project is finalized and approved we may need to preview the project for our clients on the web. In AS3 some stage methods are only available to the standalone player. Instead of saving two versions of the same project, medicine one to test the Projector functionality and another for online approvals; we can build one multi-purpose file.

AS3 Method:

?View Code ACTIONSCRIPT
if(Capabilities.playerType == "StandAlone"){
stage.displayState = StageDisplayState.FULL_SCREEN;
 
// mouse hide and show for touchscreen kiosk: default (hide)
Mouse.hide();
}
trace(Capabilities.playerType); //StandAlone

AS2 Method:

?View Code ACTIONSCRIPT
trace(System.capabilities.playerType); //StandAlone

Here is a list of Flash Player type strings:
from Flash AS3 language reference
"ActiveX" for the Flash Player ActiveX control used by Microsoft Internet Explorer
"Desktop" for the Adobe AIR runtime (except for SWF content loaded by an HTML page, which has Capabilities.playerType set to "PlugIn" )
"External" for the external Flash Player or in test mode
"PlugIn" for the Flash Player browser plug-in (and for SWF content loaded by an HTML page in an AIR application)
"StandAlone" for the stand-alone Flash Player

If you need to know the player version number of the Flash Player use this code:
AS3:
trace(Capabilities.version); //MAC 10,0,2,54 or WIN 10,0,2,54

AS2:
trace(System.capabilities.version); //MAC 10,0,2,54 or WIN 10,0,2,54

tip 1: If your swf requires a newer Flash Player version, it is best to detect flash player versions using the Flash Version Detection option in the HTML publishing settings and require the user to download the newer player. SWFs published to newer Flash Player versions can be very unstable when running in older Players and can cause browser and system crashes.

tip 2:
Standalone and Desktop players are built into the executables so the Flash Player version will always be correct no matter what is currently installed on the system.

tip 3:
For a complete list of all the system capabilities you can learn about the system that is running your projects, look here.

Converting AS3 to Cocoa Touch:
The iPhone is another interest of mine because it is just so cool. I would love to build apps for the iphone but do not know when I would have time to learn cocoa touch. That is why I am very interested in Andy Jacobs' Blog and his tutorials on AS3 to Cocoa Touch. Now if I can just find the time, sildenafil these tutorials definitely make understanding cocoa conventions much easier for an AS programmer.

AS3 Reference iPhone Application:
So what is the next best thing to having Flash on the iPhone? How about an Action Script 3 reference documentation application for the iPhone? Not sure when I would use it. Perhaps when they port the Flex SDK to the iPhone, help otherwise I would rather use the online version with a huge monitor, full keyboard and mouse. I do not know why I still had to get the app, It is just one of those things that sound so good.
Was anyone else thrown for a loop as much as I was about Flash CS4s animation system? I knew the basics and played around with the new animation tools before, buy but then I had my first real animation job with it. Wow! that really sucked.

It is hard to say if the new tools are better then before, ambulance that all depends on your needs. If you want to do a quick animation, diagnosis then stick with the classic tweens. If you want higher quality animation with some real fine tuning then the new tools are for you. I have to admit, if I had written this post just one day earlier, my option of the new animation tools would have been completely 180° opposite. Now I think they are great, so if you are frustrated now, read on and take a deep breath.

Forgetting How to Animate:
My first hurdle was to forget how I animated in the past. Instead of placing a keyframe on the timeline everywhere you want the x, y or z property to change in value, you keyframe the two extremes of your your animation. Everything in-between and easing is handled by custom tween curves.

In this demo we will do a bouncing ball, but this one will animate and bounce off all four sides of the stage. Previously we would place our ball on the stage where we want the ball to hit the sides, maybe add a motion guide for some nice arks to simulate gravity, then tweak the tweens between each keyframe until we have something that looks believable. Now a single tween last the entire length of our animation, so adding those extra keyframes on the timeline will mess up your tween.

Extremes:
We just start with two keyframes, one at each extreme of where we want the ball to travel.
Then with the ball selected, open the motion editor. Here we see our x and y curves, well they are just strait lines. If you apply a tween you will just get a change in the motion dynamics between the two keyframes. Instead scroll down to the Eases row, this is where all the real animation happens now. Click on the plus icon and select custom from the bottom of the list. Do this twice. I hate that we are not able to name our custom tweens, maybe next release, anyway, create one for the x axis and one for the y axis.

By default each curve starts at 0% on the left and goes to 100% on the right. On the right side of the curve, change the value to 0%. Now slide back up to the x and y tween drop downs and select the custom tween you wan to apply to each property. I chose "1-custom" for x and "2-custom" for y. Now slide back down and lets get to work.

If you test out the animation now, nothing will happen, not even the diagonal movement we had before.

Custom Curves:
On each custom curve place four keyframes. Now with the individual keyframes selected, slide the values of each tween until you get the desired placement of the ball on each axis. Now we can mess with the curves to effect the dynamics of how the ball bounces from one side to the next. We can even create nice arc effects to really pull off a convincing animation.

We only need to do this for the x, y and z properties. The other properties like scale, color and filters allow you to apply curves directly in their tween rows. The three "statual" properties do not allow any curves to be applied directly, all you can do is apply an existing tween from the tweens section of the Motion Editor. If you try to keyframe your x and y properties on the timeline and apply a tween, you will notice the tween is applied across all frames and you will not get the desired result. The movement will work, but the easing will not.

I finished off the animation with some blur and a shadow animation. I just copied the ball tween, added an advanced color setting, broadened the x and y extremes and tweaked the blur.

Tip:
Though you cannot save tween curves, (they do this in photoshop, so hopefully on next release) you can copy curves from one object's Motion Editor to another. Once you have an animation in the can, you can save it as a motion preset. This is really powerful, it even saves the blank keyframe I place at the end of my tweans for tidiness.

Other Pros to the Motion Editor:
You can stretch or condense the animation by dragging the last frame and all the keyframes adjust proportionally. You also can change instance properties like the instance type MovieClip to Graphic, instance name and loop properties once then it applies across the whole tween.

There may be a better way of doing this but if you want to continue an animation and start where the previous tween ended. It may be best to start a new tween instead of stretching things out and adjusting your tween curves inside the Motion Editor to make room. The best way I have figured out how to do this is to grab the tween on the timeline, hold down option (Mac) or alt (PC) as you drag it to an empty spot on the timeline, which will make a copy. Convert the tween to Frame by Frame Animation. Now you can remove all the frames but the last one which is right where the previous tween left off. It would be nice it this was available as a one step command too.

In the sample below, I keyframed the x and y extremes, though I wanted the animation to start a little to the right of extreme left. I understand the tweens start and 0 (extreme left) and end at 100 (extreme right), but these are not really just tweens anymore, are they? To make this work without making two animations, I set frame 1 to the desired x coordinate and the alpha on the previous frame to 0. I then copied the tween, using the method above, and pulled out the second frame to place over the first frame on the timeline.

The new tweening tools are very powerful and will help us produce better quality animations, I am glad they still have the option of a classic tween as I still use that from time to time for really simple stuff (it is just faster) along with shape tweens. I do not look at this as a replacement of the tools I am used to using, but a new really powerful option when animating. You do have to plan ahead a little and it will take a extra time setting up custom tween and tweaking things to look right. We had to do a lot of animation slight-of-hand tricks to get things to look right before, so you have to admit this is cool. Just remember with great power comes great responsibility (Ben Parker).

Download Source
This is a two in one post, ask the first half will demonstrate how to build a small but powerful animation engine. The second half is a demo and source for an expanded version of the same animation engine.

The goals for our engine are:
1. Light Weight - We do not want to apply an onEnterFrame event handler on every MovieClip. Each instance of an onEnterFrame event increases processor usage, health so we will use one onEnterFrame event to process all animation.

2. Robust - Issues can arise with you try daisy chain onEnterFrame events, garbage collection and rendering sequences can cause the chain to break. So we need a powerful management system.

3. Flexible - Some projects we only need to animate _alpha, others will need to tween _x, _y, _rotation, _xScale or a combination of them all. With a little extra code we can make this animation engine process most MovieClip Properties.

When I program something new, I make a list of all the features I need for the app. Below are the notes for this engine, now we can add the variables and methods to support each feature.

?View Code ACTIONSCRIPT
// data, array and object management.
 
// data handler, add data to array
 
// remove data from array
 
// enter frame event
 
// process animation and make tweens happen

The Array:
First is data, we will use an array to hold all the data for each animation while the engine runs. Keeping all the data in a central location means less issues caused by garbage collection and objects being added to and removed from the stage.

Arrays are super powerful, you may be familiar with an array that looks like this:

?View Code ACTIONSCRIPT
var tempArr:Array = new Array("red","blue","green","yellow");
trace(tempArr[0]); // "red"
 
//or
 
var tempArr:Array = [];
tempArr[0] = "red";
tempArr[1] = "blue";
tempArr[2] = "green";
tempArr[3] = "yellow";
trace(tempArr[1]); // "blue"

This engine will require much more information that is tightly organized. For this we will add a data object to each element of the array. A data object can look similar to an array, that is because they can be indexed like an array.

?View Code ACTIONSCRIPT
var tempObj:Object = new Object();
tempObj[0] = "hello";
trace(tempObj[0]); // "hello"

Property type variables can also be set on a data object.

?View Code ACTIONSCRIPT
tempObj.mess = "world";
 
trace(tempObj[0] + " " + tempObj.mess); // "hello world"

By combining a data object and an array we can keep a ton of data that is easily retrieved while the engine runs. First we need to declare our array. This is a short hand version of setting a new array.

?View Code ACTIONSCRIPT
// data, array and object management.
 
var animationArr:Array  = [];

Adding Data To The Array:
That was too easy, but don't worry, it will get a little more complicated in a minute. Now we need to add data to our array, so this section will cover a method to do just that. The function will need to receive the following information as arguments then add the data to the array.

1. obj:Object - This will reference the object (MovieClip) to be animated. Object can also reference TextFields and Buttons.

2. prop:String - the property ("_x") of the object we want to animate. To animate multiple properties for the same object, we need to call this method one time for each property. It may seem like extra work, but gives the engine greater flexibility.

3. val:Number - the value we desire the object property to be when the animation has finished.

4. ease:Number - The amount of ease to apply to the object property as it changes over time. Easing can require complicated equations, but we will keep things as simple as possible. If a positive number, the tween will have no ease and process the property changes over the amount of frames specified linearly. If a negative number, we will use that value in a simple easing equation that will cause an ease effect by incrementing the property value less and less as it gets closer to it's destination value.

5. end:Function - To allow daisy chaining, we will be able to call a function when each animation has ended.

This method will execute the following:
A. Send data to the removeTween method to make sure we are not duplicating an animation of any property animations, that would be bad. We will pass the object and the property string, so the removeTween method can validate and remove the correct element if it exists.

B. Find the tween increment amount (jump) to adjust the object property each frame.

C. Enter the new data as an object into the array using push. To do this we will use the curly brackets { } to designate an object. similar to how square brackets [ ] designate an array. Inside the curly brackets we will assign each variable (variable name, colon (:), variable value). A comma separates each element in the object list, similar to an array.

?View Code ACTIONSCRIPT
// data handler, add data to array
function insertTween(obj:Object, prop:String, val:Number, ease:Number, end:Function){
//A. manage duplicates in the array
removeTween(obj, prop);
 
//B. figure out the tween increment for the frames specified.
// target value minus the current value, as a positive number, divided by the number of frames.
var dif:Number = Math.abs(obj[prop] - val) / ease;
 
//C. add data to the animation array
animationArr.push({ aniObj: obj, propStr: prop, propValue: val, jump: dif, aniEase: ease, endFunction: end });
 
}

Remove Element or Duplicates:
We need to make sure that that the same object property is not trying to be animated twice. Say you have an animation connected to a button that slides something up, then when the button is clicked again, it slides back down. If the button is pressed before the object tween is complete we need to end the first animation, then we need to start the tween back down starting at it's current location.

This method will loop through the animationArr and look for any duplicates, if one is found, then it is removed. We will also use this method when a tween is complete to remove the animation from the array.

We need two arguments to validate a tween match, the object and the property to be animated. There may be two instances of the object in the array as long as they are for different properties.

1. obj:Object - Object to be animated

2. prop:String - The property of the object to be animated.

As we loop through the array, we will compare the obj in the argument to the aniObject of each element. If we get a match on the Object and the property, then the element will be removed using Array.splice(), then we will stop the loop. As long as duplicates are always checked before data is entered into the array, there should never be an instance of more than one element matching.

?View Code ACTIONSCRIPT
// remove data from array
function removeTween(obj:Object, prop:String){
for(var p:String in animationArr ){
if(animationArr[p].obj == targObj && animationArr[p].prop == prop){
animationArr.splice(Number(p),1);
break;
}
}
}

To keep things running fast, we only want to use one onEnterFrame event to run everything. You may also add other method calls to this event listener to power other features in your application.

We will use another for loop to pass the object from each array element to the animation handler method. That is where all the real magic happens.

?View Code ACTIONSCRIPT
// enter frame event
this.onEnterFrame = function(){
for(var p:String in animationArr){
animationHandler(animationArr[p]);
}
}

Finally making things move, this method will receive a data object and increment the object properties to be tweened.
1. obj:Object - This is the data object from addTween method, it has references to the visible objects to be animated as well as the property and easing information.

A. Set the current property value to "tempVal"

B. Find out if the value is increasing or decreasing.

C. If the value is increasing, we need addition.

D. Let's talk about easing, if the ease value is above 0, we are going to use the animation increment (jump) we made in the addTween method. This is super easy but makes for boring animation. If the value of ease is less then 0, we will use a simple easing equation. ((t - c )/ e) 1. We get the difference of the current value and the target value (t-c). 2. Then divide that value by ease amount. We are only using the negative value to differentiate if we want an ease or linear animation, so we need to convert the ease value to a positive number using Math.abs(ease). Every time the object property value moves closer to target value the difference is divided by much smaller numbers. This causes the tween to move slower as the target value is reached creating a very accentuated ease effect.

The only catch is if you have a function call set to go off at the end of this animation, the ease ,if set too high, can cause the animation to take an extra second to finish before the function is called.

E. Check to see if the destination has been reached or over shot, if so, set the value manually to the target value, remove the tween and fire off the function call if present.

F. Now do the same thing as above, but use subtraction this time.

?View Code ACTIONSCRIPT
// process animation
function animationHandler(obj){
 
//A. get current value of object property.
var tempVal:Number = obj.aniObj[obj.propStr];
 
//B. check if value should go up or down.
var dir:Boolean;
tempVal < obj.propValue ? dir = true: dir = false;
 
//C. if value needs to increase we add.
if(dir){
 
//D. check for an ease value, if linear, increase using jump amount, else use the ease equation.
obj.aniEase > 0 ? tempVal += obj.jump:  tempVal += (obj.propValue - tempVal) / Math.abs(obj.aniEase);
 
//E. if destination has been reached, remove tween from array and call function.
if(Math.round(tempVal) >= obj.propValue){
tempVal = obj.propValue;
 
//remove tween
removeTween(obj.aniObj, obj.propStr);
 
//call end function if present
if(obj.endFunction != null){
obj.endFunction();
}
}
// apply the tempVal to the object property. By setting the value in this way,
// we are able to tween any property using the same code
// Example: (boxMC["_x"] = 200; will set the _x property of a MovieClip instance
// called "boxMC" to 200.
obj.aniObj[obj.propStr] = tempVal;
}
else{ // same as above except using subtraction.
obj.aniEase > 0 ? tempVal -= obj.jump: tempVal -= (tempVal - obj.propValue) / Math.abs(obj.aniEase);
if(Math.round(tempVal) <= obj.propValue){
tempVal = obj.propValue;
 
//remove tween
removeTween(obj.aniObj, obj.propStr);
 
if(obj.endFunction != null){
obj.endFunction();
}
}
obj.aniObj[obj.propStr] = tempVal;
}
}

Now that all the stuff is done, we can initiate the engine with one line of code.

?View Code ACTIONSCRIPT
insertTween(boxMC, "_x", 360, 10, null);

To animate more properties of an object we need to add a call for each property to be animated. The following example will animate the _x, _y, and _alpha properties of a MovieClip instance called "boxMC" over 15 frames. You can change the ease values to create more interesting animations.

?View Code ACTIONSCRIPT
insertTween(boxMC, "_x", 360, 15, null);
insertTween(boxMC, "_y", 300, 15, null);
insertTween(boxMC, "_alpha", 0, 15, null);

The New Animation Class:
This was originally built in 2002, but it was too complicated to use with most projects. It has been revised a few times over the years into the latest, simpler incarnation. There are more powerful solutions out there like Tweener, but I think this is simple and light enough for most of my needs.

Features:
1. Tweens all common properties for MovieClip like: _x, _y, _width, _height, _xScale, _yScale, _rotation and _alpha.

2. Easing is not perfect code-wise, but looks and works pretty nice. Includes a Tweens class with Super Ease, ease in and ease out.

3. Simple to use.

4. Multiple instances of this class can run at the same time, not that you should need to, but it is possible.

5. This class uses an interval instead of onEnterFrame form more consistent animation across projects that are set to different frame rates. Based on 24 fps.

This version adds an argument for speed. With expanded ease functionality we needed an extra argument.

Class Usage:
The following sample will animate the _x property of a MovieClip instance named "boxMC" over twenty frames with a ease value of 80.

?View Code ACTIONSCRIPT
// import and register the Animation class.
import com.hdi.as2.Animation;
var ae:Animation = new Animation();
 
// sample call to Animation class to initiate a tween.
ae.setTrans(boxMC,350,"_x",20,80,null);
//Arguments:
//ae.setTrans(objMC:Object, propValue:Number, property:String, speed:Number, ease:Number, endFunction:Function);

In the demo below you can change the property, value, speed and ease values of each tween by updating the input fields and pressing the tween button. Ease values between 0 - 100 and -1 and -100 produce similar tweens to the standard Flash tween. Ease Values between greater than 100 and less than -100 will produce a super tween and the speed value will be ignored. Super Ease values between 103 - 120 and -103 - -120 produce the best results.

Demo

Download Source

There are a some really nice video/swf players out there already, more about here is mine. It was first built in 2005, more about thus the out-dated design, but has been upgraded with some nice features over the years.

Some of the features include dynamic colors on the LED display that can be easily updated to match a site color scheme. Dynamic video size, AutoLoad, Jpeg placeholder, cookie support, and can run standalone or loaded into your own Flash app.

Another interesting feature is a loading system that tries to figure out the client's download speed and buffer the correct amount. This works pretty well in most cases but some web servers can be unreliable when it comes to streaming video with a consistent data rate. So buffer times will very with each download.

Included are FLAs to skin the GUI and update the display logos. This is the pro version we were planning on selling, but were too busy with other projects and never got around to it.

Just a heads up, I have another video app that will be released shortly. It is very similar to my Scrollbar class, in that you do not skin it, the code wraps around artwork that you create to control flvs and audio files. That way you can go crazy with the UI design and the layout of each control. It is written in AS2 and will be coming soon, so check back.

Below is a demo and the contents of the included readme.txt file.

--------------------------------------------------------------------------------------
HD-Video Player 2.0
Created:  3/2006
Build Date: 3/7/2009
 
This full featured flv / swf video player was built to be super easy to incorporate into your existing site or Flash applications. Controls include fast forward, rewind, pause / play, volume, and scrubbing playhead.
 
Extra features:
1. Custom Colors, adjust the player colors to make it  look even more at home on your site.
 
2. Place Holder Images, the player can auto load and play or show a jpg placeholder until the user clicks the play button, saving bandwidth.
 
3. Cookies, You can set cookies so that video automatically play the first time a user comes to your site, but each time after, the video will wait for user interaction.
 
4. Custom skins and logos. You can easily change the color of the LED display of the current skin, but if you need more of a custom look, you can modify the video_bkg.fla to create your own video skin. You can also change the logos that appear while loading and play by modifying the logo.fla and logo_play.fla.
 
5. Stop video from javascript. Flash video can get stuck in the player plugin, window.document.HD_Player.SetVariable("javaCall.val",1); ,replace "HD_Player" with Player id.
 
Quick and Easy Start:
If you have an flv file, just re-name it "video.flv" and place it in the same directory as the hd_player.swf . Run the hd_player.html file and you are watching video. Or you can copy this code to your own html file and again you are watching video.
 
<!-- <object width="326" height="275" id="HD_Player" align="middle">
<param name="allowScriptAccess" value="sameDomain" />
<param name="movie" value="HD_Player.swf" />
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<embed src="HD_Player.swf" quality="high" bgcolor="#ffffff" width="326" height="275" name="HD_Player" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object> -->
 
Default 320 x 240:
OK, if your video is not supposed to be viewed at 320 x 240. Just modify the width and height attributes of the object code to the size your video plus 6 pixels for the width and 35 pixels for the height. This will allow your viewers to see the nifty controls and border.
 
*Hint:  width = video width +