29.11.09

Flex 3 / AS3 : Save User Interface for Games

Source Code:
The commented code for this save interface can be found here.

Introduction:
I'm currently in the process of developing using the Pushbutton Engine, and it's going to be a long time before I can write a tutorial on the ideas/process involved in creating the save interface, so I've decided to just present a tutorial for using it in this post. Also if , if version 1.0 of Pushbutton Engine still doesn't have support specifically for savedata I will port this code to be compatible with the component framework.

Rundown of Classes:
  • ISaveState : This is the interface that should be implemented by objects that you intend to use as save states.
  • ExampleSaveState : An example implementation of ISaveState, used for the demo in Main.mxml.
  • SaveManager : This class contains the code for saving and loading.
  • Main.mxml : A messy, poorly labeled, but functional demonstration of the features of SaveManager.
Features of SaveManager:
  1. Ability to save objects to local storage.
  2. Ability to enumerate and load objects from local storage.
  3. Ability to delete objects from local storage.
  4. AutoSave/Load/Delete feature that allows the class to be used without a user interface.
  5. Multiple save slots, with a code specified max number of slots.
  6. Alerts to handle user confirmation for overwrites and deletes.
  7. Data displayed adapts according to current user interface specified.
SaveManager Constructor:
  • showAlerts - Boolean determines if alerts should pop up during use saveClass. This should probably be set to false when autosave is used so that the "Confirm Overwrite" dialog doesn't pop up.
  • saveClass - Class representing the class of the saved data. This is required by actionscript serialization so that the object can be successfully serialezed / deserialized from a SharedObject. Without it casting would throw type errors because type info would be lost.
  • targetSave - The object you will be saving if this instance is going to be used for saving, can also be set later using targetSaveState()
  • slotList - A component that extends the flex ListBase class. This parameter will be used for displaying the save slots.
  • saveButton - A button that will cause a save to the currently selected slot, or the autosave slot if no slot is selected.
  • loadButton - A button that will load the currently selected slot, or the autosave slot if no slot is selected.
  • deleteButton -A button that will delete the currently selected slot, or the autosave slot if no slot is selected.

Dynamic UI:
The UI adjusts depending on which component parameters are set to null.

  1. If slotList is null, only the autoSave save slot will be available to the buttons, because there is no way to select a save slot.
  2. If saveButton is null, the Create New Save... entry won't appear in the slotlist.

Demonstration:
Main.mxml defines a bunch of controls that demonstrate the SaveManagerClass.

  1. The top row of buttons determines which features are available in the current SaveManager. Clicking buttons will hide or show controls according to their nullity.
  2. The first list shows all of the save states.
  3. The save button will save the "create save info" text fields to the currently selected slot (or autosave slot).
  4. The load button loads the currently selected (or autosave) slot.
  5. The delete button deletes the currently selected (or autosave) slot.
  6. The three text inputs are for creating save data members to demonstrate saving.
  7. The data grid shows the object currently stored in targetSaveState of the SaveManager (it will change when slots are loaded)

Usage Notes:
ISaveState.as
- Implementing classes must have a parameterless constructor in order for serialization to work.

The commented code for this save interface can be found here.

5.8.09

AS3: How to Create a Cancelable Event

How to Create a Cancelable Event

Explanation:
The easiest way to explain a cancelable event is by example. Hopefully the following movie loads. In case it doesn't, following is a description:

  • There is a TextField which displays "Points Available: 5". The 5 represents an int in code that keeps track of the points available.
  • There are two Spinners (Spinners spinners are a text field that displays a number, and a right and left arrow button to increase or decrease the number displayed). Both Spinners start with the value "0". The available points can be distributed to the Spinners.

These two behaviors are achieved using cancelable events:

  1. When a Spinner is at 0 it can no longer be decreased.
  2. When there are 0 points available the Spinners can no longer increase.




Creating the Spinner:

Creating a cancelable event begins in the class which dispatches the event. In this case that is the Spinner class with its "SCROLL_RIGHT" and "SCROLL_LEFT" events. In this code _btnLeft and _btnRight are Buttons with their position relating to Left and Right. I won't run through the code for laying out the buttons and textfield, but if you don't know how to do it, you can download the full source at the end of this tutorial and read comments. This code goes in the Spinner class:

    private function addEventListeners():void
{
// Event called when left button is clicked
_btnLeft.addEventListener(MouseEvent.CLICK, startLeftScroll);
// Event called when right button is clicked
_btnRight.addEventListener(MouseEvent.CLICK, startRightScroll);
}pre>


