Flash AS3 Loadmovie Error #1009 - External AS file - actionscript-3

We have created a program in Flash that uses an external actionscript file.
I'm trying to load/import this swf in another flash file but I'm getting a 'Error #1009: Cannot access a property or method of a null object reference'
I know this is to a reference in my external .as file but I'm not sure how to fix this
This is my code to load (and scale) the swf
var ld:Loader = new Loader();
addChild(ld);
ld.load(new URLRequest("tatton.swf"));
ld.contentLoaderInfo.addEventListener(Event.COMPLETE,function(evt) {
var mc = evt.target.content;
mc.scaleX=0.7031;
mc.scaleY=0.7031;
});
Anyone have any ideas?
Thanks
Edit: here is the full error code: TypeError: Error #1009: Cannot access a property or method of a null object reference. at Tatton()
And below is my .as file code:
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.utils.setTimeout;
import flash.utils.clearTimeout;
import flash.utils.getDefinitionByName;
public class Tatton extends MovieClip
{
public var active_clip:MovieClip;
public var to:Number;
public function Tatton()
{
// Create empty vector of movieclips;
stage.addEventListener(MouseEvent.CLICK, reset_timeout);
init();
}
public function reset_timeout(e:Event = null)
{
clearTimeout(to);
// 3 mins
to = setTimeout(fire_timeout, 150 * 1000);
}
public function fire_timeout():void
{
// Reset the system (and run attractor) if we're not on the attractor already.
if ( !(active_clip is Attractor))
{
init();
}
}
public function init()
{
// Reset globals
Globals.skip_menu_anim = false;
Globals.skip_staff_menu = false;
load_movie("Attractor");
reset_timeout();
}
public function load_movie(name:String):void
{
if (active_clip is MovieClip)
{
kill_active_movie();
}
active_clip = createInstance(name);
addChild(active_clip);
active_clip.startup();
}
public function kill_active_movie():void
{
active_clip.shutdown();
removeChild(active_clip);
active_clip = null;
}
public function createInstance(className:String):Object
{
var myClass:Class = getDefinitionByName(className) as Class;
var instance:Object = new myClass();
return instance;
}
}
}

try this
public function Tatton() {
addEventListener(Event.ADDED_TO_STAGE, stageAvailable);
}
private function stageAvailable(e:Event = null) {
removeEventListener(Event.ADDED_TO_STAGE, stageAvailable);
// Create empty vector of movieclips;
stage.addEventListener(MouseEvent.CLICK, reset_timeout);
init();
}
refer to this article to understand why

You need to add the event listener after you call Loader.load because contentLoaderInfo is null until load is called.

Related

Cast loaded SWF with designed interface in main class

First of all I read linked topic but unfortunately any of the tips didn't work for me: Casting a loaded SWF as an interface
My problem indeed is similiar, I have got created SWF (Content.swf) where Content.as which is document class there:
package {
import flash.display.MovieClip;
public class Content extends MovieClip implements IGame {
public function igameMethod():void {
trace("implemented method of IGame");
}
}
}
IGame interface (in the same directory as Content.as) contains sole method 'igameMethod'
package {
public interface IGame {
function igameMethod():void;
}
}
and such compiled SWF is loaded by Loader class in LoadSWF where Main.as is document class and it is something like that:
public class Main extends MovieClip {
private var swfLdr:Loader;
private var game:IGame;
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);
swfLdr = new Loader();
var r:URLRequest = new URLRequest("../lib/Content.swf");
var defaultLoaderContext:LoaderContext = new LoaderContext(true, ApplicationDomain.currentDomain);
//none of settings for ApplicationDomain doesnt' work (with checkPolicy or with or without ApplicationDomain.currentDomain set)
swfLdr.load(r,defaultLoaderContext);
this.addChild(swfLdr);
swfLdr.contentLoaderInfo.addEventListener(Event.COMPLETE, onExternalSWFLoaded);
//tried Event.INIT too without success
}
private function onExternalSWFLoaded(e:Event) : void {
var Game:Class = ApplicationDomain.currentDomain.getDefinition( "IGame" ) as Class;
if (e.target.content is IGame) {
trace("Is IGame");
}else {
//output of this condition is false
//so e.target.content is not IGame
trace("No its not IGame");
}
var Game:Class = ApplicationDomain.currentDomain.getDefinition( "IGame" ) as Class;
//tried to cast as class without success too
var gameContent: IGame = IGame(swfLdr.content); //app breaks here
// TypeError: Error #1034: Type Coercion failed: cannot convert LoaderSWF#87f0089 to IGame
}
I've got also IGame interace (duplicated to LoadSWF project) with the same package structure (in the same folder as document class) as Main.as to let LoadSWF use igameMethod() on Content.swf, but i can not use it because of TypeError: Error #1034: Type Coercion failed: cannot convert LoaderSWF#87f0089 to IGame. So the compiler can't convert this Content to IGame.
Have you got any idea, which would help me with this topic?
Thanks for any tips in advance.
Kindest regards Pawel

