F9 for actions

Some possibly useful and definitely unuseful ActionScript 3.0 code.

Oct 26

byxb asked: This isn't a question, but more sharing a workaround for components since you feed comes up quite a bit for custom component building. I Just found a way to order parameters for components in CS5/CS5.5! Insert unicode character U+200B in front of the parameter name. If you have 5 params, put five of those in front of the param you want first, four in front of the second, etc. U+200B is a zero-width space so it has no impact on the text, just the param order.

That’s a really interesting solution, thanks for sharing! Unfortunately I have moved out of the realm of component making for a while now and I think the last time I did it was with CS4, so hopefully CS5 and 5.5 have brought about less quirkiness than I had previously run into.


Oct 17

Exploration of Radial Collision

I was fortunate enough to meet Terry Paton at this year’s MAX conference. If you don’t know, he’s a Flash game developer that produces some great work and contributes a lot of knowledge to the online web of Flash resources - definitely a recommended follow.

Anyway, he made a blog post showing simple distance-based radial collision technique that he uses often in his games. The technique wasn’t new to me, but something about his post lit a fire in me to explore the idea to an extent that I’ve never put down in code before.

While playing around with the concept, I thought to myself that knowing when something hits something else is great, but often for games you want to know where something hit the other thing and usually you want one or the other or both of those objects to react upon that collision, much like things react to collisions in the physical world. It’s also useful knowing if something collides with a certain coordinate, such as the current position of the mouse.

So I took Terry’s code and expanded upon it with the idea that instead of getting back a true or false on whether objects are colliding, instead if there is a collision, you get back a data object with some really useful information about that collision. Here is the Collider Class:

package  {
	import flash.display.Sprite;
	import flash.display.DisplayObject;
	
	public class Collider {
		
		public static var lastCollision:Object;
		private static var pointsprite:Sprite;

		public function Collider() {
			// constructor code
		}
		
		public static function checkPointCollision( px:Number, py:Number, o1:DisplayObject, customRadius:Number = 0 ):Object {
			
			if( !pointsprite ) {
				pointsprite = new Sprite();
				pointsprite.graphics.beginFill( 0, 0 );
				pointsprite.graphics.drawCircle( 0, 0, 1 );
				pointsprite.graphics.endFill();
			}
			
			pointsprite.x = px;
			pointsprite.y = py;
			return Collider.checkCollision( pointsprite, o1, customRadius );
		}


		public static function checkCollision( o1:DisplayObject, o2:DisplayObject, customRadius1:Number = 0, customRadius2:Number = 0 ):Object {
			
			var dx:Number = o1.x - o2.x;
			var dy:Number = o1.y - o2.y;
			
			var csquared:Number = dx*dx+dy*dy;
			var dist:Number = Math.abs(Math.sqrt(csquared));
		
			var r1:Number;
			var r2:Number;
			
			if( customRadius1 != 0 ) {
				r1 = customRadius1;
			} else {
				r1 = (o1.width*.5);
			}
			
			if( customRadius2 != 0 ) {
				r2 = customRadius2;
			} else {
				r2 = (o2.width*.5);
			}
			
			var tr:Number = r1+r2;
			
			if (dist = 360 ) {
				realDegrees -= 360;
			}
			while ( realDegrees < 0 ) {
				realDegrees += 360;
			}
			return realDegrees;
		}
	}
}

And here it is in action, followed by the timeline code for the swf

import flash.display.Sprite;
import flash.display.DisplayObject;

var bumpers:Vector.<Bumper> = new Vector.<Bumper>();
var collision:Object = {};
init();

function init():void {
	
	for( var i:int = 0; i < 40; i++ ) {
		var b:Bumper = new Bumper();
		
		//b.x = Math.random()*stage.stageWidth;
		//b.y = Math.random()*stage.stageHeight;
		b.x = 90*Math.cos(i) + stage.stageWidth*.5;
		b.y = 90*Math.sin(i) + stage.stageHeight*.5;
		
		bumpers.push(b);
		addChild(b);
	}
	
	this.addEventListener( Event.ENTER_FRAME, onFrame );
}