addEventListeners() is called once, at the creation of the Spinner class. It sets up event listeners for when the Left and Right Buttons are clicked. These clicks will cause the Spinner class to dispatch SCROLL events, as shown in the following code:
private function startRightScroll(e:Event):void
{
// Add a listener for the dispatched event to allow cancel
// behavior.
addEventListener("SCROLL_RIGHT", endRightScroll);

// Dispatch the event
dispatchEvent(new Event("SCROLL_RIGHT", false, true));
}

private function startLeftScroll(e:Event):void
{
// Add a listener for the dispatched event to allow cancel
// behavior.
addEventListener("SCROLL_LEFT", endLeftScroll);

// Dispatch the event
dispatchEvent(new Event("SCROLL_LEFT", false, true));
}


In the previous code, an event listener is added for the event that is about to be dispatched. It is important to do things in this order so that the Spinner class is the last object to be notified about a SCROLL event, giving the other classes a chance to mark the event as cancelled. It is also important to note that when dispatching the events, the "cancelable" parameter is set to "true". Finally the code that actually controls if the behavior occurs or not is contained in the endLeftScroll() and endRightScroll() methods.
public function endRightScroll(e:Event):void
{
// Remove the event listener
removeEventListener("SCROLL_RIGHT", endRightScroll);

// If the default behavior hasn't been cancelled
if (e.isDefaultPrevented()==false)
{
// Increase the value and refresh the textbox
_value += 1;
updateValue();
}
}

private function endLeftScroll(e:Event):void
{
// If the default behavior hasn't been cancelled
if (e.isDefaultPrevented()==false)
{
// Decrease the value and refresh the textbox
_value -= 1;
updateValue();
}
}



In these methods, A call is first made to removeEventListener(). As previously mentioned, this is done because you want to add a new event listener each time the event is dispatched, so that the Spinner object will always be the last object to get notified of the SCROLL event. The next thing to check is e.isDefaultPrevented(). If the event has been canceled, that means another class has called e.preventDefault(), which will mark isDefaultPrevented() as "true". So if isDefaultPrevented() == false, then you complete the default behavior of the event. In this case, the response to the behavior being cancelled is to just exit the method without making any changes.

Canceling the Event:

The spinner class has now been created in a way which will allow the SCROLL_RIGHT and SCROLL_LEFT events to be cancelled, all that remains is to create the code which cancels them when necessary. In the Main class _spinner1 and _spinner2 are Spinner instances, and _points is the number of points available to be distributed. After creating the controls, addEventListener() is called on the Spinners as follows:

   private function addEventListeners():void
{
// Listen for left or right scrolling on spinner 1
_spinner1.addEventListener("SCROLL_RIGHT", pointAdded);
_spinner1.addEventListener("SCROLL_LEFT", pointSubtracted);

// Listen for left or right scrolling on spinner 2
_spinner2.addEventListener("SCROLL_RIGHT", pointAdded);
_spinner2.addEventListener("SCROLL_LEFT", pointSubtracted);
}


Next pointAdded and pointSubtracted are created with if conditions which determine if the SCROLL events should be cancelled:

private function pointAdded(e:Event):void
{
// If there are points availiable
if (_points > 0)
{
// Subtract a point and update the text
_points -= 1;
updateText();
}else {
// If there are no points available
// prevent the default behavior of the
// event (cancel it).
e.preventDefault();
}
}

private function pointSubtracted(e:Event):void
{
// If the spinner value is higher than 0
if (Spinner(e.target).value > 0)
{
// Make a point available and update the text
_points += 1;
updateText();
}else {
// If the spinner is at 0
// prevent the default behavior of the
// event (cancel it).
e.preventDefault();
}
}



The zipped source code to this tutorial can be found here.

If you have comments / questions / suggestions, let me know, this is my most complicated tutorial currently and I'm trying to work on making it more clear, thanks in advance for any input.

25.7.09

AS3: Basic Testing With FUnit in FlashDevelop

Basic Testing With FUnit

Testing is an often overlooked, but important part, of developing reliable applications (in any language). In this tutorial I will cover a very basic setup of FUnit in the FlashDevelop environment. I decided to make this blog because I couldn't find a reliable tutorial for the version of FUnit (0.70.0410), probably because it is in alpha stages.

What You Need:

  • FUnit: You can find it here. As of the time I'm writing this it is still in alpha. The FAQ page does say it is generally follows NUnit for structuring, so hopefully this tutorial will remain useful in the future versions.
  • FlashDevelop and Related Files: If you don't have FlashDevelop set up for programming yet, check out this tutorial.


Purpose of Unit Testing:

The goal of testing is to guarantee the accuracy of your code. The basic idea is that you pass known arguments to each of your methods, and compare values to the output and affected objects to see if each method behaves correctly.

