AS3 PV3D Preloader

Preloading is crucial when you have to load anything that takes more than a couple seconds. I’ve never liked the popular export to frame two, movie clip on the stage containing every single asset technique either. In my opinion it always felt like a hack, and somewhat of a hassle when you have larger files. I also prefer to have a single empty key frame on the main time line, so I created this preloader. It’s essentially a wrapper swf that loads your main swf which contain all the assets. I also thought this would be the perfect opportunity to represent Papervision3D by rocking the logo. The preloader is only 10k total, and uses TweenLite. You’ll also need the latest PV3D 2.0 classes which can be found HERE.

Download Source
View Swf

Preloader.as

/**
 * AS3 PV3D Preloader v2.2
 * Copyright (c) 2009 Marco Di Giuseppe	- http://designmarco.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package
{
	import flash.display.Sprite;
	import flash.display.Loader;
	import flash.display.Stage;
	import flash.display.StageScaleMode;
	import flash.display.StageQuality;
	import flash.display.StageAlign;
	import flash.events.Event;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.net.URLRequest;
	import com.greensock.easing.Expo;
	import com.greensock.TweenLite;
	/**
	 * Preloader Class Loads an External swf while
	 * animating a movieclip from the Library
	 */
	public class Preloader extends Sprite
	{
		private var swf:String = "main.swf"; //name of swf we are preloading
		private var inertia:Number = 5; //amount of easing applied to progress bar
		private var wait:Number = 2; // duration of time before loading begins
		private var preloader:PreloadClip; // library movieclip of logo
		private var barRatio:Number; // length of bar divided by 100
 
		public function Preloader()
		{
			addEventListener(Event.ENTER_FRAME, checkStage, false, 0, true);
		}
 
		/**
		 * Verify that the stage has been established by the browser
		 * @param	event
		 */
		private function checkStage(event:Event):void
		{
			if (stage.stageHeight > 0 && stage.stageWidth > 0)
			{
				removeEventListener(Event.ENTER_FRAME, checkStage);
				init();
			}
		}
 
		/**
		 * Initialize Preloader
		 */
		private function init():void
		{
			stage.scaleMode = "noScale";
			stage.quality = "High";
			stage.align = "TL";
 
			preloader = new PreloadClip();
			addChild(preloader);
 
			barRatio = preloader.progress_mc.bar.width / 100;
			preloader.x = stage.stageWidth * 0.5 - preloader.width * 0.5;
			preloader.y = stage.stageHeight * 0.3;
			preloader.progress_mc.bar.width = 0;
 
			var i:int = preloader.numChildren - 1;
			var logo:Sprite;
			while (i--)
			{
				logo = preloader.getChildByName("m" + i) as Sprite;
				TweenLite.from(logo, 0.4, { scaleX:10, scaleY:10, alpha:0, delay:i * 0.1, ease:Expo.easeOut } );
			}
 
			TweenLite.delayedCall(wait, loadContent);
		}
 
		/**
		 * Begin Loading Process
		 */
		private function loadContent():void
		{
			var loader:Loader = new Loader();
			var request:URLRequest = new URLRequest(swf);
			setListeners(loader.contentLoaderInfo, true);
			if (request) loader.load(request);
		}
 
		/**
		 * Display Loading Progress
		 * @param	event
		 */
		private function progressHandler(event:ProgressEvent):void
		{
			var percentLoaded:Number = int((event.bytesLoaded / 1024) / (event.bytesTotal / 1024) * 100);
			var barWidth:Number =  barRatio * percentLoaded;
			preloader.progress_mc.loading_txt.text = String(int(percentLoaded) + "%");
			preloader.progress_mc.bar.width += (barWidth - preloader.progress_mc.bar.width) / inertia;
 
			if (percentLoaded >= 100) preloader.visible = false;
		}
 
		/**
		 * Handle possible Loading Error
		 * @param	event
		 */
		private function ioErrorHandler(event:IOErrorEvent):void
		{
			trace("ioErrorHandler: " + event);
		}
 
		/**
		 * Add loaded swf to the display list
		 * @param	event
		 */
		private function completeHandler(event:Event):void
		{
			var main:* = event.target.content;
			TweenLite.from(main, 1, { alpha:0, delay:0.5, onStart:addChildAt, onStartParams:[main, 0], onComplete:destroy } );
			setListeners(main, false);
		}
 
		/**
		 * Remove Preloader
		 */
		private function destroy():void
		{
			if (preloader && preloader.parent)
			{
				preloader.parent.removeChild(preloader);
				preloader = null;
			}
		}
 
		/**
		 * Manage Loading Event Listeners
		 * @param	dispatcher
		 * @param	b
		 */
		private function setListeners(dispatcher:IEventDispatcher, b:Boolean):void
		{
			var state:String = b ? "addEventListener" : "removeEventListener";
			dispatcher[state](Event.COMPLETE, completeHandler);
			dispatcher[state](IOErrorEvent.IO_ERROR, ioErrorHandler);
			dispatcher[state](ProgressEvent.PROGRESS, progressHandler);
		}
	}
}

