Flash & AS3 info, source, & experiments
ActionScript
FotB ’07, Astro (Flash Player 10), & Diesel (Flash CS4)
Nov 7th
In-spite of some personal international traveling hiccups, Flash on the Beach 2007 was an incredible conference! I learned something new or was greatly inspired at nearly every session that I attended. I’ll be covering the specifics of these sessions in greater detail in a series of future posts. However, the Adobe keynote done by Richard Galvan deserved its own post, of which I wanted to get out straight away.
Many of the new features that will be in Diesel (Flash CS4) we are already aware of from the announcements at MAX and other various places. These features include H.264 support, multi-core support, a 2.5D feature set, a new and improved text engine, full screen hardware acceleration, programmatic filters (Hydra), etc.
However, there were a couple of features & changes that I either didn’t know existed at all, or else I learned some further details that I previously did not:
- Typed arrays (vectors)
- 64-bit support
- “Mobile convergence”
- Hydra to use the GPU (if available)
- New ‘object-based’ tween model
- IK (Inverse Kinematics) Tweens
Typed arrays. Given that typed arrays are part of the newly proposed ECMAScript4 standard, I had anticipated Adobe would follow suit eventually, but I didn’t think that they were planning on including this in CS4. Given that Adobe just released AS3, I had assumed that they would not modify the language until CS5 in order to give the world a chance to catch up and not have to call code they write this year, “legacy code”, in the very next version. I’m certainly not complaining, however, as I have always believed this is something that should have been part of AS3 in the first place (right along side of the ability to have private constructors and properly implement the singleton pattern).
64-bit support. For obvious reasons, the community has been crying for flash 64-bit support for some time now. I had hoped that CS3 might support it, but am definitely relieved to hear that CS4 “officially” will.
“Mobile convergence.” Although I’m not entirely sure what is implied by this, it sounded to me like they intend to remove the current separation between Flash and Flash Lite. The Nokia N810 was referenced as an example of a mobile device that already supports full fledged Flash. Although there are some obvious negative ramifications of this, mobile hardware advancements are happening so rapidly, I believe this is a step in the right direction and that soon enough, the ram-hog known as Flash should run, for the most part, just fine on most mobile internet browsers. It will certainly be a solution to the great-many web developers that currently do not consider mobile devices when creating their Flash content. I agree with Aral in that, “I don’t think Flash Lite is going away any time soon,” but I do believe its days are officially numbered.
Hydra to use the GPU (if available). I have heard some confusion about whether this is true or not from various blog postings. It was wonderful to hear straight from the horse’s mouth that all filters made in HYDRA will in-fact use the GPU (if one is available). I was fearful that many would-be web developers would start going crazy using all these open source filters that they found online, and our web browsing performance would start to go down the drain. Although this may still be the case for GPU’less systems (such as most mobile devices), it should definitely allow for some powerful filter effects on *most* systems to run quite smoothly.
New ‘object-based’ tween model. Adobe is planning on making their timeline tweening creation system “object-based.” Currently, if you want to create a tween, you create a new keyframe, right click on it, and then choose add motion/shape tween. In Diesel (CS4), you’ll instead place the object that you want tweened on the stage, right click on that object, and then create the motion/shape tween on the object itself. You can then click to any different point on the timeline, manipulate whatever you’d like about the object, and magically, a new tween has been created. The difference is subtle, but since motion tweens will soon be based on the object instead of the timeline, you can do things like manipulate (scale, rotate, etc) the entire tween as its own object or entity, you can use native bezier curves to guide the object’s path, and many other cool features. It sounds like you will still be able to visually see “keyframes” for any particular tween in the timeline, you can even select which keyframes for which property should be displayed. For example, you could choose to view the keyframes that correspond to location only, or to color only, etc… Very cool. Check out this video:
IK (Inverse Kinematic) Tweens. Most of us were already pleasantly surprised at the MAX ’07 announcement that Adobe was going to support Inverse Kinematics (for more information on what it currently takes to do this in Flash, check out Keith Peters excellent book, Foundation Actionscript 3.0 Animation: Making Things Move!). But, FotB ’07 was the first time that they announced native IK tween support! This was so cool that I’ll let the video do the talking:
All in all, it was a great session. Oh, and for historical records, Paul Betlem (senior director of Engineering for the Flash player) pledged the following four commitments regarding future versions of flash:
- Backward compatibility
- Fast, efficient distribution
- Secure experiences
- Cross platform support (Mac, Windows, & Linux)
Thanks John Davey for organizing such an excellent conference!! Hopefully I’ll get to see you again at FotB’08 (which Davey announced will be Sept 27 – Oct 1, 2008)!
I posted various pictures from the event on flickr which can be seen here.
Organizing your AS and FLA Files in Large Development Environments
Jun 13th
I lead an ever-growing team of Flash developers at a company called DigiDeal. We create electronic poker tables that go in casinos. Our goal is to pump out new games as often as possible. Since most casino games are just a variation of some “base level” game (such as Poker, Blackjack, Baccarat, etc), inheritance and code re-use is extremely important to us. Whenever possible, everything we create is broken into modular components with a good API. The “modules” can be as simple as a playing card or bet chip. But they can also be fairly complex such as a chip compilation linker, which takes care of creating multiple chip groups (one for your personal bank and [n] others depending on the number of distinct bet types in the given game), and allows them to interact with each other, send chips flying across the screen, color up the chips, balance the chips, and do various other animations. These “modules,” as I’m calling them, consist of a MovieClip/Sprite stored in the Flash Library and a linked AS class file.
Let’s say I get a spec for some new variation of a Blackjack game that I’m supposed to develop. My ideal goal for development would be as follows:
- Create a new .fla and the associated Document Class.
- Copy in all of the previously developed modules into the Flash Library or Stage as needed.
- Re-skin these modules where necessary.
- Write an inherited class for any of the modules that do not exactly fit my current needs.
- Import all of the necessary module packages in the Document Class.
- Utilize their API’s (properties, methods, and events) to get the game running as desired.
This, of course, is nothing new or exciting in the normal development world. But there is a unique organization problem in Flash. You have to organize, not just your .as files (package tree) and any associated images, sounds, and/or videos, but you also have to organize your Flash Library MoveClips. There are a couple of ways that this could be done.
You could create a single “modules.fla” which kept every component that you might ever need in a single file. Then, whenever you started a new project, you would just get everything that you need all from one place. This might be a great solution if you don’t have many modules. But what if you have over 200 modules and the .fla gets over 300 MB? Try opening and saving a 300 MB file in Flash. Personally, I’m not a fan of my mouse cursor turning into an hour glass for an extended period of time. Not to mention the repository ramifications if you only wanted to modify a single one of these modules or if multiple developers wanted to work on multiple modules simultaneously.
So, naturally, a better solution is to save each module in its own .fla. The question just becomes, how do you organize these .fla’s?
You could save them all at the root of the package tree. The benefits? You never have to set a class path and you’re guaranteed that the module you are looking for is somewhere located in a single folder. The downfalls? The module you are looking for is somewhere in a single folder. But good luck finding it quickly or efficiently if you have a ton of .fla’s.
So, it seems a better solution is to have these modularized .fla’s in their own folder tree. But how should this be organized? You could come up with some arbitrary folder organization structure that makes sense to you. But then let’s say that you just hired Joe Developer and he found the .as file for a module that he wants to use in a new game. Now although the folder tree that you created for your .fla files seems brilliant in your own eyes, Joe Developer might happen to have trouble understanding it. Now you have to spend extra time training Joe, when a more intuitive solution could take care of this for you.
A better idea would be to have some sort of organizational congruency between your .as files, .fla files, image files, sound files, and video files. For me, and ideal situation would be to navigate to a single folder and it would have everything that I need or is used by the module all in one location. Trust me, you will save yourself tons of time training the new people or remembering ‘where the heck you put that’ down the road if everything is in one place.
So, this is the approach that I went with:
Each level of the major inheritance tree has a folder called “modules.” Within it, there may be a few sub folders, but eventually there is a leaf node folder with the same name as the class that it contains. For illustration purposes, let’s say we had a module called “MyModule.” Inside the MyModule folder, there will be three things:
- The actual .as file for the class (MyModule.as)
- A folder called “resources”
- A folder called “sample”
Any images, sounds, or videos used by MyModule will be stored in the “resources” folder. Easy to find, easy to update.
The “sample” folder will contain MyModuleSample.fla and MyModuleSample.as. This will be the .fla and corresponding Document Class needed to quickly test/alter the module. MyModuleSample.fla will have a folder within its Flash Library called MyModule. The goal is that this folder can be copied out of the Library of the sample and pasted into any other desired .fla as a single, self-contained module.
I’m sure some people might scrutinize me for having .fla’s intermixed with my .as files, but this organization has proven very intuitive for new hires and has made it very easy for them to copy the packaged up Flash Library stuff into a new project. It has also saved me from having multiple folder trees open in my OS or having to move up and down the folder trees more frequently.
As a side benefit, this has made repository management much easier as well. Let’s say I modified multiple modules in various locations, but I only want to commit one of them. I can commit just the MyModule folder and it will grab exactly the files that I want committed along with it–no more, no less.
Hope this helps. Let me know your thoughts…
Bitmap and Sprite Conversion in ActionScript 3
Jun 8th
I got tired of writing the Bitmap and Sprite Conversion code in AS3 multiple times and finally decided I’d write a small utility that would easily do this for me.
Usage:
Let’s say you have some some Sprite on the stage called _mcSprite that you want to become a bitmap, then you would do the following:
[as]var tmpBitmap:Bitmap = DisplayConverter.spriteToBitmap(_mcSprite);[/as]
DisplayConverter.bitmapToSprite() is also included. Both functions include an optional second parameter if you wish to enable smoothing.
Get the open source class here.
Update:
I just realized that the spriteToBitmap function did not maintain the transparency of the original. This is because the BitmapData constructor defaults the fillColor to opaque white instead of transparent. This can be fixed by setting the alpha byte of the ARGB hex code to “00″ instead of “FF”. For example:
[as]var bitmapData:BitmapData = new BitmapData(sprite.width, sprite.height, true, 0x00FFFFFF);[/as]
The class in the download link above has been updated with this issue resolved.
FlashCS3 Class Path Oddities
Jun 2nd
I just spent the last 30 minutes wanting to pull an Office Space on my computer. It all boiled down to odd behavior related to setting the class path in Flash CS3. Allow me to save you from a similar frustration:
Let’s say I have an .fla located in “com.natejc.display.utils”. Since I’ll be using other classes in different packages, I set my class path to “..\..\” to get me back to the “com.natejc” level.
Now let’s say that this .fla contained a MovieClip in the Library that was linked to a class called “ImageLoader” in the “com\natejc\display\utils\” folder. So, I naturally set the linkage properties of this MC to “com.natejc.display.utils.ImageLoader”. Upon compiling, Flash kicks out the following error message:
5001: The name of package ‘com.natejc.display.utils’ does not reflect the location of this file. Please change the package definition’s name inside this file, or move the file. C:\src\com\natejc\display\utils\ImageLoader.as
What!? Yes it does! They match perfectly!! Well, I finally discovered that if I moved the ImageLoader.as file to any other location and changed the linkage appropriately, everything worked great.
Conclusion: If a class lives in the same location as the .fla file, the linkage is always simply the class name without any package prefix, regardless of what your class path is set to or how deep the file actually exists within this path.
However, this means that the movieclip in my library can never be copied and pasted into a different library without someone remembering to change the linkage. C’mon Adobe, even if it is in the same folder, I should still be able to utilize my class path and specify the full package in my MovieClip Linkage.
FlashDevelop 3 Beta review
Jun 1st
On Tuesday (May 22, 2007), Mika Palmu, Philippe Elsass, and Nick Farina made an alpha release of the next installment of my favorite ActionScript editor, FlashDevelop. Somehow, I missed that they released the beta last night!
I tip my hat to the guys that made it. Considering it’s a free editor, it’s pretty darn good. I have a few rants and items on my wish list that I’ll get into in a moment; but all in all, these guys could easily sell this product and yet they offer it for free. I’m surprised Adobe hasn’t hired them to save their horrible IDE in Flash CS3 (yeah, yeah, it’s improved… but for a company of their size and the number of years that Flash has under its belt, it should be significantly better than it is). Anyway, if you like and actively use the product, you should support them. If you are still using the Flash IDE to write your code, please, make your life easier and install FlashDevelop.
There is finally expanded keyboard shortcut support to allow utilization of keys such as ALT and PageDown.
Viewing multiple code files simultaneously in a split screen mode is even easier which can be seen here:
The Find & Replace is much better than it was in v2, but I wish it had a “replace within selection” option…
The code snippets have all been moved to individual external files. The best part is that they are now language specific! This means that I can have two different snippets, with the same name, but with completely different functionality depending on the language that I’m currently working in. There are a few $(EntryPoint) parameter oddities within snippets, but I expect they will fix this before the final release. Unfortunately, my biggest desire for FlashDevelop, more than anything else, still hasn’t been implemented. That is support for custom snippet parameters that can be changed in a popup dialog on the fly with default values. The SE|PY ActionScript IDE (also a great editor done by Alessandro Crugnola) has offered this feature for quite a while. See the screen shot below for how it works:
Configuring many FlashDevelop settings (but not all) or installed plugins is much easier with the new settings GUI:
The code completion is outstanding. The crash recovery seems to work fairly well (but I noticed a couple of oddities). The new integrated browser works okay, but it is in dire need of forward and back buttons (I wouldn’t even use this browser if it weren’t for the one click access it has to the online FlashDevelop documentation wiki).
All in all, FD is still my favorite (free) AS editor, and FD3 is a nice next step. If they add support for custom snippets, I would be as happy as Google was to locate E.T.
PowerCursor – Flash Tactile mouse cursor response?
May 23rd
Check this out:
“Tactile sensations like stickiness, roughness, pressure, volume or mass can be experienced in a graphical user interface without resorting to special force feedback devices. Powercursor uses a technique called ‘visually simulated force feedback’ to evoke the tactile experience.”
Pretty cool concept. Not sure how practical it really is, but I can think of a few creative uses and a couple of unique flash games that would be fun to use it in. It’s all in AS2, but I doubt it would be very hard to port to AS3. Nice concept. Check out the examples here.
ActionScript 3 Data Structures
May 18th
I’ve been longing to re-create the Zelda Arena game I created a while back in AS 3 (under a different title so I don’t get sued by Nintendo), and actually finish the project (feature-complete) and post it online where multiple people could go up against each other on a single server. My dreams for the game might be larger than my spare time allows (it seems like I don’t even know what ‘spare time’ means lately), but I think I’ll take a shot at it and see what happens.
In order to do it properly and write some decent AI, I’ll need some good Graph and Tree data structures written in ActionScript 3. I was about to pull out all of my old C++ code for these structures that I wrote back in college and port ‘em over, until I noticed Michael Baczynski of Polygonal Labs did all the work for me! He called it AS3 Data Structures for Game Developers and, so far, has included the following structures:
- Multi-Dimensional Arrays (2d and 3d, native)
- Queue
- Stack
- Tree
- Binary Tree
- Binary Search Tree
- Hash Table
- Linked Lists
- Heap
- Priority Queue
- Graph
- Bit Vector
Although I haven’t begun to use them extensively yet, all of the features that I desire seem to be there. The code looks pretty good, both from an efficiency and a design pattern point of view. Everything has ASDoc supported comments. He even has a nice tutorial on using the Tree Class and it seems he might be adding more tutorials later. Nice work Michael!
You can download the structures here:
Tweener Transition CheatSheet
May 16th
Have you ever wished you could have all of the different Tweener transition types (based on the Robert penner easing equations) on a single cheatsheet? I have too. So, I finally got around to making said cheatsheet. Enjoy.
Registered Socket Functions
May 3rd
Now that you know how to dynamically cast variables at runtime, we can create a very cool static class I dub RegisteredSocketFunctions. The purpose of this class is to allow any function to be “registered,” which, by doing so, allows global access to the function directly.
The goals of the RegisteredSocketFunctions class:
- Any function in any class can be very easily “registered.”
- Once registered, any function in any class can be executed, maintaining all parameter functionality.
- Any implied or direct usage of the “this” expression in the executed function will be interpreted properly.
Here’s the API:
[as]
/**
* Adds a new function to the list of available socket function calls.
*
* @param sFName Socket function call string reference name.
* @param funcReference A Function reference to the actual function.
* @param thisObject A reference to the object that should be the “this” object when this function is executed.
*
* @usage RegisteredSocketFunctions.registerFunction(“myTestFunction”, myTestFunction, this);
*/
public static function registerFunction(sFName:String, funcReference:Function, thisObject:Object):void
[/as]
[as]
/**
* Removes a function from the list of registered socket function calls.
*
* @param sFName The socket function call that should be removed.
*
* @usage RegisteredSocketFunctions.unregisterFunction(“myTestFunction”);
*/
public static function unregisterFunction(sFName:String):void
[/as]
[as]
/**
* Executes a Function that was previously registered using registerFunction with the name sFName.
*
* @param sFName The string reference name of the function that is to be executed.
* @param argArray The optional list of parameters that should be executed with the function.
* @param thisObject The optional object to which the Function referenced by sFName is applied. The “this” operator for the executed function will be thisObject if thisObject is non-null; otherwise, it will be the thisObject specified when registerFunction was called.
*
* @return Returns whatever value (if any) is returned by the function being called.
*
* @usage RegisteredSocketFunctions.registerFunction(“myTestFunction”, [var1, var2]);
*/
public static function executeFunction(sFName:String, argArray:Array = null, thisObject:Object = null):*
[/as]
Example:
Let’s say you have the following class
[as]
package
{
import com.natejc.utils.communication.RegisteredSocketFunctions;
public class RSFTestClass
{
private var _sName:String;
private var _nAge:uint;
public function TestClass()
{
RegisteredSocketFunctions.registerFunction(“testFunc”, testFunc, this);
} // END CONSTRUCTOR
public function testFunc(sName:String, nAge:uint):String
{
this._sName = sName;
this._nAge = nAge;
trace(“Hey ” + _sName + “, I can’t believe you’re ” + String(_nAge) + ” years old!”;
return sName + String(nAge);
} // END FUNCTION testFunc
} // END CLASS TestClass
} // END PACKAGE
[/as]
Then any other class in any other function could execute testFunc by doing the following:
[as]
var s:String = RegisteredSocketFunctions.executeFunction(“testFunc”, ["Joe Mama", 90]);
trace(s);
// which traces:
// Hey Joe Mama, I can’t believe you’re 90 years old!
// Joe Mama90
[/as]
Caution:
This class is intended to allow execution of functions across a network (which we will be discussing further later). Although this may seem like a cool, time saving way to allow classes all over your code interact with each other, doing so is definitely poor coding practice. Just like in real life, a child should never have command over its parent
. Having said that, if your project is due in 1 hour and you don’t have time to write all of the event handling that you should write, well, congratulations; you just found a class that will encourage your bad habits…
Download: RegisteredSocketFunctions.as
Tweener + Bezier + Zeh = Brilliance
May 1st
Zeh, the brains behind Tweener, has done it again. One of the main goals of Tweener was to create a system designed to allow the creation of animations (be they simple or complex) very easily. This goal was definitely accomplished. However, designing something that is appealing to the crowd wishing for simplicity, often leaves the crowd looking for more power, in wanting. Furthermore, attempting to appease both crowds congruently, is often like getting a camel through the eye of a needle.
I never thought Brazil had camels, but Zeh just threaded the needle with one. Introducing, Bezier curves in Tweener. Check it out.
Dynamic Casting and * in ActionScript 3
Apr 27th
This discussion is necessary in order to continue with our network programming lessons.
Casting (converting one variable type to another) in ActionScript 3 is very easy. The following code casts a uint as a String:
[as]var nNum:uint = 5;
var sNum:String = String(nNum);[/as]
But what if you don’t know what the variable should be cast as? For example, let’s say you have a client-server application. The server sends you an XML packet that contains the data for a variable and it tells you what the type of the variable should be with a written String expression. Your goal is to store this data in a variable of the proper type.
First, you have to know about the * (Special Type) operator. This can be used to create a variable that is “untyped.” For example, the following function can take any type of variable as a parameter:
[as]public function helloUntypedVariable(myVar:*):void
{
trace(“hello ” + String(myVar));
}[/as]
If you have an untyped variable you can determine which type of variable it is at runtime using the is operator:
[as]public function customTypeOf(dataObject:*):String
{
if (dataObject is uint)
return “uint”;
if (dataObject is String)
return “String”;
}
var n:uint = 5;
var s:String = “Hello World”;
trace( customTypeOf(n) ); // traces “uint”
trace( customTypeOf(s) ); // traces “String”
[/as]
It’s important to note that the “is” operator returns true for anything and everything that the variable in question is qualified to be. For example, the following code all returns true:
[as]var n:int = 5;
trace(n is uint); // traces “true”
trace(n is int); // traces “true”
trace(n is Number); // traces “true”
trace(n is String); // traces “true”[/as]
Even though n is of type “int”, it even returns true in the statement “n is uint” because the value is positive and therefore qualifies to be a uint.
Now we know enough to create our “CustomCaster” utility class. This static class has two purposes: to determine the most restrictive type of a variable (CustomCaster.customTypeOf) and to cast a variable as some other data type that can be specified at runtime (CustomCaster.customCast):
Download the latest version here.
Flash Network Programming via TCP/IP, part 2
Apr 26th
Today, I give you a free utility class that handles everything you need to handle in order to establish a connection. Tomorrow, I give you the world a class that make it seem like you are calling functions directly on the server and visa versa.
Download the latest version of the ConnectionEstablisher class here.
Usage example:
[as]// To establish a new connection, do the following:
var _server:ConnectionEstablisher = new ConnectionEstablisher(“127.0.0.1″, 4500);
// To send data to the server, do the following:
var xmlPacket:XML =
_server.send(xmlPacket);[/as]
Flash, AS 3, and physics
Apr 25th
There are a lot of good physics libraries and examples out there, such as the Fisix Engine, . But I just stumbled across a couple new ones: www.feedthehead.net, www.acrobots.net, and this monster truck demo (with source). Feedthehead has some fun easter eggs as well; for example, try pulling off the nose multiple times.
With the performance increases in AS3, new developments in Flash 3d and continual growth in the Flash physics world, I imagine the quantity and quality of flash games will start becoming the “new wave.”
The Little Tweener that Could
Apr 23rd
I used MC Tween all the time. When AS 3.0 came out, I loved everything about it, except the fact that there was no MC Tween. I sent an e-mail to Zeh asking if he was planning on porting it. He mentioned that he was working on a new implementation called Tweener, but that it was only for AS 2 and not yet ready for the public. Zeh was kind enough to send me the source so I spent that week porting it to AS3.
It’s funny to think back to those days, which was really not that long ago, and now I couldn’t even imagine what it would be like to make a Flash app without using Tweener!
Well, apparently I’m not the only one. It’s been great to see John Grden talk about how easy it was to learn and use in conjunction with Papervision3D, or to hear Ricardo Cabello (aka, Mr. Doob) say, “If you need a tween class, don’t look [at] any other, you only need Tweener!”
If you don’t know what Tweener is yet, head over to the project on Google Code and read the quick description. I promise it is worth it!