FUnit Classes:

The basic classes of FUnit that will be dealt with in this tutorial are:

  1. TestSuite - This will load the tests in your classes in order to put them together so the TestRunner can run them.
  2. TestRunner - This is the class that actually runs your tests and returns the output. There are a few types of TestRunner's, but the only one that will be dealt with in this tutorial is "funit.core.TestRunner"
  3. DebugTestListener - This class gives a readable debug output of your test results. There are other graphical TestRunners that could eliminate the need to use this class, but as far as I can tell the graphical output is under heavy development and I don't want this tutorial to be outdated a day after I finish it.

User Created Classes:

  1. Main - The Main class created by FlashDevelop when you make a new AS3 project.
  2. ProjectTestSuite - This class will create a collection of all tests to be run by the TestRunner.
  3. BasicClass - This class will have a method that does a basic operation which we will test.
  4. BasicClassTest - This class will contain the tests for BasicClass.

Preparing the Project:

  1. Setup the project properties so that the debug output will display correctly. This may not always be necessary, but with FUnit 0.70.0410 and FlashDevelop 3.0.2 RTM it is. For some reason when they movie is loaded as a document in FlashDevelop the debug output never happens, so you have to change it to play externally. To change how the movie is played, click Project > Properties..., set Platform target to Flash Player 10, and change the "Test Movie" dropdown menu to "Play in external player".
  2. In order to use FUnit, FUnit.swc needs to be placed somewhere in the project (I put it in lib\FUnit). Next in FlashDevelop Project window, right click FUnit.swc and select "Add to Library". Now all of the classes of FUnit should be available in your project.
Making a Test Suite:

In my opinion, the easiest way to make sure all of your tests get run, is to make a Test Suite of your own.

  package
{
import funit.core.TestSuite;

public class ProjectTestSuite extends TestSuite
{

public function ProjectTestSuite()
{
// Add the Basic Test Class tests to this suite.
add(BasicClassTest);
}

}

}

To create the TestSuite, you simply create a class that extends TestSuite. In order to specify which tests the suite contains, make calls to add() with all of the classes containing tests as arguments.

Creating The Test Class:
Ideally unit tests should be created before the classes they test. In theory, creating tests that guarantee your program is functionally sound, and then passing them all by coding the program should create a functionally sound program. If you code first it's much easier to accidentally create code that is difficult to test, or tests that use knowledge about how the code works, which doesn't neccessarily check functionality.

The class to be tested in this tutorial will have only 2 methods. add(a:int, b:int):int and getLastResult():int. add() will add two numbers, store their result in a private class var, and return the result. getLastResult() will return the last result determined by the object.

Some points to consider about how these methods will work:

  1. If getLastResult() is called before add() is called for the first time, it throws an error.
  2. After a call to add(), the number returned, getLastResult() and the sum of the arguments added, should all be equal.
  3. After a second call to add() getLastResult() should change to reflect the result of the second call.

There are definitely more thing that could be tested for in this class, but I feel like these three major point should take away most of the chance for problems to occur. Each of these seperate situations should be its own test, resulting in the following code:


 package
{

import funit.framework.Assert;

[TestFixture]
public class BasicClassTest
{

// This object will be used by each test method
private var testObject:BasicClass;

public function BasicClassTest()
{

}

/**
* This method will reset testObject to the new
* instance each time a new test is run.
*/
[SetUp]
public function setup() : void
{
testObject = new BasicClass();
}

/**
* Tests calling getLastResult() before there is
* any result.
*/
[Test]
[ExpectedError("Error")]
public function testadd_error() : void
{
// Make an illegal call to getLastResult()
testObject.getLastResult();
}

/**
* Tests the functionality of add() and getLastResult()
*/
[Test]
public function testadd() : void
{
// Test the add and getLastResult() functions
Assert.areEqual(10, testObject.add(3, 7));
Assert.areEqual(10, testObject.getLastResult());
}

/**
* Tests the functionality of add() and getLastResult()
*/
[Test]
public function testadd_twice() : void
{
// Test the add and getLastResult() functions
testObject.add(3, 7);
Assert.areEqual(17, testObject.add(8, 9));
Assert.areEqual(17, testObject.getLastResult());
}
}

}