Main.as

/**
 * 	PV3D 2.0 Basic Example
 * 	@author Marco Di Giuseppe
 * 	marco (at) designmarco (dot) com
 * 	http://designmarco.com
 */
package
{
	import flash.events.Event;
	import org.papervision3d.view.BasicView;
	import org.papervision3d.objects.primitives.Plane;
	import org.papervision3d.materials.BitmapAssetMaterial;
 
	public class Main extends BasicView
	{
		private var plane:Plane;
 
		public function Main()
		{
			super(0, 0, true);
			addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true);
		}
 
		// initialize pv3d scene
		private function init(event:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
 
			_camera.focus = 100;
			_camera.zoom  = 11;
 
			var material:BitmapAssetMaterial = new BitmapAssetMaterial("image");
			material.smooth = true;
			material.doubleSided = true;
 
			plane = new Plane(material, 500, 500, 2, 2);
			plane.pitch(20);
			scene.addChild(plane);
 
			addEventListener(Event.ENTER_FRAME, render, false, 0, true);
		}
 
		private function render(event:Event):void
		{
			plane.yaw(0.75);
			singleRender();
		}
	}
}

comments

11 Responses to “AS3 PV3D Preloader”

  1. Beebs on February 18th, 2009

    After searching, testing, comparing tons of conundrum of preloader, I think your method is way more simpler. I don’t use your preloader but I think your idea is less complicated. Well done!

    I thought with the arrival of AS3 everything will be easier, but how predictable the thing become : when the version of Actionscripting there will be a problem of :
    1. Preloader
    2. Scrollbar
    3. Embedding Font
    And Adobe will keep cashing on this…Sigh!!!

  2. David on March 4th, 2009

    Hi,
    this is wonderfull simple… I don’t understand what i think is a little bug on IE.

    If i reload the page the loader goes on TL position and there is no way to have it at the middle of the page…(on firefox and safari it’s ok both on mac or pc)

    some ideas?

  3. Nikos Katsikanis on March 4th, 2009

    HI, good job and thanks for sharing. How would you integrate this into a flex pre loader?

  4. Marco on March 4th, 2009

    @David
    Nice Catch David, I just updated the preloader with a fix that resolves the issue.

  5. Anthony on March 24th, 2009

    Hi! great preloader!

    i was trying to get it to preload a papervision swf file i created.

    but i get the error

    TypeError: Error #1009: Cannot access a property or method of a null object reference

    i know its probably something really easy but ive been coding for somewhere near 15 hours now and my brain is dead.

    Thank you!!!

  6. Marco on March 24th, 2009

    @Anthony
    You’re probably trying to access the stage before it’s been added to the display list. I recommend using an Event.ADDED_TO_STAGE event so you know it’s available.

  7. Hellen CLARK on March 26th, 2009

    I like your blog and wanted to say keep up the good work. Do you plan on posting more soon?

  8. Phillip on September 18th, 2009

    Hello your loading bar does not seem to show is there any possible way of fixing this?

  9. Phillip on September 18th, 2009

    Error: Error #2099: The loading object is not sufficiently loaded to provide this information.
    at flash.display::LoaderInfo/get content()
    at Preloader/ioErrorHandler()
    Papervision3D Public Alpha 3.0 – PapervisionX (18.09.08)

  10. Marco on September 18th, 2009

    It should work now.

  11. Kinga on November 22nd, 2009

    Sorry, I have also problems with the progress bar and text. Any way of fixing this? Thanks :)

Leave a Reply