AS2 to AS3 conversions, loading multiple external swf's with same preloader - actionscript-3

I'm new as a member here, but have found some very helpfull information here in the past, and cannot find a fix for my current issue. I've been trying to rewrite my flash AS2 website to AS3, and am getting roadblocked by all the major differences between these to actionscripts. I have a majority of it rewritten (successfully I think), but cannot seem to find the correct way to rewrite this AS2 code:
//AS2 ATTACH PRELOADER
function onLoadStart(target){
attachMovie("preloader anim", "preloader_mc", 500, {_x:447, _y:290});
}
function onLoadProgress(target, bytes_loaded, bytes_total){
target.stop();
target._visible = false;
preloader_mc.value = bytes_loaded/bytes_total;
}
function onLoadComplete(target){
trace("complete")
target.play();
target._visible = true;
preloader_mc.removeMovieClip();
}
function onLoadError(target, error_code){
preloader_mc.removeMovieClip();
trace(error_code);
}
//AS2 LOAD SWFS WITH ABOVE PRELOADER
var loader_mcl = new MovieClipLoader();
loader_mcl.addListener(this);
skullo_b.onRelease = function(){
startPreload("load/skullo.swf")
}
fruit_b.onRelease = function(){
startPreload("load/fruitbat.swf")
}
//...many more swfs left out to save space
function startPreload(url){
loader_mcl.loadClip(url, container_mc);
}
I know attachmovie is no longer for AS3, so from my research I've rewritten it as follows, but keep getting other errors that I'm having a loss on fixing. Basically, I have 30+ buttons, that when I click on each, it will load an external swf at the same location on the stage (container mc) and hide the previously loaded swf, and each swf will utilize the same preloader (preloader_anim). I've included the current errors I'm getting after finally clearing some others. If anyone can help me out, or point me to an online example of this I haven't been able to locate I would be very grateful. I've found some examples of loading external swfs with as3, but not multiples with the same preloader. I am also very new to as3, and haven't messed with classes yet, so all my code is on the timeline if that makes any difference.
//AS3 ATTACH PRELOADER
//ERROR 1046: Type was not found or was not a compile-time constant: preloader_mc.
//ERROR 1180: Call to a possibly undefined method preloader_mc.
var preloader_anim:preloader_mc = new preloader_mc();
preloader_anim.x = 458;
preloader_anim.y = 290;
addChild(preloader_anim);
function onLoadProgress(target, bytes_loaded, bytes_total){
target.stop();
target._visible = false;
var preloader_mc = bytes_loaded/bytes_total;
}
function onLoadComplete(target){
trace("complete")
target.play();
target._visible = true;
preloader_mc.removeMovieClip();
}
function onLoadError(target, error_code){
preloader_mc.removeMovieClip();
trace(error_code);
}
//AS3 LOAD SWFS WITH ABOVE PRELOADER
var imgLoader:Loader = new Loader();
//ERROR 1061: Call to a possibly undefined method addListener through a reference with static type flash.display:Loader.
imgLoader.addListener(this);
skullo_b.addEventListener(MouseEvent.CLICK, skullo_bClick);
angel_b.addEventListener(MouseEvent.CLICK, angel_bClick);
function skullo_bClick(e:MouseEvent):void {
startPreload("load/skullo.swf")
}
function metal_bClick(e:MouseEvent):void {
startPreload("load/metal.swf");
}
function startPreload(url){
//ERROR 1061: Call to a possibly undefined method loadClip through a reference with static type flash.display:Loader.
imgLoader.loadClip(url, container_mc);
}