FUnit code line by line:

  • 6. [TestFixture] is metadata that FUnit uses to process this class (essentially as if it were extending the class TestFixture). It is necessary on classes like this, intended to be included in a suite.
  • 11. An empty instance of our class to be tested, this is used later in the code.
  • 22. [SetUp] This metadata tells the TestRunner to run this method before each test is run. The running order would be setup() ... test ... setup() ... test ... setup() ... etc. It will be used for each test in this class.
  • 25. testObject = new BasicClass() Before each test is run, this will place a new instance of BasicClass in testObject. This is useful because it means you won't have to create BasicClass individually somewhere in each of your tests. A note about using private members in tests: It is bad coding to have tests that rely on the results of other tests. This is importantly because many testing api's do not guarantee the order your tests will be run in.
  • 32. [Test] This tells FUnit that this method is a Test method. You will see it above each method that is used to test.
  • 33. [ExpectedError("Error")] This means that we expect an error of class Error to occur during this method call. If an error does not occur, then the test will fail.
  • 37. testObject.getLastResult() This is an illegal call because add() has not been called previously on the testObject instance. This should cause an error to be thrown and the test to pass.
  • 47. Assert.areEquals(10, testObject.add(3, 7)) This is the heart of most unit testing. It checks the equality of the number 10, and the value returned from the add function. If they are equal then the test passes, otherwise it fails. Assert contains a number of other ways to compare objects and primitives that can all be viewed in the FUnit documentation.
  • 48. This line guarantees that the getLastResult() function returns correctly after add() has been called.
  • 59. This line calls add() for the second time in this method.
  • 60. This line guarantees that the value of getLastResult() has been correctly updated after the second call to add().

Creating the class:

Now that the test is coded, the defined behavior can be used to write the actual class. There is nothing special about this class so I am just going to post it assuming that if you are dealing with testing, you understand AS3 well enough to make a simple class:


 package
{

public class BasicClass
{

private var lastResult:int = 0;
private var initialized:Boolean = false;

public function BasicClass()
{

}

/**
* Adds two numbers and puts the result in lastResult
* @param a number 1
* @param b number 2
* @return a + b
*/
public function add(a:int, b:int):int
{
// add() has been called so set initialized to true
initialized = true;
// Save the sum
lastResult = a + b;
// Return the sum
return lastResult;
}

/**
* Get property
*
* @return The last sum calculated by this instance.
*/
public function getLastResult():int
{
// If add() has not been called, throw an error
if (initialized != true)
{
throw new Error("An addition has not previously occurred");
}
// Otherwise return the last sum
return lastResult;
}

}

}

Get it running:
All that is left is to start up the TestRunner in the Main class and run the movie in debug mode. Following is the line by line:

 package
{
import flash.display.Sprite;
import flash.events.Event;
import funit.core.TestRunner;
import funit.listeners.automation.DebugTestListener;

public class Main extends Sprite
{

public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}

private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
// Run the tests
runTests();
}

private function runTests():void
{
// Create a new TestRunner which will run the tests
var runner:TestRunner = new TestRunner();
// Create an instance of our test suite
var suite:ProjectTestSuite = new ProjectTestSuite();
// Load the suite into the runner
runner.load(suite);
// Run the loaded suite and output the results to Debug
runner.run( new DebugTestListener() );
}

}

}
  • 1-23. All standard FlashDevelop AS3 loading stuff, check here if you don't understand it.
  • 28. Create a new TestRunner (The class that actually runs the tests)
  • 30. Create an instance of the suite we created.
  • 32. Load our suite (Which thereby loads all tests added to the suite) into the test runner.
  • 34. Run the tests. The argument "DebugTestListener()" is an FUnit class which causes the results of the test to be shown in the Debug Console. For information on other forms of output, read the updates on the FUnit site.

Hopefully you've got everything working... if not, the source for this project can be found here.

Feel free to contact me with any comments or suggestions.

12.5.09

AS3: Dynamically Loading Sounds in FlashDevelop

Dynamically Loading Sounds in FlashDevelop

Dynamically loading sounds in an AS3 movies allows you to store files seperately from your movie. Depending on where and how your sound is stored there may be significant time involved in loading it. Another method of using sound in your movie by embedding it directly into your movie can be found here.

The Set Up:

  • Either upload sound to your own webspace, or find the address to one online to use for testing. The sound must be formatted as a mp3 to be loaded into a movie.
  • Create a new AS3 project space in FlashDevelop.

Non-blocking image load:

  • ... Non-Blocking?:
    Loading an image without Blocking means that while the sound is being loaded, code continues to run. This is a problem if the application demands that the sound plays immediately when you call Sound.play(). However, blocking sound loading takes some foresight in AS3, and non-blocking sound loading is adequate for many situations. If you need your sound to play immediately when you call Sound.play() and are using this method, make sure you give your sound adequate time to load before calling play().

The Code:

   // entry point
