So I’ve spent the better part of the past two or three days fumbling around Flash Builder 4.7 because, come on, who wants to use old, outdated Flash Builder 4.6, right?
Anyway, I unknowingly backed myself into a corner when I (stupidly) uninstalled FB 4.6 before installing FB 4.7 because a download link for FB 4.6 is apparently hard to come by these days. As a result, I was stuck with the task of fixing the monumental wall of errors facing me when I first imported up my old game project.
This has nothing to do with this preloader stuff, but in case anyone out there runs into this problem, this is bad and throws errors:
[cc lang=”actionscript3″ escaped=”true”]
[Embed(source = “../lib/levels/level1.lvl”, mimeType = “application/octet-stream”)]
[/cc]
This is valid:
[cc lang=”actionscript3″ escaped=”true”]
[Embed(source = “/../lib/levels/level1.lvl”, mimeType = “application/octet-stream”)]
[/cc]
Spot the difference! That alone fixed 80+ errors I was facing. Apparently that leading forward slash is now mandatory.
Alright, onto the preloader.
Custom Preloader in Flash Builder 4.7
From what I can surmise, things have changed in FB 4.7 and I’m not sure if there are plans to “fix” things back to the way they used to work.
To get started, the basic core of my Preloader.as class I got from somewhere else on the internet. I can’t seem to remember exactly, but shout-out to them.
Edit: I’ve found the original source of the preloader code to be from a post on pixelpaton.com.
Now, this process involves two classes, the Preloader.as class and your document class (here, mine will be Main.as).
Step One – Compiler Settings
- Open FB 4.7 and right-click on your project, select Properties.
- Click ActionScript Compiler on the left and find the Additional compiler arguments field.
- Append this in that field: -frame appFrame Main
Note: This assumes Main is the name of your document class, make sure you change it appropriately.
Step Two – Preloader Class
- Create a new class, call it Preloader.as.
- Paste the following code into this class:
[cc lang=”actionscript3″ escaped=”true”]
package
{
import flash.display.DisplayObject;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.utils.getDefinitionByName;
[SWF(frameRate=”60″, width=”700″, height=”525″, backgroundColor=”0x000000″)]
public class Preloader extends Sprite
{
// Private
private var _preloaderBackground:Shape
private var _preloaderPercent:Shape;
private var _checkForCacheFlag:Boolean = true;
// Constants
private static const MAIN_CLASS_NAME:String = “Main”;
public function Preloader()
{
trace(“Preloader: Initialized.”)
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
public function dispose():void
{
trace(“Preloader: Disposing.”)
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
if (_preloaderBackground)
{
removeChild(_preloaderBackground);
_preloaderBackground = null;
}
if (_preloaderPercent)
{
removeChild(_preloaderPercent);
_preloaderPercent = null;
}
}
// Private functions
private function onAddedToStage(e:Event):void
{
trace(“Preloader: Added to stage.”);
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
stage.scaleMode = StageScaleMode.SHOW_ALL;
stage.align = StageAlign.TOP_LEFT;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(e:Event):void
{
if (_checkForCacheFlag == true)
{
_checkForCacheFlag = false;
if (root.loaderInfo.bytesLoaded >= root.loaderInfo.bytesTotal)
{
trace(“Preloader: No need to load, all ” + root.loaderInfo.bytesTotal + ” bytes are cached.”);
finishedLoading();
}
else
beginLoading();
}
else
{
if (root.loaderInfo.bytesLoaded >= root.loaderInfo.bytesTotal)
{
trace(“Preloader: Finished loading all ” + root.loaderInfo.bytesTotal + ” bytes.”);
finishedLoading();
}
else
{
var percent:Number = root.loaderInfo.bytesLoaded / root.loaderInfo.bytesTotal;
updateGraphic(percent);
trace(“Preloader: ” + (percent * 100) + ” %”);
}
}
}
private function beginLoading():void
{
// Might not be called if cached.
// ——————————
trace(“Preloader: Beginning loading.”)
_preloaderBackground = new Shape()
_preloaderBackground.graphics.beginFill(0x333333)
_preloaderBackground.graphics.lineStyle(2,0×000000)
_preloaderBackground.graphics.drawRect(0,0,200,20)
_preloaderBackground.graphics.endFill()
_preloaderPercent = new Shape()
_preloaderPercent.graphics.beginFill(0xFFFFFFF)
_preloaderPercent.graphics.drawRect(0,0,200,20)
_preloaderPercent.graphics.endFill()
addChild(_preloaderBackground)
addChild(_preloaderPercent)
_preloaderBackground.x = _preloaderBackground.y = 10
_preloaderPercent.x = _preloaderPercent.y = 10
_preloaderPercent.scaleX = 0
}
private function updateGraphic(percent:Number):void
{
// Might not be called if cached.
// ——————————
_preloaderPercent.scaleX = percent
}
private function finishedLoading():void
{
var MainClass:Class = getDefinitionByName(MAIN_CLASS_NAME) as Class;
if (MainClass == null)
throw new Error(“Preloader: There is no class \”” + MAIN_CLASS_NAME + “\”.”);
var main:DisplayObject = new MainClass() as DisplayObject;
if (main == null)
throw new Error(“Preloader: The class \”” + MAIN_CLASS_NAME + “\” is not a Sprite or MovieClip.”);
addChild(main);
dispose();
}
}
}
[/cc]
There are two main components here you need to worry about.
- Be sure to change the values in the SWF metadata tag to whatever you want (above the class declaration).
- Also be sure to change the value of the constant that holds the name of the document class (again, mine is Main.as):
private static const MAIN_CLASS_NAME:String = “Main”;
This is the most absolute bare-bones preloader you can have. It simply uses two rectangle shapes to display a loading bar. When you need to, you can replace the functionality with graphics or whatever.
Step 3 – Main.as (or whatever your document class is)
There is nothing special about Main.as. This is simply the “starting point” for your game. It doesn’t matter what’s in the actual .as file, just as long as the file exists right now.
Step 4 – Default Application
- Right-click on Preloader.as in the Package Explorer window and select Set as Default Application.
- In the Package Explorer window, Preloader.as should now have an icon with a small blue circle and Main.as should not.
(Also, very important. Preloader.as should also have a green triangle on it’s icon while Main.as should not. If Main.as does have this triangle, read below section, “Having Problems?.” The image to the right shows a green triangle on both icons – this is bad.)
Step 5 – Profit!
That’s it, you’re done. The main change here (at least from the method I’ve become accustomed to) is the lack of the [Frame(factoryClass = “Preloader”)] tag typically utilized.
Having Problems?
Depending on when you’re adding a preloader to your project, you may have to do one more thing. I learned this the hard way after things would only work once, then on the next build it’d be all messed up again.
You only need to worry about this if there is a green triangle on the icon next to Main.as in the Package Explorer window.
- Right-click on your project and select Properties.
- Select ActionScript Applications on the left.
- In the list on the right, select Main.as and click Remove. All that should be left in the list is Preloader.as (default).
- Now select Run/Debug Settings on the left.
- In the list on the right, select Main and click Delete. All that should be left in the list is Preloader.
- Click OK. All done!
From what I’ve seen, there hasn’t been a clear-cut answer to this preloader issue posted anywhere for FB 4.7 yet, so that’s why I wrote this up.
I originally didn’t know the “old” method of creating preloaders was deprecated until FB 4.7 kept throwing a ReferenceError: Error #1065: Variable Main is not defined error as soon as I attempted to build my project. Big thanks to the topic on the Adobe forums here that led me to this solution.