Posts Tagged preloader

More on preloaders: passing the loaderInfo

I previously made 2 posts on the topic of preloaders (The right way to do a preloader in AS3, External Preloader; more complex cases), well this post will be a continuation of those. And one that I believe not everyone will agree with me. I know that because I didn’t agree with it at first but the more I thought about it the more it felt right.

When it comes to code I’m a bit of a fascist, I have trouble accepting habits of other coders if they are not the same as mine. So when I see something different my first reaction is to frown upon it (I am talking just about code; I am a very open minded person). When I first saw this mean of passing variables from the preloader to the main application that a coworker was doing I didn’t quite like it.

In the post about the more complex preloaders, I showed how to use an interface to pass data from the preloader to the loaded (main) movie. Now this part of the code is still the same. What changes is that instead of passing the flashVars (variables that are passed to the flash from the html embed code or javascript) individually inside fo the init method of the Main class (also in the interface), we pass them all together by giving the root.loaderInfo instead.

I already know what you are going to say: this is not strictly typed so it is bad. I know, I know, but if you think about it a bit you see that at some point the flashVars are not typed anyway; when they transition from html to flash. So what is the harm of perpetuating this just one level more? In the init method inside the Main class, the first thing I do is that I type the parameters passed, so I do end up typing my variables.

Now, you’re going to ask what do you gain from this? Well, since the preloader is an external file, every time you are going to pass more variables to the Flash from the HTML, you will have to modify 3 files : the preloader.fla, the IMain.as and the Main.as. Now if you pass the loaderInfo instead of the individual flashVars, you will only need to modify the Main.as since it is there that you type the variables. You completely bypass the preloader, which in a way make sense since your preloader doesn’t need to know about your application, all it does is to load it. once your preloader is completed you don’t ever have to touch it again.

Here is some code to illustrate this. In the preloader :

var mainContent:IMain;
function onLoadComplete(event:Event):void{ // this would be the function that the loader would call when the loading is completed
  mainContent = IMain(loader.content);
  addChild(Sprite(mainContent) );
  mainContent.init( root.loaderInfo);
}

And in the Main class :

package{
  import com.zedia.interfaces.IMain;
  import com.display.Sprite;
  import com.display.LoaderInfo;
 
  public class Main extends Sprite implements IMain{
    public function init(loaderInfo:LoaderInfo):void{      
      var flashVar1:String = String(loaderInfo.parameters.flashVar1);
      var flashVar2:Number = Number(loaderInfo.parameters.flashVar2);
      //do something with the FlashVars
    }
  }
}

, , ,

8 Comments


External Preloader; more complex cases

In my previous post I spoke about what would be my optimal external preloader, but I really covered only simple examples. In relations to external preloaders, there are 2 cases where it gets more complex. First, when you want to time you preloader’s animation with your main content’s animation and second, when you use FlashVars (variables passed from the HMTL to the SWF).

Timing a preloader animation with the main content animation

Sometimes you don’t want to start the loaded content as soon as it’s been loaded.  You want to leave time for the preloader’s exit animation to end or you want to morph your preloader with the main content to have some sort of continuity. In those cases, the external preloader has to call a method of the main content. That sounds simple but it actually isn’t. If you try to call a method directly like we used to do in ActionScript 2 the compiler will complain because it doesn’t know if the loaded content will have such a method. In order to solve this problem you will have to use interfaces. You can get more information about interfaces on this previous post of mine. Now that the loaded content is typed to an interface you will be able to call it’s method and the synchronization between the preloader and the content will be good.

Using FlashVars

FlashVars are really useful and a lot of times you might end up using them. The problem is that contrarily to ActionScript 2, in AS3 the root variable will refer to this SWF’s root, not to the entire application’s root. So from the loaded content you don’t have access to the FlashVars. You solve this problem the same way as we solved the preceding problem: by using an interface. In the first case, we mostly would have called a method without parameters like init() or something like that, but in this case the parameters will be the FlashVars. You might want to pass the root.loaderInfo.parameters.YOUR_VAR_NAME as a parameter or you might want to do some checking as to know if the parameter was passed or not. In your interface you will have to write down all the parameters you want to pass and what type (String, int, Number, etc) they are. Here is an example of how you could do it.

Here is the interface:

package com.zedia.interfaces{
  public interface IMain{
    function init(flashvars1:String, flashvars2:Number):void;
  }
}

Here is some of the code of that the preloader could contain:

import com.zedia.interfaces.IMain;
 
var mainContent:IMain;
function onLoadComplete(event:Event):void{ // this would be the function that the loader would call when the loading is completed
  mainContent = IMain(loader.content);
  addChild(Sprite(mainContent) );
  mainContent.init( String(root.loaderInfo.parameters.flashvars1),Number(root.loaderInfo.parameters.flashvars2) )
}

Here is some code of the loaded content:

