[AS3, Solved] Adding a child to Main calls Main()

7 posts

Flag Post

I am trying to create a re-usable wrapper for a Flash game. The idea is that the game has no preloader, and its compiled .swf form is an embedded asset to the wrapper, which handles the preloader. I use FlashDevelop, and the game and wrapper are AS3 projects without and with preloader, respectively.

Here’s the Main class for the wrapper:

package 
{
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.utils.ByteArray;

	[Frame(factoryClass="Preloader")]
	public class Main extends Sprite 
	{
		[Embed(source="../lib/game.swf", mimeType="application/octet-stream")]
		private const EmbeddedSWF:Class;
		
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			trace("Preloader complete");
			var binaryData:ByteArray = new EmbeddedSWF();
			var animationLoader:Loader = new Loader();
			animationLoader.loadBytes(binaryData);
			trace("Application ready");
			addChild(animationLoader);
			trace("Wrapper Complete.");
		}		
	}
}

Here is the output of the code:
Preloader complete
Application ready
Wrapper Complete.
Preloader complete
Application ready
Wrapper Complete.
Preloader complete
etc… You get the gist.
Execution finally ends in an internal error.

If I comment out “addChild(animationLoader);” then the output becomes:
Preloader complete
Application ready
Wrapper Complete.
and the debugger doesn’t crash. And, of course, the embedded game doesn’t run, either, since it hasn’t been added to the display list. Therefore it looks like adding the embedded .swf as a child to the wrapper’s Main causes Main() to be called again. The listener gets added again, and triggered, as a consequence, but I have no idea what on Earth is going on. Any insight into what’s going on and what I’m doing wrong would be appreciated.

 
Flag Post

it seems that it’s loading itself…

 
Flag Post

What package is the game and wrapper in?

Adding a loader to the display list brings in all the classes from the embedded SWFexcept any which are already defined. If your game is also in the default package then (no package).Main will resolve to the Main that already exists, and it will try to instantiate that instead! Resulting in an infinite loop of wrapper loading wrapper, as you are seeing.

Since this is a general purpose wrapper you should probably handle this properly and use an ApplicationDomain to load the embedded SWF into, i.e.

private function init(e:Event = null):void 
{
	removeEventListener(Event.ADDED_TO_STAGE, init);
	trace("Preloader complete");
	var binaryData:ByteArray = new EmbeddedSWF();
	var animationLoader:Loader = new Loader();
	animationLoader.loadBytes(binaryData, new LoaderContext(false, new ApplicationDomain()));
	trace("Application ready");
	addChild(animationLoader);
	trace("Wrapper Complete.");
}

(Only the loadBytes line changed.)

Thanks go to this blog entry.

 
Flag Post

If you don’t add it to the stage, init is never called; this is why i surmise you are loading the same file.

 
Flag Post

I think that’s because Loader doesn’t actually try to instantiate anything until you add it to the display list, so even though it’s got a class loop (i.e. it’s referencing the same Main that called it, not the one in the embedded SWF) it doesn’t call the constructor unless it’s added somewhere.

 
Flag Post
Originally posted by BobJanova:

I think that’s because Loader doesn’t actually try to instantiate anything until you add it to the display list, so even though it’s got a class loop (i.e. it’s referencing the same Main that called it, not the one in the embedded SWF) it doesn’t call the constructor unless it’s added somewhere.

Well you see, he has a Listener that calls init when added to the stage so I’m guessing that it’s the same file.

 
Flag Post

BobJanova had it right, and checking (with a trace) whether the game.swf file was initiated showed it was not, so indeed it is overwhelmingly likely that the already existing Main being called was the problem. The fixed line solved the problem (more evidence that what Bon described was the trouble) so it now works perfectly. Thank you very much. I’ll amend the thread title.