var loadedSound:Sound = new Sound(new URLRequest("http://sites.google.com/site/programmingetc/Home/sploosh.mp3")); // Begin loading sound from the web
loadedSound.play(); // Sound will play after it has finished loading.
Line By Line:


  1. Lines up with the "//entry point" comment that should be in the default as3 project in FlashDevelop.
  2. Create a sound object. By providing it's constructor with a URLRequest, it will begin downloading the sound immediately, alternately you could call loadedSound.load(URLRequest).
  3. Play the sound. Techinically this queue's it up to be played once it is finished loading.

.zip source for this project can be found here

11.5.09

AS3: Embedding Sounds in FlashDevelop

Embedding Sounds in FlashDevelop


Embedding sounds in an AS3 movie will give fast access with no preloading. As an alternative, the same sounds can be used in multiple movies. In order to update sounds without rebuilding your project, or to save space by using the same images in multiple movies, you may want to also check out a tutorial on how to load sounds from an external source here.

The Set Up:
  • Get yourself a soundclip. Flash supports many types of embedded sound including:

  • AAC, AIFF, MP3, AVI, WAV, AU

  • Create a new AS3 project space in FlashDevelop.

  • Right click on your "src" folder, in the dropdown menu click "add >> new folder"

  • Change the name of your New Folder to snd.

  • Now add your soundclip to the project in one of two ways:

  • A) Find your soundclip in the windows filesystem and drag it directly into your project and drop it on your "snd" folder.

  • B) Right click the "snd" folder, click "add >> existing item", select the soundclip you want to add.

Note: Creating the "snd" folder is not necessary, it is just good to get in the habit of organizing your projects. Alternately you could just store everything directly in the "src" folder.


Getting your image in the movie:

  1. Add the Embed tag:
    You need to create an embed tag in order to make your soundclip accessible to the movie:
    [Embed(source='snd/sound.mp3')]
    "snd" corresponds to the folder the clip is stored in, and "sound.mp3" should be replaced with the name of your file.


  2. Create a class for the Embed tag:
    In order to use the embed tag, a class variable must be defined directly below it. This class variable is instantiated to create the embedded sound. The signature of a variable used for embedding can vary, the example below is a class variable and should be added after the opening brackets of your class, before any function definitions:
    [[Embed(source='snd/sound.mp3')]

    private const embeddedSound:Class;

  3. Create an instance an embedded sound:
    In order to create a useable object from a soundclip class, you simply create a new instance if the soundclip's class, and cast it to an instance of Sound. This code should go after the //entry point comment in your AS3 project.
    var soundClip:Sound = new embeddedSound(); // Create an instance of the embedded sound

  4. Play the sound:
    All that is left is to play the sound. This code can be inserted directly below the code from step 3:
    soundClip.play(); // Play the sound

.zip source for this project can be found here

AS3: Dynamically Loading Images in FlashDevelop

Dynamically Loading Images in FlashDevelop with AS3

Dynamically loading images in an AS3 movies allows you to store images seperately from your movie. Depending on where and how your image is stored there may be significant time involved in loading an image. Another method of using images in your movie by embedding them directly into your movie can be found here.

The Set Up:
  • Either upload an image do your own webspace, or find the address to one online to use for testing. The image must be formatted as a gif, jpg, or png.
  • Create a new AS3 project space in FlashDevelop.

Non-blocking image load:

  • ... Non-Blocking?:
    Loading an image without Blocking means that while the image is being loaded, code continues to run. This is a problem if the application demands that the image displays immediately after you call addChild(). However, blocking image loading takes some foresight in AS3, and non-blocking image loading is adequate for many situations. Blocking image loading will be covered in a future tutorial.

The Code:

// entry point
var imgInstance:Loader = new Loader(); // Create a new loader object
imgInstance.load(new URLRequest("http://sites.google.com/site/programmingetc/Home/image.png")); // Begin loading the image from web
addChild(imgInstance); // Display the image
Line By Line:

  1. Lines up with the "//entry point" comment that should be in the default as3 project in FlashDevelop.
  2. Create a loader object. It will be used to load the image, and can also be used as a DisplayObject for displaying the loaded image.
  3. Call the load method, with a URL parameter that points to an image (hosted on my google webspace).
  4. Add the loader instance to the sprite. The image will be displayed when it loads.

.zip source for this project can be found here

9.5.09

AS3: Embedding Images in FlashDevelop with AS3

Embedding Images in FlashDevelop with AS3

Embedding images in an AS3 movie will give faster access to images without preloading. As an alternative, the same images can be used in multiple movies. In order to update images without rebuilding your project, or save space by using the same images in multiple movies, you may want to also check out a tutorial on how to load images from an external source here.

The Set Up:

  • Get yourself an image. I haven't found a definite confirmation of formats supported for embedding anywhere, but from personal use I know "gif/jpg/png/svg" filetypes are supported. SVG is a vector graphic file, which I used Inkscape (a free open source vector art program) to create.
  • Create a new AS3 project space in FlashDevelop.
  • Right click on your "src" folder, in the dropdown menu click "add >> new folder"
  • Change the name of your New Folder to img.
  • Now add your image to the project in one of two ways:
  • A) Find your image in the windows filesystem and drag it directly into your project and drop it on your "img" folder.
  • B) Right click the "img" folder, click "add >> existing item", select the image you want to add.

