AS3 FLVPlayback seekBar problem

I’m customizing the FLVPlayback component with the individual video control components, but the SeekBar wouldn’t work no matter what I did, though the PlayPauseButton worked fine.

vidPlayer.seekBar = controls_mc.seek_mc;

Turns out that you need to set the SeekBar property of the FLVPlayback component AFTER you call play().

It took me a while to find the resolution to this annoying issue; hopefully google will index this post and help someone out.

jvanpelt - February 10th, 2009

bulkloader content null problem

Ok, so i’ve been trying to track down a BulkLoader bug in my framework for days now and I FINALLY managed to figure out what it was. First let me say that I don’t like try…catch statements very much. They obscure where an error is occuring in your app.

The way the framework works is, when it initiates it starts loading all of the external swfs that it needs, starting with home.swf on down the list. If you navigate to a page that isn’t loaded it’ll display a loading dialog and force BulkLoader to move that page’s assets to the top of the queue. This works well with SWFAddress, which allows you to start the application (site) from any page via deep-linking. Bla bla bla. The problem I was having was that the first item loaded by BulkLoader, no matter which page it was, would sometimes error out.

What I eventually found was that in BulkLoader’s ImageItem class, where the actual loader exists, the COMPLETE Event was being called but there was no content in the loader’s content property. But ImageItem’s onCompleteHandler doesn’t verify that the content exists, it just sets _content = loader.content and calls super.onCompleteHandler(evt). Flash has always had these weird little timing errors that’ll pop up where something is supposed to be ready to go, but it’s just not quite there.

override public function onCompleteHandler(evt : Event) : void {   _content = loader.content;

   if (!_content){       var t = new Timer(50, 1);       t.addEventListener(TimerEvent.TIMER_COMPLETE, onCompleteHandler);       t.start();   } else {       super.onCompleteHandler(evt);   }}

So I added in a quick check to see if the content is there. If it’s not, run a timer for 50ms then try again and Yay! it works. I don’t know if the other LoadingItem types have this same problem, but I do know that I had trouble finding any info on this issue. Hopefully this helps somebody.

jvanpelt - November 24th, 2008

referencing library items in an external swf by "linkage name"

I’m working on a base framework for Flash projects at work using PureMVC, SWFAddress, and BulkLoader. I’ve gone back and forth for a while now on the issue of loading one 600k swf that contains all of your assets, or loading page assets as individual swfs, which I think is the better way. What I wanted to avoid was having to compile individual “functioning” swfs that aren’t really part of the system. I want to simply use swfs as asset libraries and nothing else. The problem comes when you go to add an object from your loaded library.

If I try to add a graphic asset from the external library to the stage in my mediator I’ll get an error because basically that object does not exist yet. After doing a bit of research yesterday I found a work-around that I don’t particulaly like, but it works.

First of all, you have to define an ApplicationDomain in your Loader — or in this case, BulkLoader — with a LoaderContext object:

var context:LoaderContext = new LoaderContext(false,ApplicationDomain.currentDomain);bulkLoader.add(HomeMediator.ASSETS,{context:context});bulkLoader.add(AboutMediator.ASSETS,{context:context});etc...

Then you have to use the handy getDefinitionByName method in flash.utils. I have to say, though, that as useful as this little bit of code it, I don’t really like it. It feels like a hack. But it works, so let me show you the difference. First, the old way:

var header_mc = viewComponent.addChild(new HomeHeader());header_mc.init({x:100, y:200, name:"header_mc"});

became:

var ClassName:Class = getDefinitionByName("HomeHeader") as Class;var header_mc = viewComponent.addChild(new ClassName());header_mc.init({x:100, y:200, name:"header_mc"});

I can tell you, I hated this right off the bat. The idea of adding another line of code for every graphic element I add to the stage made me cringe. You’ll notice I’ve got this init() method that I’m calling on my objects as well. I’ll explain that in a minute.

The final solution I came up with for addressing adding elements to the stage was to create a DisplayManager class with a single static method:

public static function attachObject(viewComponent:*, ClassName:String, initObject:Object = null):Object{   var _ClassName:Class = getDefinitionByName(ClassName) as Class;   var _mc = viewComponent.addChild(new _ClassName());

   if (initObject){ _mc.init(initObject); }

   return _mc;}

which boils three lines of code in my mediators down to one:

