Using Flash Studio Pro
In the following exercise, you'll create an enhanced standalone Flash application using Flash Studio Pro and FSCommands.Before proceeding, you need to install the Flash Studio Pro trial version (Windows only) on your computer by following these steps:
Locate the file flashstudiopro_trial_setup.exe on the CD-ROM for this book and double-click the file to open it.Follow the installer's instructions to install Flash Studio Pro.After installation, launch the application.
When launching Flash Studio Pro for the first time, you get a Flash Studio Pro tips pop-up window. Close that window. You can control a variety of Flash Studio Pro settings (see figure). The following is a brief overview of the available options and settings:
TAB | DESCRIPTION |
---|---|
Input File | Flash Studio Pro creates an executable file that holds at least one SWF file. On this tab, you specify the location on your hard drive for that SWF file. |
Style | On this tab, you can change visual properties of the file and the window in which it launches. This includes properties such as the window title, the window borders, and the icon used for the executable file. |
Size/Position | Here you can specify the size of the window and where on the screen it should position itself when launched. |
Mouse/Keyboard | On this tab, you can define how you want the window to respond to certain keypresses and mouse interactions. For example, you can set the right-click to be, ignored or to drag the window. |
Flash | This tab allows you to specify a few playback options for the Flash file, such as quality and background color. Also, you can select the option to include the Flash Player OCX with your executable file. |
Files | Flash Studio Pro gives you the option to include files, such as extra SWF files or text files, in the final executable. You can specify on this tab which files to include. |
Output File | On this tab, you specify certain properties of the executable file, such as its name, output directory, compression, and even an expiration date. |
Batch | You can specify multiple SWF files and convert them to executable files. All SWF file names entered in this tab are processed with the same options. |

