Tuesday, September 25, 2007

Embedding a font in a component

it took me quite a while and a variety of sources to work out how to set an embedded font for use in a comboBox component in AS3, so i thought i would record the solution for others(and myself in future when i forget!).

Here are steps to follow:

Step 1. add the font you wish to embed to the library, set it to 'Export for ActionScript' and give it a Class name.(in this case 'ComicSans')
Step 2. add a comboBox component to your stage.
Step 3. add the following script:

var Comic:TextFormat=new TextFormat();
Comic.font=new ComicSans().fontName;
Comic.size=12; //let's say we want to change the font size

combo.textField.setStyle("embedFonts", true);
combo.textField.setStyle("textFormat", Comic);
combo.dropdown.setRendererStyle("embedFonts", true);
combo.dropdown.setRendererStyle("textFormat", Comic);


A couple of points to be aware of:

when setting your TextFormat font, don't use the font's linkage identifier directly, this property requires the name that the system uses when referring to the font.
rather request the name of the font through the font class.
i did this above with the line:
Comic.font=new ComicSans().fontName;

the font of the textfield within the combo needs to set, and the text within the list component(dropdown property) within the combo also needs to be set.
these are set differently.
while the textfield is set directly with setStyle, the list component is set indirectly, with setRendererStyle as there will be multiple textfields within the list component.

ENTER_FRAME problem

i've got an interesting conundrum for you all.

According to Flash help, ENTER_FRAME "...does not go through a 'capture phase' and is dispatched directly to the target, whether the target is on the display list or not."

and it is true that an object with an ENTER_FRAME event does seem to work okay if it's not on the display list.

however, if you start loading external assets, it seems to forget about this ENTER_FRAME event at some random point in time! insert the code below into a frame, and replace imageFile with an actual external asset. the enterFrame function should count up from 1 to infinity, but instead at around 30(for me) it stops!

however, if you add the MovieClip to the stage, it receives the ENTER_FRAME event without fail.

const imageFile:String="put a swf here.swf";
var tally:int=0;
var loadertally:int=0;
setUpEnterFrame();
nextLoader();
function setUpEnterFrame() {
var newObject:MovieClip=new MovieClip();
newObject.addEventListener(Event.ENTER_FRAME,enterFrame);
//this.addChild(newObject); -------works when these comments are removed...
}
function nextLoader() {
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderDisplayed);
var request:URLRequest = new URLRequest(imageFile);
loader.load(request);
moveToRandomPlace(loader);
this.addChild(loader);
}
function enterFrame(event:Event):void {
tally++;
trace(">>>>enterFrame - "+tally);
}
function loaderDisplayed(event:Event):void {
loadertally++;
if (loadertally<200)>
nextLoader();
}
trace("loader complete - "+loadertally);
}
function moveToRandomPlace(whichObject:DisplayObject):void {
whichObject.x=(Math.random()*stage.stageWidth);
whichObject.y=(Math.random()*stage.stageHeight);
}

STOP PRESS!

I've resolved this issue with some credit to kglad in forums - the problem is that as newObject is a variable local to the nextLoader function, when this function is complete and is garbage collected, the EnterFrame no longer triggers... i initially encountered this problem with Tweens - it is a very easy mistake to make - something to be cautious of!

Thursday, September 20, 2007

labels that are numbers

today i was given a movieClip of a candle slowly burning down. it had 15 states represented by numbered frame labels, and i wanted to go to the appropriate label based on the number of days the candle had been burning. the problem is, even if you convert the variable to a string, flash treats it as a number. so:

days=14;
gotoAndStop(String(days));


even though this is a string, flash still interprets this as frame number rather than a frame label. it goes to frame 14, rather than label '14'. there may be a solution out there, but the only one i know is renaming all of the labels to include an alpha character. laborious...

AS3 to the rescue!

we now have access to available frame labels and the related frame numbers in an array. so assuming we know where which number label we're after - which is easy in my case where the labels where numbered from 1 to 15, we can easily access the label even if its name is a number:

days=14;
this.gotoAndStop(this.currentLabels[days-1].frame);

Wednesday, September 12, 2007

double click problems

Let's say we want to set up a standard doubleClick interaction on a movie-clip(draw a square inside this clip) with instance name square:

square.doubleClickEnabled=true;
square.addEventListener(MouseEvent.DOUBLE_CLICK,double);
function double(event:MouseEvent):void {
trace("doubleclick");
}


Compile, it should work fine - "doubleclick" should trace when you double click the square.

Now place a movie-clip inside square with instance name circle(draw a circle inside this clip).

Recompile. Notice that double-click isn't recognised if you double click on the circle...

For some reason the circle movieClip is preventing the double-click event from bubbling up to square. forcing 'circle' to ignore the double-click and allow the event to continue on its merry way to 'square' is the best solution i have found:


square.circle.mouseEnabled=false;