var header_mc = DisplayManager.attachObject(viewComponent, "HomeHeader", {x:100, y:100, name:"header_mc"});

Lovely.

Ok, so let me quickly fill you in on the init() thing, which I thought I had posted on in the past, but it turns out I had only posted about the thought that lead up to it, simple proptery setting. I took this idea and created a very simple class, DisplayClip, that extends MovieClip and adds an init method that takes an initObject as a parameter and transfers those parameters to the MovieClip. I’ve got TypicalBtn and TypicalMenuBtn classes that extend DisplayClip, and I have to say it’s come in extremely handy.

package com.peteramayer.as3.display {

    import flash.display.*;    import flash.text.*;    import flash.events.*;

    public class DisplayClip extends MovieClip implements IEventDispatcher{

        public function DisplayClip() {            trace("[DisplayClip]");        }

        public function init(initObj:Object ) {            for (var prop in initObj) {                this[prop] = initObj[prop];            }        }

    }

}

jvanpelt - November 18th, 2008

Flash & Google Analytics

Just a quick post on using Flash and Google Analytics together, which is really quite simple using Google’s newer javascript as opposed to the old urchin javascript. You have to make one quick change — add the trackPage method to pageTracker._trackPageview() :

<!-- START GOOGLE ANALYTICS CODE --><script type="text/javascript">   var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");   document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));</script>