function onFrame( e:Event ):void {
	
	for( var i:int = 0; i < bumpers.length; i++ ) {
		
		collision = Collider.checkCollision( player, bumpers[i] );
		if( collision ) {
			
			arrow.rotation = collision.angle;
			arrow.x = collision.x;
			arrow.y = collision.y;
			
			player.xvel =  8*Math.cos( collision.radians );
			player.yvel =  8*Math.sin( collision.radians );
			
			bumpers[i].xvel +=  Math.cos( collision.oppositeRadians );
			bumpers[i].yvel +=  Math.sin( collision.oppositeRadians );
			
		}
		
		collision = Collider.checkPointCollision( mouseX, mouseY, player );
		if( collision ) {
			player.xvel = 5*Math.cos( collision.oppositeRadians );
			player.yvel = 5*Math.sin( collision.oppositeRadians );
		}
	}
}

It’s not perfect, but for getting you up and running with collisions it does a pretty decent job. Enjoy

DOWNLOAD THE SOURCE


Feb 24

vmedium asked: I'm using:

[Inspectable(name = "Set Platform: ",defaultValue = "PC",enumeration = 'PC,Mac,PS3,XBox 360,Wii,NintendoDS,PSP,PS2,Xbox')]
public var platform:String;

I also have some other values as well.

Is there a way to disable a parameter if I set the platform to Mac?

best, thansk for your blog entries, very helpful

JT

I don’t know of any way to disable parameters based on other parameter choices. I think the properties panel is pretty rigid when it comes to component parameters.

What I have done to get around this is build panels with Flash and JSFL that allow you to add your own swf-based interface to control the properties of your component instance on the stage. This works really nicely if you have a complex component that needs more than just text fields to customize properties. You can also build your custom panel to edit multiple component instances at once, something that you can’t do with the properties panel.

Thanks for reading.

-Andrew


Feb 7

Fixing the “*** Building code hint cache ***” warning in Flash CS5 Pro

I have been battling with Flash CS5 Pro for the last few weeks with it not giving me any code hinting. Whenever I would do something and expect a code hint window, I would instead get nothing, except for a small yellow triangle with exclamation in the bottom right of the code window. Rolling over that icon gave the tool-tip “*** Building code hint cache ***”. After searching around online I found a lot of people complaining about the code hinting engine in Flash Pro, however the blogged-about solutions I found got me nowhere, and no one seemed to be addressing this specific warning message.

After thinking about how the code hinting system might work, I took a look at my opened files in Flash Pro. I had a lot of them open, mostly because I switch between a lot of projects in any given day. I know that the code hinting only works on an AS file when it’s properly associated with an open AS3 FLA file, and I had that, however what I also noticed was that I also had an AS2 FLA open, and it happened to be the first file opened in the set. So with little expectation I closed the AS2 FLA, closed Flash and re-opened it, and code hinting was miraculously revived.

Moral of the story is, the code hinting engine is quirky, if it’s not working it can very well be due to the files you have opened. I have Flash set to re-open my last opened files when it starts up. So if you have that configured be extra careful, and when in doubt, close all of your files and start fresh.


Nov 29

JSFL Script Failing or Timing Out

So in my latest endeavor of JSFL, I was building a panel that allows one to browse for an XML file that another program I built puts together. The xml file defines a set of FLA files and the number of scenes within that file. The file is loaded in and parsed out by actionscript, and once it’s all ready to be built I looped over the data and fired off a JSFL script to build each FLA file based on the specified parameters.

Now figuring out how to build the FLA file and add scenes was pretty easy, even the JSFL documentation made it pretty apparent how to do this:

function createFLATemplate( dir, filename ) {
	
	fl.createDocument("timeline");
	var newDoc = fl.getDocumentDOM();
	newDoc.height = 430;
	newDoc.width = 550;
	newDoc.framerate = 24;
	
	fl.trace( dir+"/"+filename+".fla" );
	fl.saveDocument( newDoc, dir+"/"+filename+".fla" );
	
}