Passing variable value from function in a class in AS3

I'm working with as3 and I don't understand how to pass from a value on a function to a global variable. I have this code (in a .as file):
package {
public class loadInfo {
import flash.events.*;
import flash.net.*;
private var teamA:String;
public var urlLoader:URLLoader = new URLLoader( );
public function loadInfo() {
urlLoader.addEventListener(Event.COMPLETE, handleComplete);
urlLoader.dataFormat = URLLoaderDataFormat.VARIABLES;
urlLoader.load(new URLRequest("data.txt" ));
}
public function handleComplete( event:Event ):void {
this.teamA = urlLoader.data.teamA;
}
public function getTeamA():String{
return teamA;
}
}
}
What I'm doing with this code is to load several variables which are in a .txt file.
and in the .fla file I have:
import loadInfo;
var dat:loadInfo = new loadInfo();
trace(dat.getTeamA());
but the result is "null".
So, I have no clue what to do. Help is appreciated. Thanks.
The problem is that you don't wait for the loader to complete. It takes time to load that txt file and if you call getTeamA immediately, the loader isn't finished. You should do something like this:
var dat:loadInfo = new loadInfo();
dat.addEventListener(Event.COMPLETE, onDataLoaded);
function onDataLoaded(e:Event):void {
trace (dat.getTeamA());
}
And within loaderInfo:
public function handleComplete( event:Event ):void {
this.teamA = urlLoader.data.teamA;
dispatchEvent(new Event(Event.COMPLETE));
}
Should work properly. Keep in mind that loaderInfo must extend EventDispatcher (class loaderInfo extends EventDispatcher {)..

Actionscript 3: Access movieclips from array with for-loop

I am having some trouble with accessing the movieclips I've added as childs. From what I've read, a way to solve this is to add every new movieclip to an array, and then loop through this array when I want to change something about all the movieclips.
In my case I want to scale them.
This is how I've tried to implement this function:
package
{
import flash.display.MovieClip;
import flash.utils.Dictionary;
import flash.events.MouseEvent;
import Airport;
public class Main extends Sprite
{
public var tile:MovieClip
public var bg_image:Sprite;
public var airport:Airport;
public static var airportDict:Dictionary = new Dictionary();
public static var collectedAirportArray:Array = new Array();
public function Main()
{
addEventListener(Event.ADDED_TO_STAGE, init);
}
public function init(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// airportDict is being filled up here.. but that's not really relevant for my problem
bg_image = new Image();
addChild(bg_image);
bg_image.addEventListener(MouseEvent.CLICK, testfunction);
for (var k:Object in airportDict)
{
var airport:Airport = new Airport(k,airportDict[k]["x"], airportDict[k]["y"]);
collectedAirportArray.push(collectedAirportArray);
bg_image.addChild(airport);
}
}
private function testfunction(evt:MouseEvent):void
{
for each (tile in collectedAirportArray)
{
tile.scaleY = 2 * tile.scaleY;
}
}
}
}
This give me the error message TypeError: Error #1034: Type Coercion failed: cannot convert []#30977eb1 to flash.display.MovieClip.
at Main/testfunction() when clicking on the bg_image
You have an error in where you are making the array. You have there collectedAirportArray.push(collectedAirportArray); - you're basically pushing an array into itself. Nice snakey, they said. You should instead push the newly created airport in there:
collectedAirportArray.push(airport);
If your airport is any kind of DisplayObject your code should work.
What AirPort class is extending? If it extends MovieClip then try type casting like so:
private function testfunction(evt:MouseEvent):void
{
for each (tile in collectedAirportArray)
{
var myTile:MovieClip = MovieClip(tile);
myTile.scaleY = 2 * myTile.scaleY;
}
}

How to call a function inside .FLA from an AS Class

My Main class is added to the stage of my .fla and I want to remove and re-add/"restart" the class when it finishes animating. All of my animations are happening in Main and are added to the display tree inside Main. How can I run the finishNow() function from within Main.as?
The .fla file:
var run:Main = new Main(this);
stage.addChild(run);
function finishNow() {
stage.removeChild(run);
var run:Main = new Main(this);
stage.addChild(run);
}
The Main.as file:
var stageHolder:Object;
public function Main(stageHolderTemp) {
stageHolder = stageHolderTemp;
trace(stageHolder);
}
function callFinishFunction():void {
// how to call finishNow() function from .fla file here
}
EDIT: The design of the program has changed. Still trying to do the same thing (call finishNow() function – but it is now in Program.as). It all works fine, except throws an error for program.finishNow();:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
The .fla file:
It now does not contain any code. It is linked to Program.as.
The Program.as file:
package {
import flash.display.MovieClip;
public class Program extends MovieClip {
public function Program() {
startNow();
}
function startNow() {
var run:Main = new Main(this);
addChild(run);
}
function finishNow() {
removeChild(run);
var run:Main = new Main(this);
addChild(run);
}
}
}
The Main.as file:
package {
import flash.display.Sprite;
public class Main extends Sprite
{
var stageHolder:Object;
public var program:Program;
public function Main(stageHolderTemp) {
stageHolder = stageHolderTemp;
trace(stageHolder);
someFunctionsThatDrawGraphics();
}
function callFinishFunction():void {
// how to call finishNow() function from Program.as file here?
program.finishNow();
}
}
}
You can call addframeScript to call FLA function.
If your .fla linked to Main.as file, you can directly called. try this:
public function Main() {
finishNow();
}
.fla code
function testFunction()
{
trace("111");
}
.as file
package {
import flash.display.MovieClip;
public class Main extends MovieClip {
public function Main() {
testFunction();
}
}
}
Actually , no need to create the class object every time . It will be enough to call a function in that class every time .
But for your question ..
Try this ....
In program.as
var run:Main = new Main(this);
run.addEventListener("FINISH",finishNow);
addChild(run);
function finishNow(e:Event)
{
}
In main.as ,
function callFinishFunction():void
{
dispatchEvent(new Event("FINISH"));
}

Initialize Assets after Preload

Whenever I export the .swf file of my Flash game, I am receiving "TypeError: Error #1009: Cannot access a property or method of a null object reference.", along with a Runtime Shared Library Preloading Warning for my preloader. I have my timeline organized so that the first and third frames are both empty along with a stop(); command in the Actions layer. The second frame contains a single MovieClip that contains all of my exported assets, which are going to be initialized in the third frame of the timeline. None of my assets, except for the preloader, are exported in the first frame. What changes should I make to my Document Class for it to initialize the assets in the third frame?
Document Class:
package com.gameEngine.documentClass
{
import flash.events.*;
import flash.display.*;
import flash.geom.Point;
import com.gameEngine.assetHolders.*;
import com.gameEngine.assetHolders.Levels.*;
public class Document extends MovieClip
{
private static var _document:Document;
private var preloader:Preloader;
public var mcMain:Player;
public var restartButton:RestartButton;
public var spawnArea:SpawnArea;
public var level_1:Level_1;
public var level_2:Level_2;
public var level_3:Level_3;
public function Document()
{
addEventListener(Event.ADDED_TO_STAGE, init);
_document = this;
preloader = new Preloader(390, this.loaderInfo);
this.addChild(preloader);
preloader.addEventListener("loadComplete", loadAssets);
preloader.addEventListener("preloaderFinished", showLogo);
mcMain = new Player(this);
restartButton = new RestartButton(this);
spawnArea = new SpawnArea();
level_1 = new Level_1(this);
level_2 = new Level_2(this);
level_3 = new Level_3(this);
this.addChild(restartButton);
this.addChild(spawnArea);
this.preloader.x = 400;
this.preloader.y = 250;
restartButton.x = 822.95;
restartButton.y = 19;
spawnArea.x = 400;
spawnArea.y = 250;
trace ("Document Class Initialized");
// constructor code
}
public static function getInstance():Document
{
return _document;
}
private function loadAssets(event:Event):void
{
this.play();
}
private function showLogo(event:Event):void
{
this.removeChild(preloader);
}
public function init(event:Event)
{
if (stage.contains(spawnArea))
{
addChild(mcMain);
}
mcMain.x = spawnArea.x;
mcMain.y = spawnArea.y;
}
}
}
Preloader Class:
package com.gameEngine.assetHolders
{
import com.gameEngine.documentClass.*;
import flash.display.*;
import flash.events.*;
public class Preloader extends MovieClip
{
private var fullWidth:Number;
public var loaderInfo:LoaderInfo;
public function Preloader(fullWidth:Number = 0, loaderInfo:LoaderInfo = null)
{
this.fullWidth = fullWidth;
this.loaderInfo = loaderInfo;
addEventListener(Event.ENTER_FRAME, checkLoad);
}
private function checkLoad (event:Event):void
{
if (loaderInfo.bytesLoaded == loaderInfo.bytesTotal && loaderInfo.bytesTotal != 0)
{
dispatchEvent(new Event("loadComplete"));
phaseOut();
}
updateLoader(loaderInfo.bytesLoaded / loaderInfo.bytesTotal);
}
private function updateLoader(num:Number):void
{
progressBar.width = num * fullWidth;
}
private function phaseOut():void
{
removeEventListener(Event.ENTER_FRAME, checkLoad);
progressBar.gotoAndPlay(2);
if (progressBar.currentFrame == progressBar.totalFrames)
{
phaseComplete();
}
}
private function phaseComplete() : void
{
dispatchEvent(new Event("preloaderFinished"));
}
}
}
You have a lot of race conditions going on here. Many of these events could occur at relatively random times in relation to one another . . . you have to think asynchronously. That is, there can be no assumption that any object exists. E.g., in Document.init(), you check is if the spawnArea exists, but it is almost guaranteed not to at that point, and you never check for it again.
Without making any specific changes, I can recommend a generic solution. For any object (objB) you want loaded after another object (objA) is loaded, have objB created in the objA's ADDED_TO_STAGE handler. A simple example would be:
var objA:Whatever;
var objB:WhateverElse;
[...]
objA = new Whatever();
objA.addEventListener(Event.ADDED_TO_STAGE, objAAddedHnd);
[...]
public function objAAddedHnd(event:Event)
{
// remove the event, if no longer needed:
objA.removeEventListener(Event.ADDED_TO_STAGE, objAAddedHnd);
objB = new WhateverElse();
objB.addEventListener(Event.ADDED_TO_STAGE, objBAddedHnd);
}
[...]
public function objBAddedHnd(event:Event)
{
// remove the event, if no longer needed:
objB.removeEventListener(Event.ADDED_TO_STAGE, objBAddedHnd);
// and so on . . .
}
At this point, it shows that you would need to plan the timeline of object creation.