Note: Creating the "img" folder is not necessary, it is just good to get in the habit of organizing your projects. Alternately you could just store everything directly in the "src" folder.

Getting your image in the movie:

  1. Add the Embed tag:
    FlashDevelop makes it easy to generate the necessary code to embed images. Place the typing cursor on an empty line above your main function. Next, in the Project View, right click on your image and click "Insert Into Document". FlashDevelop should add something like this at the cursor:
    [Embed(source='img/image.png')]
  2. Create a class for the Embed tag:
    In order to use the embed tag, a class variable must be defined directly below it. This class variable is instantiated to create the embedded image. The signature of a variable used for embedding can vary, the example below is a class variable and should be added after the opening brackets of your class, before any function definitions:
    [[Embed(source='img/image.png')]
    private const embeddedImage:Class;
  3. Create an instance an embedded image:
    In order to create a useable object from an image class, you simply create a new instance if the image class, and cast it to an instance of DisplayObject. This code should go after the //entry point comment in your AS3 project.
    // entry point
    var imgInstance:DisplayObject = new embeddedImage();
  4. Display the image:
    All that is left is to display the image. The position and rotation can be adjusted first, or they can be left to default (zero). This code can be inserted directly below the code from step 3:
       imgInstance.x = 50; // Set x coordinate of image
    imgInstance.y = 45; // Set y coordinate of image
    imgInstance.rotation = 45; // Set rotation to 45 degrees
    addChild(imgInstance); // Add this image to the Sprite object

.zip source for this project can be found here

4.5.09

AS3: Hello World Movie

First AS3 Movie: Hello World

This is a guide to making a quick Hello World app in FlashDevelop with ActionScript 3. This tutorial assumes you have FlashDevelop up and running, and a default ActionScript 3 project open, ready to build and run. If not check this tutorial for instructions on how to get there.

Building on the last tutorial, this is a very simple addition.



   // entry point
var textField:TextField = new TextField(); // Create a new TextField object
textField.text = "Hello World"; // Assign the text property of the field
addChild(textField); // Add the TextField to this Sprite

Breaking it down line by line:



  • Declaring and assigning a TextField:
       var textField:TextField = new TextField(); // Create a new TextField object
    This statement declares a TextField type variable named textField. The syntax for declaring a variable is: var variableName:variableType; Declaring a variable just tells the program to prepare for the existence of an object. If you try to do anything with an unassigned variable other than assign it to something, or check if the variable is null, you will get some kind of null object error. The way the variable is assigned above is just for convenience, it could also be done using:
       var textField:TextField; // Declare a new TextField variable
    textField = new TextField(); // Assign the variable to an object


  • Setting the text to be shown:
    textField.text = "Hello World";    // Assign the text property of the field

    This statement assigns the "text" property of the textField object to "Hello World". The "text" field contains the string that the TextField will draw to the stage. "Hello World" is surrounded by double quotes, which makes it a string in AS3.

  • Adding the TextField object to be drawn:
       addChild(textField);      // Add the TextField to this Sprite
    addChild(parameter) is a method that makes the object you used as a parameter a child of the drawable object that used the method. This means that textField is now a child of Main, and when Main draws, so will TextField (unless it's "visible" property is set to false). The class you are using extends the class "Sprite" so although you don't see the function addChild() defined anywhere in your code, it is a member of your class through its superclass.

  • Note:If you copy this instead of typing it in and using the autocomplete feature you will have to add this line up by your other imports to use the TextField:
    import flash.text.TextField;

Now build your project and run, you should now see the words "Hello World" in the top left corner of your window.

.zip source code for this project can be found here.

Tutorials on the Basics:
Embedding an Image
Dynamically loading an Image
Embedding and Playing Sound
Dynamically loading and Playing Sound

3.5.09

FlashDevelop: AS3 FlashDevelop Default AS3 Project

AS3 FlashDevelop Default AS3 Project

Time to explain what all that automatically created code in Main.as means. This tutorial assumes that you already have FlashDevelop up and running, and able to compile and run ActionScript 3. If you aren't at this point, check out my previous post.

This tutorial is really beginner programming info, If you already understand the code in Main.as, you can just scan, or skip to the next tutorial.

This is how Main.as looks initially:


package
{
import flash.display.Sprite;
import flash.events.Event;

/*
*
* ...
* @author your name
*/
public class Main extends Sprite
{

public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}

private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
}

}

}



  • Basic syntax info:
    Blocks of code are opened and closed using { and }. The general format is "Statement { code; }". In AS3 blocks without a statement essentially do nothing because there is no block level scope for variables. If you don't what that means don't worry about it yet.