Let's go through this in order of your errors.
ERROR 1046: Type was not found or was not a compile-time constant: preloader_mc
&
ERROR 1180: Call to a possibly undefined method preloader_mc.
These errors are because the compiler can't find any class called preloader_mc
If you have an asset in your library called preloader_mc, that is not enough, you need to go it's properties and choose export for actionscript, then give it a class name (the class name can be the same as the library asset name, so: preloader_mc).
Just make sure though, that you don;t have any variable or function names that clash with your class names (this is currently your case with preloader_mc). Common practice, is to make all class names start with an Uppercase letter, and all function and vars start with a lowercase letter.
2.
ERROR 1061: Call to a possibly undefined method addListener through a reference with static type flash.display:Loader.
In AS3, what you want is addEventListener. With the Loader class you need to listen for each event, instead of giving it a context that has pre-set methods. It takes a string event name, and a callback function. So you probably want this:
imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, imgLoaderComplete);
imgLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressHandler);
function progressHandler(e:ProgressEvent):void {
//this function will run whenever progress in the load is made
trace("progressHandler: bytesLoaded=" + e.bytesLoaded + " bytesTotal=" + e.bytesTotal);
}
function imgLoaderComplete(e:Event):void {
//this function will be called after the loader finishes loading
}
It's also a good idea to listen for IO_ERROR & SECURITY_ERROR events on the loader as well:
imgLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
imgLoader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
ERROR 1061: Call to a possibly undefined method loadClip through a reference with static type flash.display:Loader.
There is not method called loadClip on the Loader class. What you want is the following (to start loading)
imgLoader.load(new URLRequest("yoururlhere"));
For more details on how to properly use the Loader class, read the documentation.
So, in the end, it should look more like this:
//take your preloader movie clip, and export it for actionscript with the class name "Preloader_MC"
//create vars for the pre loader and loader (don't create the objects yet though)
var preLoader:Preloader_MC;
var imgLoader:Loader;
skullo_b.addEventListener(MouseEvent.CLICK, skullo_bClick);
angel_b.addEventListener(MouseEvent.CLICK, angel_bClick);
function skullo_bClick(e:MouseEvent):void {
startPreload("load/skullo.swf")
}
function metal_bClick(e:MouseEvent):void {
startPreload("load/metal.swf");
}
function startPreload(url) {
//if the loader is currently populated, destroy it's content
if (imgLoader) {
imgLoader.unloadAndStop();
removeChild(imgLoader);
}else {
//it doesn't exist yet, so create it and add the listeners
imgLoader = new Loader();contentLoaderInfo
imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, imgLoaderComplete);
imgLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressHandler);
imgLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
imgLoader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
}
if (!preLoader) {
preLoader = new PreloaderMC();
addChild(preLoader);
}
imgLoader.load(new URLRequest(url));
addChild(imgLoader);
}
function removePreLoader():void {
removeChild(preLoader);
preLoader = null;
}
function progressHandler(e:ProgressEvent):void {
var percentLoaded:Number = e.bytesLoaded / e.bytesTotal; //number between 0 - 1
preLoader.value = percentLoaded;
}
function imgLoaderComplete(e:Event):void {
removePreLoader();
}
function ioErrorHander(e:IOErrorEvent):void {
//file not found, do something
removePreLoader();
}
function securityErrorHandler(e:SecurityErrorEvent):void {
//do something, file wasn't allowed to be loaded
removePreLoader();
}

Related

as3 error: access of possibaly undefind property through a reference with static type flash.display:DisplayObject

I have this as3 project, and in frame one of the timeline I tried to load a swf movie named "menu" and in this loaded movie I have an instance of a button named "button1", and I want to add a new EventListener to this "button1". my code is here:
var theLoader:Loader = new Loader();
var address:URLRequest = new URLRequest("menu.swf");
theLoader.load(address);
theLoader.contentLoaderInfo.addEventListener(Event.COMPLETE , swfDidLoad);
function swfDidLoad(evt:Event){
if(theLoader.content){
addChild(theLoader);
var button:SimpleButton = theLoader.content.button1;
button.addEventListener(MouseEvent.CLICK, handler1);
}
}
function handler1 (event:MouseEvent):void
{
removeChild(theLoader);
gotoAndStop(10);
};
but I get this undefind property error. what should I do? Am i doing this right at all?
The reason you are getting that error is because you are trying to access button1 on theLoader.content which is a non-dynamic DisplayObject (this means that only explicitly defined properties/methods are valid). You must first cast it to a MovieClip (which is dynamic).
You should change that line to:
var button:SimpleButton = MovieClip(theLoader.content).button1;