package{
  import com.zedia.interfaces.IMain;
 
  public class Main extends Sprite implements IMain{
    public function init(flashvars1:String, flashvars2:Number):void{
      //do something with the FlashVars
    }
  }
}

As you can see in the preloader’s ActionScript, in order to add the content to the stage, you first have to cast it to Sprite. You will have to do this when you will want to have access to Sprite properties like x and y. I admit this is a down side of using interfaces but at the same time it solved both the problems of timing an animation and passing FlashVars to the loaded content.

, , , ,

18 Comments


The right way to do a preloader in AS3

I wanted to write this post for a very long time but Lee Brimelow beat me to it. But that is alright because he confirmed that the way I was doing my preloaders was a good one.

In AS2 we were used to seeing preloaders in the 2 first frames of a flash movie, but that technique didn’t work well when you used Classes and Library object exported for ActionScript. Even in AS2, I started making my preloader external. An external preloader is a swf that sole purpose is to load another swf.

I suggest you watch Lee’s video because it explains very well why you should use an external preloader and how to do it.

I think his method can be perfected to be even more memory and CPU efficient.

Let’s take a look at the code he uses:

var l:Loader = new Loader();
l.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loop);
l.contentLoaderInfo.addEventListener(Event.COMPLETE, done);
l.load(new URLRequest("content.swf"));
 
function loop(e:ProgressEvent):void
{
  var perc:Number = e.bytesLoaded / e.bytesTotal;
  percent.text = Math.ceil(perc*100).toString();
}
 
function done(e:Event):void
{
  removeChild(percent); // was removeChildAt(0) but it make more sense this way
  percent = null;
  addChild(l);
}

That’s pretty simple and straight forward. Lee makes sure to remove assets he used for is preloader to free memory, which is good,  but if you really wanted to push things a bit farther here is what you would do:

var myMovie:Sprite;
 
var l:Loader = new Loader();
l.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loop, false, 0, true);
l.contentLoaderInfo.addEventListener(Event.COMPLETE, done, false, 0, true);
l.load(new URLRequest("content.swf"));
 
function loop(e:ProgressEvent):void
{
  var perc:Number = e.bytesLoaded / e.bytesTotal;
  percent.text = Math.ceil(perc*100).toString();
}
 
function done(e:Event):void
{
  removeChild(percent); // was removeChildAt(0) but it make more sense this way
  percent = null;
 
  myMovie = Sprite(l.content);
 
  addChild(myMovie);
 
  l.contentLoaderInfo.removeEventListener( ProgressEvent.PROGRESS, loop);
  l.contentLoaderInfo.removeEventListener(Event.COMPLETE, done);
  l = null;
}

First difference you might find is that I set the weakReference of the listeners to true. It doesn’t serve any purpose in this case but I think it is a good practice and a good habit to always put weakReference to true for you listeners.

The second thing you might see is that I don’t add the Loader to the stage. I don’t want to do that because I want to get rid of the Loader. It did it’s job, now I don’t want it using memory for nothing. So instead I created a Sprite called myMovie and I give it the content of the Loader. For this to work, the content of the Loader as to be a Sprite, but you can always change the type of myMovie to adapt to what you are loading. Once I gave myMovie the content I add it to the stage.

Now that the Loader handed off its package I can get rid of it. The first step to do so is to remove the listeners. Listeners take up CPU resources and in this case they will never be used again so I might as well remove them. Once this is done I set the Loader to null to ged rid of it. I could have just done that and not remove the listeners before because I used weakReferences and the GarbageCollector would have destroyed them, but why wait until then when you can do it now.

Well that was it, it is really just a little cleaner but I think that if someone was looking to push this further that’s how he would do this.

Do you know any better way of preloading?

, , , , , ,

50 Comments


Using TweenLite in Preloaders

In the current project that I am doing, I need to do some Tweens in the preloader, nothing really fancy, just the habitual fade in / fade out ou move in / move out. I didn’t want to use Tweener because my preloader was only weighting 7k and using Tweener would have more than doubled the size of my preloader.

I was thinking at first about using the default Tweens classes from Adobe, but I decided to check out TweenLite. I was pretty amazed of what it can do. First it weights only 2k, but doesn’t include any easing functions, so if you want those you have to import the same classes as the Tween classes. If you use easing it adds 1k to the weight so it’s not too bad. So in total it’s only 1k more than the Tween classes.

So why use TweenLite instead of the Tween classes? Well the major advantage is that it uses a syntax really similar to Tweener. Since I use Tweener in the main Flash movie, I think it’s better for people that are going to use my code after me, they won’t have two syntax to learn in order to understand my code. Also this syntax is easy to understand and I can write it without have to copy and paste previous code.

Here is an example of code using TweenLite:

1
2
import gs.TweenLite;
TweenLite.to(mc, 1, {x:46, y:43});

, ,

4 Comments