Open Game1.fla in the Lesson20/Assets directory.Notice that there are five layersBackground, Assets, Top Bubbles, Actions, and Labelsas well as three frame labels (which we'll discuss in a moment). The Labels layer contains no content. It's just used to place empty frames that are given a frame label. The Background layer contains the project's background graphics. The Assets layer contains most of the remaining visual elements for the game, except for a bitmap of some bubbles on the Top Bubbles layer (this graphic was added to give the game some depth). As usual, the Actions layer will contain the ActionScript used in this project.The game that you're going to build is very simple. You move a ship left and right using the Left Arrow and Right Arrow keys. You can fire a projectile upward from the ship, using the Spacebar. Bubbles appear from the left side of the screen and move to the right. The goal is to destroy as many bubbles as you can within a certain time limit. When finished, your score is saved to a text file if you have attained a new high score.The Initial frame label will contain script to load the current high score data from a text file. Also on this label is a button that we'll use to begin gameplay. When the user clicks the button, the timeline moves to the Game label, which contains the script and assets for playing the game. After the game's time limit has been exceeded, the timeline moves to the Game Over label, where the current score is saved to a text file if the score is higher than the previously saved high score.Other than the specific FSCommands used in this exercise, all the ActionScript used in this project should be familiar from earlier lessons. There are functions, arrays, duplicated movie clips, and the hitTest() function. Instead of dissecting each script line by line, we'll focus more on what a group of code accomplishes, and in some cases how it relates to the use of FSCommands.Before we begin scripting, you should be aware of two important assets you'll use in the exercise, both of which are contained in the Lesson20/Assets directory. Both of these assets must be in the same directory as the final project file. The first asset is a text file named highest_score.txt. This file contains the variable declaration score=0. We'll explain this in a moment. The second asset is a file named mask.bmp, which is a black-and-white bitmap image that acts as a mask for the game application's window.

These actions execute an fscommand() when the resulting SWF is wrapped in a Flash Studio Pro executable file, sending the executable a command that it has been programmed to act upon. In this case, the command tells the executable file to apply the specified bitmap file as a mask to the playback window. The end result is an executable file in the shape defined by the black-and-white image of the bitmap. The command specified here is flashstudio.maskon. (All Flash Studio Pro FSCommands start with flashstudio, so the command is actually just maskon.) The second parameter of the command specifies the path to the bitmap to be used as a mask. As you can see, we've referenced the value "mask", which actually refers to the value contained in the mask variable (mask.bmp). Although variables within Flash are not referenced in scripts by using quotes, they are when using Flash Studio Pro commands. This functionality may seem strange at first, but you'll quickly become accustomed to it.
var mask:String = "mask.bmp";
fscommand("flashstudio.maskon", "mask");
NOTETo reference the path of the bitmap directly, the syntax would look like this:
Add the following script to load and display the previously saved high score:
fscommand("flashstudio.maskon", "\"mask.bmp\");
This script creates an instance of the LoadVars class and loads the contents of the highest_score.txt text file into it. When the text file is loaded, the string "Most bubbles destroyed: 37" is displayed in the score_txt text field. The number of bubbles destroyed varies depending on the current value of score in the loaded text file.The first line of the script in this step declares highscore as a variable on the main timeline. In the scoreLoaded() function, when the text file is loaded the value of score in the file sets highscore's initial value. The highscore variable is declared on the main timeline because we need to keep it around for the duration of gameplay. At the end of the game, the current score is compared to this value to determine whether a new text file containing the updated high score should be created.Add the following script for the Play button:
var highscore:Number;
function scoreLoaded() {
score_txt.text = "Most bubbles destroyed: "+ lv.score;
highscore = Number(lv.score);
}
var lv:LoadVars = new LoadVars();
lv.onLoad = scoreLoaded;
lv.load("highest_score.txt");
When the play_btn button instance is clicked, the timeline moves to the Game frame label.The final action list keeps the movie from playing automatically when the application is opened.
play_btn.onRelease = function() {
gotoAndStop("Game");
};
stop();

The ship, projectiles, and bubbles all move at their own speeds. A speed value is the amount that the object can move (in pixels) during one frame. The variables ship_speed, bubble_speed, and projectile_speed define these speeds.Arrays of projectiles and bubbles are also created, named projectiles and bubbles, respectively. These arrays store and keep track of bubbles and projectiles that are created and used during gameplay. Using arrays makes it easy to loop through the existing projectiles and bubbles to check for collisions or to remove them all from the screen.The hits variable stores the number of bubbles destroyed. The depth variable stores the current highest unused depth. The game_length variable stores the amount of time that the game lasts, in milliseconds (we set it to last 60 seconds). The shooting variable stores a value of false. These variables will be discussed later.Add the following onEnterFrame event at the end of the current script:
var ship_speed:Number = 2;
var projectile_speed:Number = 4;
var bubble_speed:Number = 3;
var projectiles:Array = new Array();
var bubbles:Array = new Array();
var hits:Number = 0;
var depth:Number = 0;
var game_length:Number = 60 * 1000;
var shooting:Boolean = false;
This onEnterFrame event executes these five functions (none of which have been created yet) for every frame:generateBubbles() creates a new bubble at a random time.captureKeyPresses() checks whether the arrow keys or Spacebar have been pressed. Depending on which key is pressed, this function moves the ship left or right, or fires a projectile.moveProjectiles() moves fired projectiles upward.moveBubbles() moves bubbles to the right.detectCollisions() loops through the projectiles and bubbles looking for collisions.
this.onEnterFrame = function() {
generateBubbles();
captureKeyPresses();
moveProjectiles();
moveBubbles();
detectCollisions();
};
Let's add these functions next and briefly discuss how they work.Add the generateBubbles() function at the end of the current script:
If random(50) evaluates to 0, a new bubble is created. Statistically this should occur once every 50 frames. When a new bubble movie clip instance is created, a reference to it is stored in the bubbles array. The generated bubble instance is given a random size by setting its _xscale and_yscale properties to values between 50 and 100.Create the captureKeyPresses() function:
function generateBubbles() {
if (random(50) == 0) {
++depth;
var name:String = "bubble" + depth;
var clip:MovieClip = bubble_mc.duplicateMovieClip(name,depth);
bubbles.push(clip);
clip._xscale = clip._yscale = 50 + random(50);
}
}
If the Left Arrow or Right Arrow key is pressed and ship_mc is within a horizontal boundary of 185 on the left and 370 on the right, the ship_mc instance is moved the amount of ship_speed in the appropriate direction. The boundary exists to prevent the instance from moving beyond the area of water in the tub.
function captureKeyPresses() {
if (Key.isDown(Key.LEFT) && ship_mc._x > 185) {
ship_mc._x -= ship_speed;
} else if (Key.isDown(Key.RIGHT) && ship_mc._x < 370) {
ship_mc._x += ship_speed;
}
if (Key.isDown(Key.SPACE) && !shooting) {
shooting = true;
shoot();
} else if (!Key.isDown(Key.SPACE)) {
shooting = false;
}
}

This function is called when the Spacebar is pressed. It creates a new projectile, positions it on top of the ship_mc movie clip instance (so it appears that the projectile is being fired from the ship), and adds a reference to the new projectile in the projectiles array.Now create the moveProjectiles() function:
function shoot() {
++depth;
var name:String = "projectile" + depth;
var clip:MovieClip = projectile_mc.duplicateMovieClip(name, depth);
clip._x = ship_mc._x;
clip._y = ship_mc._y;
projectiles.push(clip);
}
At this point in the book, you're used to seeing for loops; however, this is the first time that we've used a for loop to count backward. This function serves two purposes: moving any projectiles that have been created as a result of the user pressing the Spacebar, and removing the projectiles if they get too high on the screen.This loop processes every projectile instance referenced in projectiles array. With every iteration, each instance referenced in the array is moved up on the screen by the amount of projectile_speed. If the y position of the currently referenced movie clip instance goes past 40, the instance is removed. The instance is removed in two steps: it's physically removed from the screen by using the removeMovieClip() method; then the reference to the instance in the projectiles array is deleted, using the splice() method of the Array class.You may wonder why this particular loop call requires i to be counted backward (--i). Think of the references to projectile instances in the projectiles array as a stack of nine books, with the book at the bottom of the stack having an index value of 0, and the topmost book having an index value of 8. Now suppose you're given the task of removing the books at positions 1 and 4. If you remove the book at index 1, the remaining books on top of that book drop down one position; the book that was formerly at position 2 is now at position 1, the book that was at position 3 is now at position 2, and so on. This creates a problem when you remove the book at position 4, because it has been dropped to position 3. Removing the book at position 4 actually results in removing the book that was formerly at position 5. The book that was originally at index 4 is skipped altogether.
function moveProjectiles() {
for (var i:Number = projectiles.length - 1; i >= 0; --i) {
var clip:MovieClip = projectiles[i];
clip._y -= projectile_speed;
if (clip._y < 40) {
clip.removeMovieClip();
projectiles.splice(i, 1);
}
}
}


This function works like moveProjectiles(), except that it handles the movement and deletion of bubble instances. These are moved to the right at the rate of bubble_speed, and removed when they've breached the rightmost boundary of the project.Next, create the detectCollisions() function:
function moveBubbles() {
for (var i:Number = bubbles.length - 1; i >= 0; --i) {
var clip:MovieClip = bubbles[i];
clip._x += bubble_speed;
if (clip._x > 550) {
clip.removeMovieClip();
bubbles.splice(i, 1);
}
}
}
This function has a nested loop. For every projectile in the projectile array, the entire bubble array is looped through and a hitTest() is performed. If hitTest() returns a value of true, a collision has occurred between the projectile being tested and a bubble instance.If a collision is detected, the hits variable is incremented, the projectile is removed, and the bubble is removed from the bubbles array. The bubble is told to play a "bursting" animation. The final frame in the bubbles_mc movie clip has an action assigned, this.removeMovieClip(), that removes the bubble clip as soon as the bubble has burst.The final action that occurs if a collision is detected is the execution of the FSCommand. shake. The shake command tells the executable to shake the playback window the number of times listed as the second parameter. When a collision is detected, the playback window shakes five times.Create the gameOver() function to handle ending the game:
function detectCollisions() {
for (var i:Number = projectiles.length - 1; i >= 0; --i) {
var projectile_clip:MovieClip = projectiles[i];
for (var j:Number = bubbles.length - 1; j >= 0; --j) {
var bubble_clip:MovieClip = bubbles[j];
if (projectile_clip.hitTest(bubble_clip)) {
++hits;
projectile_clip.removeMovieClip();
projectiles.splice(i, 1);
bubbles.splice(j, 1);
bubble_clip.play();
fscommand("flashstudio.shake", "\"5\");
}
}
}
}
The last line of script shown here uses setInterval() to tell the gameOver() function to execute after the game has been played for one minute, which is the length of time specified in the game_length variable created in Step 7.When executed, the gameOver() function takes four actions: It first clears the interval so that the gameOver() function is not called again in another 60 seconds. Then it uses a couple of looping statements to loop through and remove any outstanding projectile and bubble instances. Finally, it sends the movie to the Game Over frame label.Move the playhead to the Game Over frame label.This frame contains the text showing that the game has ended. There is also a button named playagain_btn that moves the timeline back to the Initial frame so that the game can be played again.No ActionScript will actually be assigned to this frame; rather, it will be assigned to the next frame because of the FSCommands used. Typically, when these FSCommands are placed on a frame, they're executed before the visual content of the frame is rendered. Therefore, execution of FSCommands on the Game Over frame label technically occurs while the user still sees the content of the Game label (albeit just for a split second). By putting these commands on the next frame, we let the visual content of the Game Over frame label render on the screen first, before the execution of the commands.Select the frame in the Actions layer directly after the Game Over frame label and add the following script:
function gameOver() {
clearInterval(gameID);
for (var i:Number = projectiles.length - 1; i >= 0; --i) {
var clip:MovieClip = projectiles[i];
clip.removeMovieClip();
projectiles.splice(i, 1);
}
for (var i:Number = bubbles.length - 1; i >= 0; --i) {
var clip:MovieClip = bubbles[i];
clip.removeMovieClip();
bubbles.splice(i, 1);
}
gotoAndPlay("Game Over");
}
var gameID:Number = setInterval(gameOver, game_length);
Both Windows 2000 and Windows XP come with a speech pack built in, allowing them to render strings of text to voice. This script formats a dynamic message and has Windows play the message using the flashstudio.say command. The second parameter of this command specifies a variable whose value is the text to speak.
if (hits != 1) {
var message:String = "Game Over! You destroyed "+ hits + "bubbles!";
} else {
var message:String = "Game Over! You destroyed " + hits + "bubble!";
}
fscommand("flashstudio.say", "message");
NOTEIf you're testing the game on a Windows 98 or Windows 95 machine (which doesn't have a built-in speech engine), don't include this portion of script, or you'll get an error at the end of the game.Add the following script to handle saving a high score:
At the end of the game, this conditional statement compares the value of hits (the number of bubbles hit) with the value of highscore (which is the current high score, as discussed in Step 4). If hits has a greater value, a new high score has been achieved and needs to be saved. The savetofile command saves the new score to a text file, which is loaded at the beginning of the next game.The savetofile command accepts two parameter values, separated by commas. The first line within the conditional creates a variable named saveTo, which represents the name of the target text file. The second line creates a variable named saveContent, which contains the text that will be saved. The value of this variable is created by adding the string "score=" to the value of hits. If hits has a value of 53, for example, the text score=53 is written to the highest_score.txt file, overwriting any existing text in the file.Add the following button event handler and stop() action at the end of the current script:
if (hits > highscore) {
var saveTo:String = "highest_score.txt";
var saveContent:String = "score=" + hits;
fscommand("flashstudio.savetofile", "saveTo, saveContent");
}
playagain_btn.onRelease = function() {
gotoAndStop("Initial");
};
stop();

NOTEThis step assumes that the default publish settings are used.With Flash Studio Pro open, select the Input File tab. At the bottom of the tab is the option Please Select an Input SWF. Use this option to browse to and select the Game1.swf file on your hard drive.