connection between Flex and FLash

I am working on a project, which is based on two main parts, the first part is done by Flex, and second one is a flash professional project, contains PROJECTNAME.fla and PROJECTNAME.as files. My question is how we can set some parameters in .fla project (e.g. usernames, user's images) from flex part. I explain main procedure by following;
Connect to server by flex part and get user's status
run .swf created by a flash professional project as described above
set some parameters in .swf file.
I have googled a lot, and I did not find any solution. (there was some solution that converts symbol to flex component, since it works for converting a single symbol). Any Idea will be appreciated.
There are several possibilities to pass the params from one swf (flex in your case) to another runtime loaded fla.swf:
1.Pass through the loading query params:
code in flex.swf:
public function astest()
{
var loader:Loader = new Loader();
addChild(loader);
loader.load( new URLRequest("astest1.swf?param1=value1&param2=value2"));
}
access params from fla.swf:
public function astest1()
{
if(stage)
onAdded();
else
addEventListener(Event.ADDED_TO_STAGE, onAdded);
}
protected function onAdded(event:Event = null):void
{
//root.loaderInfo.parameters - params of this swf file
//stage.loaderInfo.parameters - params of core swf file
var params:Object = root.loaderInfo.parameters;
for (var param:String in params)
trace(param,"=",params[param]);
}
output:
param2 = value2
param1 = value1
lacks of this method:
-one time usage, you can pass params only one time when loading
-the second swf must be runtime loaded by url, you can't embed it (or one of the class withing it) for example.
2.Runtime communication through the events
I recommend to use this method, it hasn't lacks of previous one.
Example of using stage as the global common dispatcher.
flex.swf:
public function astest()
{
addEventListener("ready", onReady);
var loader:Loader = new Loader();
addChild(loader);
loader.load( new URLRequest("astest1.swf"));
}
protected function onReady(event:Event):void
{
sendParams("param1=value1&param2=value2");
}
protected function sendParams(params:String):void
{
stage.dispatchEvent(new DataEvent("params", false, false, params));
}
fla.swf:
public function astest1()
{
if(stage)
onAdded();
else
addEventListener(Event.ADDED_TO_STAGE, onAdded);
}
protected function onAdded(event:Event = null):void
{
stage.addEventListener("params", onParams);
//fire event with bubbling that anables handling it in the parent swf
dispatchEvent(new Event("ready", true));
}
protected function onParams(event:DataEvent):void
{
var data:String = event.data;
trace(data);
}
output:
param1=value1&param2=value2
with this approach you send as many params as you need, you alsa can create custom event to pass Object parameters but in this case both project must have this cusom event in there source paths.

AS3 objects (buttons) from library not accessible from within certain functions

I'm working on a simple image processor in AS3 and as usual I almost had it finished when an annoying little problem appeared. I want to open an image using a dialog box, and once the image is open I want the "selectBtn" (which is in my Library) to disappear. However when I try the code below I get a: "Error #1009: Cannot access a property or method of a null object reference". I'm sure it's something simple but I just can't figure it out!
// declare variables
var image:Bitmap;
var loader:Loader = new Loader();
var fileRef:FileReference= new FileReference();
selectBtn.addEventListener(MouseEvent.CLICK, openImage);
function openImage(event:MouseEvent):void {
fileRef.browse([new FileFilter("Images", "*.jpg;*.gif;*.png")]);
fileRef.addEventListener(Event.SELECT, onFileSelected);
}
function onFileSelected(e:Event):void {
fileRef.addEventListener(Event.COMPLETE, onFileLoaded);
fileRef.load();
}
function onFileLoaded(e:Event):void {
loader.loadBytes(e.target.data);
image = Bitmap(loader.content);
selectBtn.visible = false;
}
What Todd says is accurate: where is "selectBtn" defined? Is it on a stage, or nested within some movieclip instance?
Assuming the button exists on the stage, and the code runs in the same frame as the button exists, you could try this.stage.selectBtn.visible = false;
Otherwise, trace that you have selectBtn as a reference. Or you could declare a variable to reference it. i.e.:
var selectBtnRef:Button = this.stage.selectBtn;

preloading external .swf with class file as3

so i'm trying to make an external preloader to load my main .swf (loading.swf) file that has a class file named mainLoading.as using this code:
var l:Loader = new Loader();
l.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loop);
l.contentLoaderInfo.addEventListener(Event.COMPLETE, done);
l.load(new URLRequest("loading.swf"));
var loadingPage:loading = new loading;
function loop (e:ProgressEvent):void{
addChild(loadingPage);
loadingPage.x = stage.stageWidth/2;
loadingPage.y = stage.stageHeight/2;
}
function done (e:Event):void{
removeChild(loadingPage);
addChild(l);
}
so I'm getting an error message saying:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at mainLoading()
I think i'm getting the error message because i am accessing the stage in my mainLoading() class file. I tried adding this to the constructor in my class file but it didn't work:
public function mainLoading () {
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event): void {
initStartUpScene ();
}
my initStartUpScene function just throws the intro scene to the loading.swf
any suggestions?
thanks for your help.
(question) is your mainLoading extends either Sprite or Movieclip ?
EDIT
After reading your comment, I would suggest trying this :
Add a function call inside the swf content in your complete progress handler :
function done (e:Event):void{
removeChild(loadingPage);
addChild(l);
Object(l.content).initMethod();
}
content let you access the methods in your loaded .swf main class (e.g. mainLoading)
And replace the event handling in your mainLoading by :
public function mainLoading () {
//no event handling in constructor
}
public function initMethod():void {
//here you go
init();
}
public function init():void { ... //No more event here
Btw it's not the cleanest way to solve your problem.
If that's the exact message you are getting, then yes, adding the ADDED_TO_STAGE listener should have fixed it. Remember to recompile the "loading.swf" if you make any changes to it (a step I always seem to forget)
Does "loading.swf" run just fine without any errors when running it on it's own (not loading it into the "container" SWF)?
This may be unrelated to the question you asked, but you might get better results and avoid some errors by structuring your code like this:
var loadingPage:loading = new loading;
addChild(loadingPage);
loadingPage.x = stage.stageWidth/2;
loadingPage.y = stage.stageHeight/2;
var l:Loader = new Loader();
l.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
l.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
l.load(new URLRequest("loading.swf"));
//I renamed this function since I believe "loop" is a reserved keyword.
function onProgress (e:ProgressEvent):void{
//No code needed
}
function onComplete (e:Event):void{
removeChild(loadingPage);
addChild(l);
}
You can remove the "onProgress" function if you won't be needing it as well.
OOOOOOKKKKK, so after about a week of admitting defeat, trying it again, rewriting almost half of my code, trying to convince myself that preloaders are overrated, i finally figured it out (drum roll please):
I had a variable that was referencing the stage being called before my constructor method was called. like this:
private var xScrollPosRight:Number = stage.stageWidth - xScrollPosLeft;
I just changed stage.stageWidth to 750 and it worked.
live and learn.

Controlling FPS of a loaded swf

I'm working on a flash app where I load multiple swf's. But the problem is that they have different framerates (12/25/30). If I add 2 swf's they both play at 25fps. I found numerous topic about this but I can't get it to work (in AS3). Does anyone know why it doesn't work and how to make it working?
public class MainClass extends MovieClip
{
var loader:Loader = new Loader();
var request:URLRequest;
var mcMedia:MovieClip = new MovieClip();
MovieClip.prototype.setFrameRate = function(frameRate:Number)
{
var mc:MovieClip = this;
if (mc.tweenFaster != null)
{
Timer(mc.tweenFaster).stop();
}
mc.tweenFaster = new Timer(1000/frameRate);
mc.tweenFaster.addEventListener(TimerEvent.TIMER, timelineFaster);
mc.tweenFaster.start();
function timelineFaster(event:TimerEvent = null)
{
if (mc.currentFrame == mc.totalFrames)
{
mc.tweenFaster.stop();
mc.gotoAndStop(1);
}
else
{
trace(mc.currentFrame);
mc.nextFrame();
}
event.updateAfterEvent();
}
}
public function MainClass()
{
configureListeners();
request = new URLRequest("data/7/7.swf");
try
{
loader.load(request);
}
catch (error:Error)
{
trace("Unable to load requested document.");
}
}
private function configureListeners():void
{
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
loader.contentLoaderInfo.addEventListener(Event.OPEN, openHandler);
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressHandler);
loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
loader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
}
private function completeHandler(event:Event):void
{
loader.content.scaleX = 550/event.target.width;
loader.content.scaleY = 400/event.target.height;
mcMedia.addChild(loader);
mcMedia.setFrameRate(12);
addChild(mcMedia);
}
In as3, if you're just looking to change the framerate, use stage.frameRate = 12; or whatever;
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/Stage.html#frameRate
In AS3, while you can use prototypes, you generally don't. I'd rewrite your setFrameRate function (which is badly named, shouldn't it be more.. tweenFaster, or matchFrameRate or something?)
I'd make a helper function like this:
package util{
//imports
public class TweenFasterMC extends MovieClip{
public var mc:MovieClip;
public function matchFrameRate(frameRate:Number):void
{
if (tweenFaster != null)
{
Timer(mc.tweenFaster).stop();
}
tweenFaster = new Timer(1000/frameRate);
tweenFaster.addEventListener(TimerEvent.TIMER, timelineFaster);
tweenFaster.start();
}
function timelineFaster(event:TimerEvent = null):void
{
if (currentFrame == totalFrames)
{
tweenFaster.stop();
gotoAndStop(1);
}
else
{
trace(currentFrame);
nextFrame();
}
event.updateAfterEvent();
}
}
Also, clean up your event listeners, that strong timer event listener will cause a lot of problems if you have a lot of mc's your applying this functionality to.
As far as I know all MovieClips in one flash player instance (sharing the same 'stage') will run at the same speed - there is no way to have two clips running at different speeds. So to adjust the speed you have to resort to calling gotoAndStop() on all MovieClips in the loaded clip at the right time - that won't be fun.
Code along the lines that quoo is showing will only work if the loaded swf contains just 1 MovieClip (no nesting) as far as I can see.
It seems to me that the most likely reason why this wouldn't work is that it requires every clip you load to be a simple, completely non-dynamic animation that loops for ever. If the loaded content is that simple, why not just adjust it to look better at 30fps? (If it's extremely long, a JSFL script could automate the process of adding extra frames.) Alternately, if the content isn't that simple, then attempting to change its timing by calling nextFrame from elsewhere is not going to give you what you want.
With all that said, if you're sure this is what you want to do but you're getting 0 as a return for currentFrame in your loaded content, are you sure they are AS3 SWFs? If they aren't, AS3/AS2 interoperation is a hairy subject that will warrant reading up on.
This is a real hassle, I've been scouring the net for an answer. I have particles following a path, and I want to change the speed that these particles follow the path dynamically, without changing the whole movie. just the particles movie clip.
I've tried greensock, but, that doesn't really work like i need.. i'd think there would be something that you can change dynamically for each mc, but, no dice.
the stage.frameset is only for the whole movie... argggggggg..... sucks..