<script type="text/javascript">   var pageTracker = _gat._getTracker("UA-1111111-11");   pageTracker._trackPageview();

   function trackPage(pageName){       //alert("track page: " + pageName);       pageTracker._trackPageview(pageName);   }</script><!-- END GOOGLE ANALYTICS CODE -->

Then create a class with a single static method to call your javascript using ExternalInterface.

package net {

import flash.external.ExternalInterface;

/*** ...* @author j.vanpelt** This is just a utility file with a static method to track pages.*/public class GoogleAnalytics {

public function GoogleAnalytics() {   trace("this class is not meant to be instantiated.");}

public static function trackPage(pageName:String):void{   trace("[Google Analytics] track page: " + pageName);   ExternalInterface.call("trackPage", pageName);}}}

Import this class into your project and use it like this:

GoogleAnalytics.trackPage(”Media_viewVideo:TVSpot”);

There’s nothing complicated about it, but hopefully this will help someone!

jvanpelt - August 13th, 2008

hate macs

I hate macs. I have more network problems with macs then I’ve ever had with PCs. I just opened my mac that has been in hibernation so that I can publish a Flash file. The file happens to live on my pc. So I open as OS window (what are these called on macs, anyway — the equivelent to an “Explorer” window?) and click on Network. But… nothing. Ironically, the only way I can get the mac to recognize the network is to reboot. Sometimes if I just let it sit for a while it’ll come to. But it never “just works”.

Worse yet is when I’m trying to publish a network file — and by that I mean open a file that lives on the mac with the pc and export a swf using designery mac fonts — and the mac crashes. Or flash crashes. Or the network drops. Or the mac is just having a bad day or whatever other stupid issue it might be having. And then I try to open the file again and it’s broked. Or the mac gives me some cryptic error message and it just deletes the file. I LOVE THAT. That happened to me while I was on “vacation” recently, fixing some bugs in this Flash game, and the mac decided it didn’t really feel like opening that file. And if the mac can’t have it no one can. I wound up losing 3-4 hours of graphical changes in the .fla file.

“Macs are even better now because they have intel chips and can run windows!” My pc has been able to run windows all along.

jvanpelt - March 24th, 2008

simple property setter

still working on that post mardi gras thing. actually, my tablet has become disabled, so writing is slow. but i don’t make excuses.

this idea just came to me, and i don’t know why it too so long but i really wish it hadn’t. i’ll start with this simple code snippet:

var bla = {x:200,y:100,alpha:50};

// box_mc is just a square movieclip on the stage
for(var props in bla){
box_mc[props] = bla[props];
}

I’ve been trying to think of ways to reconstruct my flash work-flow in AS3 in the post-AS2 world, replacing attachMovie with something similarly easy to use. I don’t like to have anything on my timelines. Not code, not graphics. I want everything to be drawn from libraries within swfs. In AS3 everything is an object. A graphic in your library is a…

var gfx = new LibraryItem();

…custom object that does or does not have a corresponding class.

So i was thinking about creating a base class for my library item movieclips that extends MovieClip but that accepts properties that can be dynamically set. But how to set those properties? With a for … in loop, duh. Something like:

var gfx = new LibraryLinkageName({x:200,y:100,alpha:50});

so much easier than

var gfx = new LibraryItem();
gfx.x = 200;
gfx.y = 100;
gfx.alpha = 50;
addChild(gfx);

I haven’t decided about having objects attach and remove themselves from the display list yet, but I’m thinking probably not.

jvanpelt - February 27th, 2008

automating attachMovie for ActionScript2 UI Builder classes

We finally upgraded to the Adobe CS3 suite at work, so last week I wrote up a recommendation document for importing PSDs into Flash efficiently and to the standard we want to receive our files in. (I will likely post the gist of that document here soon, it’s pretty informative.) Generally speaking, the way I do my Flash development is to keep the stage of my movies completely blank and attach every element through code. The FLA file generally exists more as a library than anything else. However, during the initial graphic production stage, in order to get all of the coordinates for the attachMovie script, I still had to rebuild the entire PSD in Flash.

So now that that rebuilding part of the process is automated, I’ve come up with a quick and simple way to automate the script-writing process that attaches the movie clips to the stage. For this to work, you have to have your movie set up correctly — or modify my script to work within your constraints. My movie clips always have the suffix “_mc” and buttons end with “_btn”. In my library, movie clips have the same linkage name as the instance name that I use, though without the “_mc”. So linkage is “logo”, instance name is “logo_mc”, etc. For buttons, linkage is “logoBtn”, instance name is “logo_btn”. Got it? Great.

So now you’ve got an FLA with your design all laid out just like the PSD, everything is on the stage, everything has an instance name and a linkage name in the library to match. It’s all set up right? Great, run this script:

(Pardon line breaks:)

for(var i in _root){

var linkage = (i.indexOf(”_mc”) != -1) ? i.substr(0,i.indexOf(”_mc”)) : i.substr(0,i.indexOf(”_btn”)) + “Btn”;
trace(’var ‘ + i + ‘ = evtObj.attachMovie(”‘ + linkage + ‘”,”‘ + _root[i]._name + ‘”,evtObj.getNextHighestDepth(),{_x:’ + Math.round(_root[i]._x) + ‘,_y:’ + Math.round(_root[i]._y) + ‘,_alpha:’ + _root[i]._alpha + ‘});’);

}
stop();

That’s going to output a bunch of code that looks like this:
(Again with the line breaks:)

var topnav_mc = evtObj.attachMovie(”topnav”,”topnav_mc”,
evtObj.getNextHighestDepth(),{_x:741,_y:0,_alpha:100});

var footer_mc = evtObj.attachMovie(”footer”,”footer_mc”,
evtObj.getNextHighestDepth(),{_x:284,_y:567,_alpha:100});

var navbar_mc = evtObj.attachMovie(”navbar”,”navbar_mc”,
evtObj.getNextHighestDepth(),{_x:10,_y:24,_alpha:100});

var field_mc = evtObj.attachMovie(”field”,”field_mc”,
evtObj.getNextHighestDepth(),{_x:10,_y:456,_alpha:100});

var sky_mc = evtObj.attachMovie(”sky”,”sky_mc”,
evtObj.getNextHighestDepth(),{_x:10,_y:0,_alpha:100});

var logo_mc = evtObj.attachMovie(”logo”,”logo_mc”,
evtObj.getNextHighestDepth(),{_x:765,_y:556,_alpha:100});

Paste that into your class that builds your ui and stop writing all of that pesky code.

Two things to keep in mind… define or replace “evtObj” with your correct path, and keep in mind that if you’re using components, getNextHighestDepth() don’t work so well. Use DepthManager or bake your own.

jvanpelt - October 29th, 2007

Fuse & onMotionFinished follow-up

One more thing while I’m still up, in follow-up to my post about the loss of onMotionFinished using Fuse, I’ve come up with something that’s just as simple.

Fuse lets you pass in “callbacks” as objects, which basically call a method in whatever scope you tell it, like so:

{scope:this,func:doSomething,args :x ,y}

It was recommended to me that movieclips could be removed like this:

bla_mc.fadeOut(1,”easeInOutQuad“,null,{scope:bla_mc,func:removeMovieClip});

but that doesn’t really replace what I’ve done in the past, which is to have one function that removes all of the movieclips as well as take care of any extraneous things that need to be done — like calling the method to build the next page. So what I came up with is this:

var onTweensDone = function(){
bla1_mc.removeMovieClip();
bla2_mc.removeMovieClip();
isSomeVariable = true;
buildPage(”pageName“);
}

bla1_mc.fadeOut(1,”easeInOutQuad);
bla2_mc.fadeOut(1.5,”easeInOutQuad“,null,{scope:this,func:onTweensDone});

I don’t like that the onTweensDone function comes before the actual tweens, since it’s counter-intuitive in the flow of things. But obviously it’s got to be defined first before it can be passed in.

I have to say that I love the delay option in Fuse. As much as i like the simplicity of post-tween events for some things, burying tweens inside of other tweensonMotionFinished events gets really tedious and the code is confusing. And man, bezierTo and Blur_blurTo are my two favorite new toys. slideTo is great too, but just adding even just a tiny bit of bezier curve to any animation really brings it to life.

jvanpelt - September 6th, 2007

flash tidbit

Something I picked up last week:

I use the “? :” syntax for simple if/else statements all over the place in my code, but one thing i never really liked was in this scenario where you’re saying if x exists, set this variable equal to x, otherwise make it y… like this:

var bla = (x) ? x : y;

So I found out that you can do:

var bla = x || y;

and it means the same thing. If x doesn’t exist, make it y. One scenario I haven’t tried yet but am suddenly curious about… if x is a boolean and it’s false, does that make bla y? Or is this only in the case of x being null or undefined? Hm!

jvanpelt - August 22nd, 2007

Fuse Tweening without onMotionFinished

Yes, I have just written a non-New Orleans based post:

I’ve been using the Tween class in Flash to good effect for a long time now, but this current project i’m working on has finally spurred me to check out Fuse again (specifically for using movieclip_mc._tint = “#FF0000″; instead of messing around with ColorMatrixFilter, ugh).

Ok, so I’m going through this other thing i’m working on, replacing Tweens with Fuse methods and whatnot, and I got stumped on something annoying: Tween has a very easy method for triggering subsequent events with “onMotionFinished,” while Fuse has a few ways of triggering events like callbacks and listeners… but i hate listeners. I don’t like writing them. I think they’re convoluted and annoying — not that using syntax like onMotionFinished is that different, but it avoids two lines of code: creating and adding the listener object.

So say I’ve got a method two methods, removePageX() and displayPageY(). removePageX() is a bunch of tweens to fade out of move movieclips, which using fuse i could just attach {scope:this,func:”displayPageY”}. BUT, before calling displayPageY, I want removePageX to tween out all of the movieclips, then removeMovieClip()’s, then call displayPageY. The closest thing that Fuse offers, of course, involves listeners. This is what I’ve come up with:

fadeStartBtn.onMotionFinished = function(){
owner.evtObj.this_mc.removeMovieClip();
owner.evtObj.that_mc.removeMovieClip();
owner.evtObj.next_btn.removeMovieClip();
owner.displayPageY();
}

gets replaced with

var listener = new Object();
listener.onTweenEnd = function(){
owner.evtObj.this_mc.removeMovieClip();
owner.evtObj.that_mc.removeMovieClip();
owner.evtObj.next_btn.removeMovieClip();
owner.displayPageY();
}
evtObj.start_btn.addListener(listener);

What it comes down to in using fuse is that I either have to add all of these listeners all over the place using this method, or, if I use callbacks (which i’ve read are better on resources), I’d have to create a kind of proxy method that happens between one remove method and the next display method. I think optimally, it could be done one of two ways. Either it could be as simple as

evtObj.start_btn.onTweenEnd = function()… (or even retain onMotionFinished…)

-or-

we could do something like

var blaMethod:Function = function(){
bla.removeMovieClip();
trace(”so bla”);
}
bleh.fadeOut(1,Regular.easeInOut,.5,{scope:this,func:blaMethod});

but that doesn’t work, presumably because of scoping issues, as it’s looking for blaMethod in the class not the removePageX method.

So I don’t know. Maybe there’s some very simple solution that I’m overlooking, and if so someone point it out! Otherwise, i guess listeners it is!

jvanpelt - August 14th, 2007