Breaking it down line by line:

    • Package:
      package
      You'll see this in all classes, it can be used for organizing your code. Unless you are planning on releasing your code to the public, or are creating an organized library for yourself, you can generally leave the package as is. One other point, your package must reflect your file system, so for example flash.display.Sprite would have to be in the path "..\src\flash\display\" and have the classname "Sprite".


    • Import:
       import flash.display.Sprite;
      import flash.events.Event;
      These statements make the Sprite class, and Event class accessible to your class. In flash you must import all of the classes you intend to use. You shouldn't have to worry about import too much because code completion in FlashDevelop automatically adds necessary import statements for you when you use it.


    • Documentation Comments:
       /*
      *
      * ...
      * @author your name
      */
      Commented lines. This is a specific type of comment meant to be used by a documentation generator. It is opened with /** and closed with */. If you type "@" on one of the comment lines, autocomplete will pop up and give you a bunch of tag options. These tags will be displayed in specific ways if you generate documentation. Even if you don't feel like setting up documentation for your class/project, it's still a good idea to put in a description of what the class is supposed to do where the "..." is to help you understand your code if you come back to it.


    • Declaring the class:
       public class Main extends Sprite
      This declares the class you are making. "public" means this class is accessible to any other class that wants to use it. "class" is a keyword labels the contents of the related code block as a class. Main is the name of your class. Quick side note about names, in AS3 public classes must be created inside files that match the name of the class, this is why our class "Main" is declared in the file "Main.as". If you screw this convention up, really it's ok because FlashDevelop gives you a nice descriptive error. "extends Sprite" declares this class as a subclass of Sprite. What this means is that our class will essentially be a Sprite, with whatever we code added to it. If you don't know about subclasses and inheritance yet, it might be wise to google "class inheritance" and "polymorphism".


    • Declaring a constructor:
        public function Main():void
    • This is the function that will be called when the Main class is used to create an object. Constructors will generally be declared public, unless you are making an abstract or static class, which isn't in the scope of this tutorial. function is a keyword that labels the related code block as a function. Main is the name of the function. In this case, the name must match the name of the class, which is what makes it a constructor in AS3. ( and ) are a space for parameters, but there are none to this constructor. Finally :void tells AS3 that this function does not return a value when called.


    • Class creation code:
      if (stage) init();
      else addEventListener(Event.ADDED_TO_STAGE, init);
    • This is an if-else statement. It first checks if this object's stage has been defined. This is somewhat like the _root of AS2, it is basically the main drawing area of a movie. If the stage exists in this object, then your code begins running the init() function. If not, addEventListener makes this class wait until it has been added to the stage, at which point it will call init. addEventListener arguments are the event time, and then the name of the method the event should call when it occurs.


    • Declaring an initialization function:
      private function init(e:Event = null):void
    • This function will be called either by the Main function, or the EventListener that the main function creates. It is private because it should only be called from within the Main class. The parameter e:Event = null declares a parameter named e, that is of the type Event. It is assigned to null which means that if you call init using init(); with no parameters, e will automatically be null. e is required to be there because functions called by event listeners will use the event parameter to report which event caused the function to be called. The :void means the function has no return value.


    • Coding an initialization function:
      removeEventListener(Event.ADDED_TO_STAGE, init);
    • This simply removes the event listener from this object if it was added in the constructor. This stops any potential problems of init being called by the handler again accidentally.

    • Code comments:
      // entry point
      Code comments start with a // and are terminated by a line end. They are just another way to document what your code does. Comments inside of code will not show up in documentation like the previously shown comments do.

    Final Comments:
    This default Main file works ideally for components that involve drawing. Using the init function and event listeners ensures that you don't attempt to do any drawing before your object is added to the stage. If your class doesn't require the stage you can just put your init code in the constructor and delete the init function.

    Next Tutorial, Hello World >>

    2.5.09

    FlashDevelop: Setting Up FlashDevelop for AS3 Programming

    Setting Up FlashDevelop for AS3 Programming:
    -Absolute beginner guide

    Hopefully this should be a straightforward tutorial of how to get FlashDevelop up and running your ActionScript 3 material... this tutorial was written on FlashDevelop 3.0 and Adobe Flex SDK 3.3.

    Files you need to grab:
    1. FlashDevelop at http://www.flashdevelop.org/community/viewforum.php?f=11 it's hosted in their forum I guess, not sure how long this link will be good.
    2. Adobe Flex SDK at http://www.adobe.com/products/flex/flexdownloads/ you can also get FlexBuilder from this site, I believe there is currently a month long trial before you have to buy. Lots of webpages say it is worth the money, but it's irrelevant to me because I will never have the money so I haven't tried it. Just grab the SDK if you are a cheap bastard like me.
    3. Windows Flash Player 9 or 10 Projector content debugger http://www.adobe.com/support/flashplayer/downloads.html this is optional, but you need some kind of Flash Player in order to run your movies, and this seems the best option to me because you have to deal with annoying security warnings etc if you use a Flash browser plugin to test. (The Projector is a standalone .exe).

    It doesn't matter what order you do the installations in for the current FlashDevelop (3.0) because the installer doesn't ask for any sort of SDK path.

    For SDK Install:

    1. Download the SDK http://www.adobe.com/products/flex/flexdownloads/
    2. Extract the SDK to a directory you will be able to find in the future. I went with "C:\AS3\flex_3.3.0.4852"
    3. Don't forget the location before you get FlashDevelop up and running.

    For FlashDevelop Install:

    1. Download the latest FlashDevelop http://www.flashdevelop.org/community/viewforum.php?f=11
    2. Run the installer (standard windows procedure for installing)
    3. Run the program.

    For Windows Flash Player 10 Projector content debugger install:

    1. Download the exe file from http://www.adobe.com/support/flashplayer/downloads.html
    2. Place the exe somewhere that you'll remember it. I stuck it in "C:\AS3\"

    Set Up ActionScript 3 IDE:

    1. Run FlashDevelop
    2. First you need to set your compile path, so that the SDK can compile your scripts. To do this go to Tools > Program Settings...
    3. A window titled Settings should pop up. You want to select AS3Context in the list on the left.
    4. Now in the right list under the Language category, there should be a property called "Flex SDK Location" set default to something like "c:\flex_sdk_3". You need to change this to the path where you unzipped all that Adobe Flex SDK stuff. You can open a folder browse window to make it easier by clicking on the "..." button that appears when you select "Flex SDK Location"
    5. Time to check if everything is set up correctly.

    Time to create an AS3 project and run it to see if everything is working:

    1. Click Project > New Project.
    2. Select AS3 Project in the Installed Templates List.
    3. Enter a Name for your Project
    4. This is a personal preference, but I always check "Create directory for project" because programming can quickly make a mess of your computer if you don't put atleast a little effort into organizing.
    5. If it isn't already selected, select the Project tab in the window on the right of your workspace.
    6. You should now see 3 folders: bin, lib, and src. bin will have some stuff in it to assist you in viewing/deploying your program that you don't really have to worry about right now. lib you can use later for your library files (if you use any). Currently we are concerned with the src folder. It should contain Main.as which you can double click to open in your editor window. There should be some basic framework code which I'll explain in the next tutorial, all you need to worry about now is checking if your setup works. Press F8 or click Project > Build Project To compile your empty project. The output should now flash a bunch of stuff and say "Build suceeded, Done (0)" at the end. If something else happens look at troubleshooting at the end of this blog.
    7. Now that your movie is built you can try to run it. You need to associate .swf files with the Flash Projector Debug program you downloaded earlier. In order to do this, expand your bin folder, and right click on a .swf file.
    8. Click Shell Menu... then Open With...
    9. Select the "Select a program from a list of installed programs" radio button and click OK.
    10. Click Browse... and find the Flash Projector exe file you downloaded.
    11. Check the "Always use the selected program to open this type of file box" and click OK.
    12. Now press F5 or click Project > Test Project to run your movie.
    13. The flash player you downloaded should now pop up and display a big white block. CONGRATULATIONS. Read on to the next tutorial to get yourself something a bit more impressive.

    Troubleshoot:

    Problem: When I try to build, a window pops up saying "Would you like to open the AS3 context settings to configure the compiler?"

    Solution: You probably forgot to set the Flex SDK Location property, or left it default. Check steps 2-4 under "Set Up ActionScript 3 IDE".

    Problem: When I press Test Program or hit F5 nothing happens.

    Solution: Check your output, does it say something about Execute not being related to any program? This means you didn't set up your file association correctly. Check steps 7-11 in the list right above troubleshooting.

    Explanation of the default AS3 project next >>