The problems came about when I assumed that it would be no problem to call this JSFL process from AS3 in a loop. For some reason at very seemingly random points, the loop script would just die within the loop, sometimes it might get through half of the FLA files, or just a few, or nearly all of them. But very consistently it was never able to create all of the FLA files in one shot. My first inkling was that instead of doing this within a loop, I should turn it into a batch process and have the AS3 script wait for each file to be created before creating the next, it seemed like a full-proof idea. I was wrong. The batch process worked perfectly in theory, but again the JSFL script would just kill everything at some point in it’s processing.

The solution that I came up with was to keep the batch process in place, however I used setTimeout with a 500ms timeout. Not the most elegant solution, but this has fixed the problem, the JSFL script no longer dies, so I guess whatever processes that were running and getting tangled up now have sufficient time to clean themselves up for the next process to run.

public function fileComplete():void {
	curFile++;
	setTimeout( buildModule, 500 );
}


If anyone has any insight as to what the real problem is, I would really like to know, but it seems for now that if you are doing a pretty lengthy batch process of things with JSFL you just need to give it a little time to breathe.


Aug 31

Moving Library Assets from FLA to FLA with JSFL

One of my latest projects had me scratching my head while I was doing my R&D. The project was to build a Flash panel that could pull assets in from another FLA that acts as a library. My first thought was to see if there was any way to copy items directly out of the library and add or paste them into the current working FLA. In my research this just isn’t possible, but I was still able to get the panel built.

Basically the process that works is as follows:

  1. Open the library FLA file
  2. Put the wanted library item on the stage with library.addItemToDocument()
  3. Use fl.getDocumentDOM().clipCut() to add the item to the clipboard
  4. Close the library
  5. Use fl.getDocumentDOM().clipPaste() to add the asset to the FLA

It seems pretty simple and it is, truly the hardest part was figuring out that that was the process to use. Here’s what my JSFL looks like:

//Loads an asset from the libraryFile into the current working FLA
//libraryFile - the filename of the library (icons.fla)
//AssetName - the asset name as it is in the FLA library
function LoadAsset( libraryFile, AssetName ) {
	
	var originalDoc = fl.getDocumentDOM();
	
	fl.openDocument( librariesPath() + libraryFile );
	var libDoc = fl.getDocumentDOM();
	
	fl.getDocumentDOM().library.addItemToDocument({x:0,y:0}, AssetName);
	
	libDoc.clipCut();
	fl.closeDocument(fl.getDocumentDOM(), false);
	originalDoc.clipPaste();
}

//this is where I'm keeping the library FLA files
function librariesPath() {
	return fl.configURI + 'Resources/AssetLibraries/';
}

And here’s the panel:

The way it all works is the panel loads an XML file that defines all the library files and populates the combo box. Then when a file is selected from the combo box, I have another JSFL function that opens the FLA and grabs all the top-level (not in folders) asset names from the library and returns them back to the panel as a comma delimited string. The string is broken up into an array and populates the asset list. The ‘Add to Stage’ button then uses the name in the list to call back to the JSFL referenced above.

Hope this helps anyone looking to do this, I found no help on this via Google in my own research.


Aug 4

Flash CS5 Font Embedding in AS3

Just wanted to link up a really helpful blog post for migrating to how Flash CS5 does Font embedding. You can no longer use the [Embed] tag to accomplish this in your classes.

Aaron L’Heureux has written a great post showing exactly how to migrate over to the new system! Flash CS5 font embedding – it’s totally different…


Another Flash CS5 Custom Component Quirk

In my attempt to make my custom components compatible with Flash CS5 from CS4, I found that my Inspectable parameters that were Objects were not working, and in fact would cause all parameters that come after it to not work.

Before I continue on with the main topic here, I just want to note that regardless of what order you define your Inspectable parameters, Flash reads them in Alphabetically by the variable name. So when I say the parameters that come after the Object parameter, I mean all those that come after it Alphabetically.

