A Flash Developer Resource Site

Results 1 to 10 of 10

Thread: A preloader class

  1. #1
    thinking is design retrotron's Avatar
    Join Date
    Apr 2003
    Location
    Utah
    Posts
    141

    A preloader class

    I've finally decided to put some preloader code into a class so I can reuse it whenever needed. It is not working however. Can anyone tell me what's wrong (or tell me how to do this better)?

    The class is pretty straight forward and simple. It simply draws a preloader movieclip and then uses setInterval to check for bytesLoaded until the target is loaded. Here's the code:

    code:

    // **************************************
    // define Loader Class Constructer
    function Loader(name,parent,target,targetDepth) {
    this.name = name;
    this.parent = parent;
    this.target = target;
    this.depth = targetDepth + 1;
    } // end Loader Class Constructer

    Loader.prototype.drawLoader = function() {
    _root.createEmptyMovieClip("loader_mc",this.depth) ; // create empty loader_mc
    this.depth += 1; // increment the depth 1
    with (_root.loader_mc) {
    // draw background box
    lineStyle(1,0x000000,100);
    beginFill(0xffffff,80);
    moveTo(0,0);
    lineTo(200,0);
    lineTo(200,50);
    lineTo(0,50);
    lineTo(0,0);
    endFill();
    // create text fields
    var loaderFormat = new TextFormat();
    loaderFormat.font = "arial";
    loaderFormat.size = 11;
    // create "loader" textfield
    createTextField("loader_txt",this.depth,10,25,100, 20);
    this.depth += 1; // increment depth 1
    loader_txt.html = true;
    loader_txt.htmltext = "loaded: ";
    loader_txt.setTextFormat(loaderFormat);
    // create "loaded" textfield
    createTextField("loaded_txt",this.depth,30,25,162, 20);
    loaded_txt.html = true;
    // create loader bar
    createEmptyMovieClip("loaderBar_mc",depth);
    this.depth += 1; // increment depth
    loaderBar_mc.lineStyle(1,0x000000,100);
    loaderBar_mc.moveTo(10,20);
    loaderBar_mc.lineTo(190,20);
    } // end with grouping
    } // end Loader.drawLoader() method definition

    Loader.prototype.runLoader = function() {
    this.drawLoader(); // draw the loader
    // run this.loadCheck() every 1 milliseconds
    this.loadInterval = setInterval(this.loadCheck,1,this.target,this.name );
    } // end Loader.runLoader() method definition

    Loader.prototype.loadCheck = function(x,y) {
    // x: the path to the target which is being loaded
    // y: the name of the current Loader instance
    // check if all bytes are loaded
    var loadBytes = eval(x).getBytesLoaded();
    var totalBytes = eval(x).getBytesTotal();
    var percentLoaded = (loadBytes/totalBytes) * 100;
    // set the values of the "loaded_txt" text field
    var loadedFormat = new TextFormat();
    loadedFormat.font = "arial";
    loadedFormat.size = 11;
    loadedFormat.align = "right";
    with (_root.loader_mc) {
    loaded_txt.htmltext = loadBytes + "/" + totalBytes + "bytes";
    loaded_txt.setTextFormat(loadedFormat);
    loaderBar_mc._xscale = percentLoaded;
    } // end with grouping
    if (totalBytes == 0) {
    // do nothing, execute Interval again
    } else {
    if (loadBytes < totalBytes) {
    // do nothing, execute Interval again
    } else {
    clearInterval(eval(y).loadInterval); // stop the interval
    // leave this commented for debugging purposes
    // _root.loader_mc.removeMovieClip();
    } // end "if loadBytes < totalyBytes"
    } // end "if totalyBytes == 0"
    } // end Loader.loadCheck() method definition

    // end Loader Class definition //
    // **************************************


    // test the loader
    // ---------------------------------------------

    // create a "holder" clip
    this.createEmptyMovieClip("holder_mc",0);

    // load the .jpg
    this.holder_mc.loadMovie("eastAsia2.jpg");

    // create and run the preloader object
    var myLoader = new Loader("myLoader",this,"_root.holder_mc",0);
    myLoader.runLoader();

    As you can see, to test it, I simply load some image or .swf into holder_mc, then create a new Loader object and run the "runLoader()" method.

    Any ideas on why this is not working (or how to do it better)?

    retrotron

    absconditus.com // experiments in actionscripted design

    "I really must get a thinner pencil. I ca'n't manage this one a bit: it writes all manner of things that I don't intend". // Alice, Through the Looking Glass

  2. #2
    Senior Member cancerinform's Avatar
    Join Date
    Mar 2002
    Location
    press the picture...
    Posts
    13,449
    You have to declare the constructor first:

    MovieClip.prototype.Loader = new MovieClip();

    What you are basically creating is some kind of component. Further you need a movieclip to associate this script with. This is what I would recognize at this point, what you might want to change. There may be other problems but I don't know.
    You may also have to registerClass like:
    Object.registerClass("Loader", Loader);

    and create linkage to export in frame 1.
    - The right of the People to create Flash movies shall not be infringed. -

  3. #3
    Senior Member cancerinform's Avatar
    Join Date
    Mar 2002
    Location
    press the picture...
    Posts
    13,449
    You have to declare the constructor first:

    MovieClip.prototype.Loader = new MovieClip();

    What you are basically creating is some kind of component. Further you need a movieclip to associate this script with. This is what I would recognize at this point, what you might want to change. There may be other problems but I don't know.
    You may also have to registerClass like:
    Object.registerClass("Loader", Loader);

    and create linkage to export in frame 1.
    - The right of the People to create Flash movies shall not be infringed. -

  4. #4
    thinking is design retrotron's Avatar
    Join Date
    Apr 2003
    Location
    Utah
    Posts
    141
    Thanks for the reply! This is good information.

    Further you need a movieclip to associate this script with
    I'm not sure I understand what you mean. Could you explain?

    You have to declare the constructor first:
    MovieClip.prototype.Loader = new MovieClip();
    I'm not sure why I need to register this class's constructor as a movieclip. Could you explain this to me more?

    I'm not sure if this plays into anything or not, but when the object executes the drawLoader() method, it creates a movieclip to contain the graphical elements of the loader. Does that make any difference here?

    absconditus.com // experiments in actionscripted design

    "I really must get a thinner pencil. I ca'n't manage this one a bit: it writes all manner of things that I don't intend". // Alice, Through the Looking Glass

  5. #5
    Senior Member cancerinform's Avatar
    Join Date
    Mar 2002
    Location
    press the picture...
    Posts
    13,449
    MovieClip.prototype.Loader = new MovieClip();

    By this way you create an instance, an object to which you can associate all the new parameters. For example when you create a component you create a movieclip first and then inside the movieclip you write the constructor. Your movieclip will have the same name "Loader". If you don't have an object, which you can fill with your parameters, the parameters will basically not exist.
    I am not a programmer, so my explanation may sound unprofessional but that is how I understand object-oriented.
    - The right of the People to create Flash movies shall not be infringed. -

  6. #6
    thinking is design retrotron's Avatar
    Join Date
    Apr 2003
    Location
    Utah
    Posts
    141
    You can be as unprofessional as you like, you're help is much appreciated!

    What you suggested is pretty new to me, I've never done it before, so that's why I'm confused. Let me try to explain it (to myself). I may be misunderstanding what you're suggesting.

    As I understand it, simply creating a function is all that's required to create a constructor function (e.g. function Loader() { } does the trick). Whenever a function is declared, ActionScript automatically creates a special "prototype" property for that function. So in my case, I can attach methods to the prototype of that function. I guess that means that any function is an object, since every function has a prototype property.

    Now, if I assign a new object to the prototype, that results in assigning some inheritance. What you suggested ("MovieClip.prototype.Loader = new MovieClip();") would then convert Loader into a MovieClip, thus it would inheret all the properties and methods of a movieclip (along with all the methods and properties I defined). This is where it's all hazy to me. Am I understanding this correctly?

    absconditus.com // experiments in actionscripted design

    "I really must get a thinner pencil. I ca'n't manage this one a bit: it writes all manner of things that I don't intend". // Alice, Through the Looking Glass

  7. #7
    Senior Member cancerinform's Avatar
    Join Date
    Mar 2002
    Location
    press the picture...
    Posts
    13,449
    First of all your script is very nice and it works. I don't know why you say it doesn't. Here it is in action:
    http://can_info_guide.tripod.com/com...structor3.html

    I have done some reading and you are correct. There is nothing wrong with your constructor. I just did not
    know this syntax. You also have created an instance of your function at the end, which I have been missing. However,
    I changed your file a bit. I put it into a movieclip, because movieclips you can put easily on stage
    from a library instead of a script. I had to flank it by initiclip so it would execute properly.

    Here is is in action:
    http://can_info_guide.tripod.com/com...nstructor.html

    Now I converted it into a component and now I had to change the script completely (constructor2.fla). I
    don't know there is a different way using your original syntax. Anyway now I had to declare Loader a
    movieclip.

    Here is is in action:
    http://can_info_guide.tripod.com/com...structor2.html

    The only problem with this is that the levels are different from your script.

    By the way if you want to use that I would not use createEmptyMovieClip because it will stay on the scene
    in every frame unless you eliminate it at one point. Just use a regular movieclip.

    Thanx. I learnt a lot.
    Last edited by cancerinform; 05-15-2003 at 11:08 AM.
    - The right of the People to create Flash movies shall not be infringed. -

  8. #8
    thinking is design retrotron's Avatar
    Join Date
    Apr 2003
    Location
    Utah
    Posts
    141
    Cancer, you are awesome. Thanks so much for your help!

    I'm glad it worked. It really seemed like it wasn't to me. But maybe it was just going too fast or something. Maybe it was too early in the morning.

    I see now what you did by making it into a movieclip. You're right, that does make it very easy to drag onto the stage, especially as a component. Yeah, I learned a lot from this about using that type of inheritance to make it a movieclip. Very cool.

    I'm going to stick with both the component and the script version. These days I'm often generating movies/textfields/etc. with actionscript because of dynamic database content. In those cases, it is nice to be able on the fly with script to create a preloader like this for some loading database entry. Of course, I could just export the component for "attachMovie()", but with the script version the .swf doesn't have to package any symbols/components and export them, it just compresses the text/code. However, if I'm working on the stage, the component is much easier.

    You'll notice a line near the bottom of the checkLoad() method that is commented out, but if uncommented it will remove the movieClip that was created. So the movieclip is created to display the loader, but once the load is finished, the movieclip is deleted and only the target is left. I left it commented just so I could see the numbers when it was finished because it was disappearing too quickly for me to see. I'll have to uncomment that now.

    I think somewhere along the way I'll add some more parameters that lets the user define the size and position of the loader, and maybe the font/fontsize as well as outline and background color/alpha.

    Okay, that's it. Thanks again for taking the time to help me! I really appreciate that.

    retrotron

    absconditus.com // experiments in actionscripted design

    "I really must get a thinner pencil. I ca'n't manage this one a bit: it writes all manner of things that I don't intend". // Alice, Through the Looking Glass

  9. #9
    Junior Member
    Join Date
    Jul 2003
    Posts
    1

    revisting this awesome loader

    I love this loader with the drawing API preloader. my only "issue" with it is it doesn't have an onload event. anyone have any ideal about how to do that?

    thanks in advance to anyone who can help with this.

    i'm actually using the zip file cancerinform made, called contructor3.zip

    Kevin

  10. #10
    thinking is design retrotron's Avatar
    Join Date
    Apr 2003
    Location
    Utah
    Posts
    141
    What exactly do you mean by wanting an onload event?

    Just for kicks, here's a better one I use these days, better because it's a movieclip method:
    code:

    MovieClip.prototype.preloadClip = function(args) {
    // initialize args object
    if (args == undefined) var args = new Object();
    if (args.field1 == undefined) args.field1 = new Object();
    if (args.field1.x == undefined) args.field1.x = 100;
    if (args.field1.y == undefined) args.field1.y = 100;
    if (args.field1.width == undefined) args.field1.width = 50;
    if (args.field1.height == undefined) args.field1.height = 20;
    if (args.field1.text == undefined) args.field1.text = new Object();
    if (args.field1.text.font == undefined) args.field1.text.font = "arial";
    if (args.field1.text.size == undefined) args.field1.text.size = 10;
    if (args.field1.text.color == undefined) args.field1.text.color = 0x000000;
    if (args.field1.text.bold == undefined) args.field1.text.bold = false;
    if (args.field2 == undefined) args.field2 = new Object();
    if (args.field2.x == undefined) args.field2.x = 150;
    if (args.field2.y == undefined) args.field2.y = 100;
    if (args.field2.width == undefined) args.field2.width = 70;
    if (args.field2.height == undefined) args.field2.height = 20;
    if (args.field2.text == undefined) args.field2.text = new Object();
    if (args.field2.text.font == undefined) args.field2.text.font = "arial";
    if (args.field2.text.size == undefined) args.field2.text.size = 10;
    if (args.field2.text.color == undefined) args.field2.text.color = 0x000000;
    if (args.field2.text.bold == undefined) args.field2.text.bold = false;

    // render preloader
    theDepth += 1;
    this.createTextField("loading_txt", theDepth++, args.field1.x, args.field1.y, args.field1.width, args.field1.height);
    this.createTextField("loaded_txt", theDepth++, args.field2.x, args.field2.y, args.field2.width, args.field2.height);
    var thisTF = new TextFormat();
    thisTF.font = args.field1.text.font;
    thisTF.size = args.field1.text.size;
    thisTF.color = args.field1.text.color;
    with (this.loading_txt) {
    selectable = false;
    html = true;
    if (args.field1.text.bold) {
    htmltext = "<b>loaded</b> ";
    } else {
    htmltext = "loaded ";
    } // end if (args.field1.text.bold)
    setTextFormat(thisTF);
    } // end with (this.loading_txt)
    var thisTF2 = new TextFormat();
    thisTF2.font = args.field2.text.font;
    thisTF2.size = args.field2.text.size;
    thisTF2.color = args.field2.text.color;
    thisTF2.align = "right";
    this.loaded_txt.html = true;
    this.onEnterFrame = function() {
    var bytesLoaded = this.getBytesLoaded();
    var bytesTotal = this.getBytesTotal();
    if (bytesTotal != 0) {
    if (bytesLoaded < bytesTotal) {
    if (args.field2.text.bold) {
    this.loaded_txt.htmltext = "<b>" + bytesTotal + "bytes</b>";
    } else {
    this.loaded_txt.htmltext = bytesTotal + "bytes";
    } // end if (args.field2.text.bold)
    this.loaded_txt.setTextFormat(thisTF2);
    } else {
    delete this.onEnterFrame;
    this.loading_txt.removeTextField();
    this.loaded_txt.removeTextField();
    } // end if (bytesLoaded < bytesTotal)
    } // end if (bytesTotal != 0)
    } // end this.onEnterFrame()
    } // end MovieClip.preloadClip()


    Then you just use it by calling it on the clip that's loading:
    code:

    this.createEmptyMovieClip("holder_mc", 0);
    this.holder_mc.loadMovie("myClip.swf");
    this.holder_mc.preloadClip();


    It will construct the loader, then remove itself when the clip is loaded (which it technically doesn't need to do, since the loaded clip erases everything anyways). You can pass an object which contains various customizable properties, font, font size, etc.

    absconditus.com // experiments in actionscripted design

    "I really must get a thinner pencil. I ca'n't manage this one a bit: it writes all manner of things that I don't intend". // Alice, Through the Looking Glass

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center