I have an AS3 project that has all its assets embedded using the [Embed]
metadata tag because I would like the resulting SWF to be completely self-contained for the sake of portability on the internet.
Problem:
The file size is rather large, and I would like a progress bar to be displayed as it loads itself instead of a blank screen until it's completely finished. I can already achieve this with Adobe Animate (Flash Professional) by having a timeline with a light frame 1 and a heavy frame 2 which has a MovieClip that embeds the bulk of the assets.
I'm trying to switch over to Adobe Flash Builder, which has no IDE timeline, but I'm at a loss on how to do the same thing as the Flash IDE. Does anyone have any ideas on how to accomplish this?
CodePudding user response:
Option №1. The one I'd picked, because it's easier to comprehend: external loader. A lightweight SWF with the only purpose of displaying some preloading info like % or progress while loading the heavyweight main module.
Option №2. There's a certain metatag that allows you to emulate that frame 1 preloader behavior. Keep in mind that is is not supported by ASC2.0 compiler (AIR SDK, I assume) but only by ASC1.0 compiler (Flex SDK). Flash Builder is a descendant of Flex Builder, so it's fine, I guess, but if it does not work for you, the first thing you should check is the compiler version your Flash Builder is packed with.
So, your main (the one you set as the document class in the settings) class should have that one metatag:
package
{
import flash.events.Event;
import flash.display.Sprite;
// Brace for the magic impact.
[Frame(factoryClass="Preloader")]
public class Main extends Sprite
{
public function Main()
{
// This is important, because at the moment of creation
// the instance is not attached to the stage.
if (stage) onStage(null);
else addEventListener(flash.events.Event.ADDED_TO_STAGE, onStage);
}
private function onStage(e:Event):void
{
removeEventListener(flash.events.Event.ADDED_TO_STAGE, onStage);
// This is the entry point of your actual application.
// The rest of the class goes normally from this point on.
Then, the mentioned preloader class. Its name should qualify exactly as mentioned in the metatag above.
package
{
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.utils.getDefinitionByName;
// This class represents the multi-framed main timeline
// thus it should subclass the basic MovieClip.
public class Preloader extends MovieClip
{
public function Preloader()
{
// Subscribe to all necessary points to monitor the loading.
addEventListener(Event.ENTER_FRAME, onFrame);
loaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioError);
loaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
}
private function ioError(e:IOErrorEvent):void
{
// Handle loading errors here.
}
private function onProgress(e:ProgressEvent):void
{
// Display loading progress here.
// Use e.bytesLoaded and e.bytesTotal values
// to calculate the % loaded and the overall loading progress.
}
private function onFrame(e:Event):void
{
// When the loading is finished, the main timeline,
// represented by Preloader class moves to the frame 2.
if (currentFrame == totalFrames)
{
stop();
onComplete();
}
}
// This method concludes the loading,
// cleans up the preloader itself
// and instantiates the Main class.
private function onComplete():void
{
removeEventListener(Event.ENTER_FRAME, onFrame);
loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, ioError);
loaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgress);
// So, here's the thing. You don't import the Main class
// because if you import it, then it will be embedded into
// the Preloader, then it must be loaded before Preloader
// can be initialized, which kind of fails the whole idea.
// Thus, you don't import the Main class but obtain it
// via the other means, like the "getDefinitionByName" method.
// Again, the fully qualified class name is to be provided.
var aMain:Class = getDefinitionByName("Main") as Class;
stage.addChild(new aMain as DisplayObject);
// Remove this instance as it no longer needed for anything.
parent.removeChild(this);
}
}
CodePudding user response:
I found a solution that works with ASC2 / AIR SDK. Although his example preloader extends Sprite, and I believe you need to extend MovieClip to make it work, since you need a frame 2. And you need a gotoAndStop(2) once it has finished loading itself. Additional information here. Man, it's not a good sign when all your reference links go through web.archive.org!