To get right down to it, the problem ended up being that I defined my parameter’s defaultValue property with single quotes rather than double. CS4 didn’t ever care about this, but it seems CS5 is a lot more picky about how you define things. Here is the before and after:

BEFORE (broken):

[Inspectable (name="Parameters", variable="ButtonParameters", type="Object", defaultValue='command:"",event:undefined,frame:1,group:undefined,scene:undefined')]

AFTER (fixed):

[Inspectable (name="Parameters", variable="ButtonParameters", type="Object", defaultValue="command:'',event:undefined,frame:1,group:undefined,scene:undefined")]

Notice how I just switched the single quotes with double quotes in the defaultValue property. Hope this helps someone who is pulling their hair out.


Inspectable Parameters Not Showing Up on Custom Components in Flash CS5

So I just upgraded to Flash CS5 this week at work and I found a really finicky problem that does not seem to be documented anywhere. I build a lot of custom components for my job, and if you’ve ever done it you know that building custom components for Flash is a little like an Indiana Jones adventure - you get beaten up a bit, there’s some problem solving, and a whole lot of improvising before you reach the end, oh yeah and snakes too.

Anyway, the problem I came across was that with my custom components moving from CS4 (where they worked great) to CS5, my components no longer had their parameters visible in the component inspector, or in CS5 the properties panel. After an hour of Google searching with no answer to be found I decided it had to be an edge case of some sort.

The way I had previously listed my Inspectable tags in my code had been after my class declaration and before my property declaration - so it looked a little like this:

public class NavigationButton extends UIComponent {
	[Inspectable (name = "Button Type", variable = "ButtonType", type = "List", defaultValue = "Text", enumeration = 'Text,Blank,Hidden')]
	[Inspectable (name = "Disabled", variable = "Disabled", type = "Boolean", defaultValue = 'false')]
	[Inspectable (name = "Label", variable = "ButtonText", type = "String", defaultValue = 'Next')]

In CS4 this was a completely acceptable way to define your inspectable parameters for your custom components. However in CS5 they just do not register. After looking at how a few tutorials organize their Inspectable tags, I found that a few of the more recent tutorials define their Inspectable parameters just before the getter and setter functions for that parameter. So with a little cut and paste I moved the Inspectable tags just above the getters and setters like so:

[Inspectable (name = "Label", variable = "ButtonText", type = "String", defaultValue = 'Next')]
public function set ButtonText( t:String ):void {
	btnlabel = t;
	draw();
public function get ButtonText():String {
	return btnlabel;
}

And viola! The Component Definition now shows all of my Inspectable parameters that I have defined in the component class. Also note that when you make the change, you’ll want to open the Component Definition window twice, because it does not recompile the clip until you hit the OK button on that window. So the parameters won’t show up the first time, but they will after the clip gets recompiled.

Also, if you’re having the problem where your component is blowing up because Flash CS5 can’t find fl.core.UIComponent you need to add in $(AppConfig)/Component Source/ActionScript 3.0/User Interface as a source path in your ActionScript settings.


May 17

Listening for stage selections with JSFL

I’ve researched and tested a few ideas, but for the most part the conclusion is that there is no nice way to monitor the stage for some sort of “Selection Event” when building WindowSWF panels or JSFL scripts. JSFL does allow you to listen for some events, however I found none of these to suffice for wanting to know when the user has selected an instance item on the stage.

Adding an ENTER_FRAME event listener to your panel works. Basically calling out to a JSFL script on each frame to see if anything is selected, but the thought of having this execution loop running is like nails on a chalkboard when it comes to being efficient. Also I noticed bugs when trying to drill into objects - double clicks not registering on the stage, etc. So that idea was pitched out the window. A timer would do the same to a lesser degree, but again it’s not as nice a solution as having Flash tell us that something was selected.

I ended up going with what I’ve seen in most 3rd-party panels - a button to manually tell flash “hey, I’m ready for you to analyze my selection I have made on the stage.” Although the manual part about this is annoying at best, it seems to be the “nice” solution for now.


Page 1 of 2