[AS2, Flash CS4 Professional]
This might sound silly, but it is extremely useful. I just did a job for a client that needed to rotate their banners on a site that they had done for them 4 years ago. The site was hard coded to:
MovieA_______________________________________________
loadMovie(”flash/MovieB.swf”, intro_mc);
intro_mc is a simple, 1 frame movie in MovieA’s library that holds a Rectangle shape the size of the banner area. You use this rectangle to precisely position the asset in Movie A. intro_mc is placed as soon as it is needed, sometimes before the frame here that loads it.
MovieB_______________________________________________
This movie has the job of loading banners and displaying them. This is a great approach for lots of reasons, but for us the most important is that we don’t have to hard-code our banner rotation worker, MovieB, into MovieA or any other caller.
MovieB loads it’s movies from an XML file called banners.xml, which looks like this:
banners.xml
<?xml version="1.0"?> <banners> <banner bannerPath="banners/banner1.swf" bannerRepeat="1" /> <!-- <banner bannerPath="banners/banner2.swf" bannerRepeat="2" /> --> <banner bannerPath="banners/banner3.swf" bannerRepeat="1" /> <banner bannerPath="banners/banner4.swf" bannerRepeat="2" /> </banners>
You notice anything interesting? bannerRepeat allows the user to determine how many times that banner should loop before proceeding to the next banner. Once at the bottom of this file, MovieB starts from the top, looping.
So hopefully now you can see why a 3-tiered model is ideal. All we need to do is call MovieB from anywhere, and it works! The file banners.xml lives in a folder beneath MovieB called simply /banners. I load each banner, stop it, and change the alpha to 0.
Here is a snippet of how I load the banners:
/*
loadListener.onLoadInit - run for each movie when loaded
*/
loadListener.onLoadInit = function(target_mc:MovieClip):Void {
target_mc.onEnterFrame = function(){
if (target_mc._currentframe == target_mc._totalFrames){
if (target_mc._name == runningBannerName){
playNextMovie(target_mc._name); // pass currently running movie's bannerName/_name [...]
runningBannerName was needed because some banners don’t behave, and start themselves! I noticed that a non-desired banner would enter here while the desired was running. Some things you can’t forsee! playNextMovie() is called each time a playing movie has reached it’s end, and has no more loops to play (per banners.xml):
/*
playNextMovie() - the name says it all!
*/
function playNextMovie(runningBanner:String){
var repeat:Boolean = false; // pessimism
// 1 based index!
if (isNaN(mNext)){ // this the first time through
mNext = 1;
} else { // normal rules apply
mNow = mNext;
mNext = mNow + 1;
}
if (mNext > (bannerPaths.length)) // we're at the end of the rotation
mNext = 1;
var idxRunningBanner:Number;
for (a=0;a<bannerNames.length;a++){
if (runningBanner == bannerNames[a]) {
idxRunningBanner = a;
trace("idxRunningBanner:" + idxRunningBanner);
break;
}
}
if (idxRunningBanner != null){
var br:Number = parseInt(bannerRepeats[idxRunningBanner]);
var bl:Number = parseInt(bannerLoops[runningBanner]);
if (br == bl){
bannerLoops[runningBanner] = 0;
} else {
repeat = true;
if (mNext == 1){ // need to mane mNext the highest #
mNext = mNow;
} else {
mNext -= 1;
}
}
} else { // idxRunningBanner is null
// play as calculated above
}
var bannerIn:String = bannerNames[mNext - 1];
var bannerOut:String = bannerNames[mNow - 1];
if (repeat) { // if repeat=true, none of this is necessary
trace("repeat!");
} else {
trace("don't repeat!");
/*
stop current
*/
_level0[bannerOut]._alpha = 0;
_level0[bannerOut].gotoAndStop(1);
/*
start next
*/
_level0[bannerIn]._alpha = 100;
_level0[bannerIn].gotoAndPlay(1);
}
runningBannerName = bannerIn;
}
There is alot here, so I’ll just point out the main points, and answer any questions in Comments below. Seeing a few of the variables declared at the top to this frame (the only frame in the movie) might help:
var bannerPaths:Array = []; // holds the relative path to the banners.xml file var bannerNames:Array = []; // banner1, banner1, ... var runningBannerName:String; // banner1, banner1, ... var bannerRepeats:Array = []; // 1, 2, 3 - how many times each movie loops... var bannerLoops:Object = new Object(); // (assoc array) how many times has each banner repeated? var mNow:Number; // banner # to fade out var mNext:Number; // banner # to fade in
As you can see, there are a few ways we need to track banners. One is by the 0-based index in banners.xml, the other is in the assigned name (banner1, banner2, …, bannerN), and the other is the full relative path to the banner itself (from banners.xml).
So now we come to the reason for the post. The above will not work. The client called and said that MovieB never loaded, and no banners were visible. I called MovieB again stand-alone, and it worked perfectly. What up?
The problem was one of target scope. With _level0 I was calling an ABSOLUTE target. When MovieB was loaded into MovieA, any absolute calls within MovieB will refer to MovieA’s coordinates (or frame of reference).
/* stop current */ this[bannerOut]._alpha = 0; this[bannerOut].gotoAndStop(1); /* start next */ this[bannerIn]._alpha = 100; this[bannerIn].gotoAndPlay(1);
That was it! But there is another gotcha here. Remember in the banners.xml file how we specified the relative path to the banners? Remember also that MovieB was in a sub-directory of MovieA called “flash” (see loadMovie() above)? Common sense would have told you the file structure would look like this:
./MovieA.swf
./flash/MovieB.swf
./flash/banners/bannerN.swf
But you’d be wrong! Because everything is relative, and MovieB’s frame of reference is now MovieA’s, the structure now looks like:
./MovieA.swf
./flash/MovieB.swf
./banners/bannerN.swf
So you see, even though we load banners.xml from MovieB and it has relative paths, the actual place the relative paths are anchored is at MovieA’s level!
So there you have it. You can see why a 3-toered design works so well, how to allow your users to change the banners, order and loops for each with a single XML file, and also how to lay out your file structure to accommodate the targets.
It’s all RELATIVE!

Categories
Tag Cloud
Blog RSS
Comments RSS

Void « Default
Life
Earth
Wind
Water
Fire
Light 