Loading an external SWF throw an error - actionscript-3

I am trying to load an External swf.
But it throws an error when I compile.
ArgumentError: Error #1063: Argument count mismatch on Main/init(). Expected 0, got 1.
at flash.display::DisplayObjectContainer/addChild()
at flash.display::Stage/addChild()
at MainSWF/onLoadedAction()
Swfloader Class
public function MainSWF():void
{
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
_loader = new Loader();
_my_url = new URLRequest("Main.swf");
_loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgressAction);
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadedAction);
_loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, IOErrorAction);
_loader.load(_my_url);
}
private function onLoadedAction(e:Event):void
{
var mc:Sprite = new Sprite();
mc.addChild(_loader.content);
trace(stage);
stage.addChild(mc);
_loader.removeEventListener(ProgressEvent.PROGRESS, onProgressAction);
}

Init is being called from somewhere else without passing the Event as an argument. Simple solution is to change your init code to look like this:
private function init(e:Event = null):void
{
}
Also you should change your ADDED_TO_STAGE code to look like this:
public function MainSWF():void
{
if(stage){
init();
}else{
addEventListener(Event.ADDED_TO_STAGE, init);
}
}
If you're already added to the stage before you've added the listener, (which is why we check and see if stage is define) then you're never going to fire the ADDED_TO_STAGE event again, unless you add/remove your main swf from the timeline which you most likely won't be doing. So, if you do include that bit of code then it only makes sense to modify the following code as well:
removeEventListener(Event.ADDED_TO_STAGE, init);
to
if(hasEventListener(Event.ADDED_TO_STAGE)){
removeEventListener(Event.ADDED_TO_STAGE, init);
}
Obviously the reason for checking to see if the listener exists is because we may have just jumped right to the init function inside the constructor, because the stage was already present (meaning this swf class was already added to the display list while or before our constructor code executed).

Related

AS3 - Access MovieClip from stage within a class

I have been stuck on this for a long time and have looked at past questions on here about this similar issue such as this post: How do I access a movieClip on the stage using as3 class?.
I use the constructor to listen for the ADDED_TO_STAGE event, and then initiate the main function to set up the eventListeners from the ADDED_TO_STAGE handler. Within the same handler I also try to get a MovieClip from the stage using the following code:
player = stage.getChildByName("player") as MovieClip;
player is defined globally as a MovieClip.
Within another handler (after the class has been added to the stage) I set the player to go to an particular frame label using player.gotoAndStop("jump");. However an output warning shows up saying "Cannot access a property or method of a null object reference".
Here is the code which I use:
public var player:MovieClip;
public function PlayerControl():void {
this.addEventListener(Event.ADDED_TO_STAGE, addedToStage);
}
private function addedToStage(event:Event):void{
removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
player = stage.getChildByName("player") as MovieClip;
}
private function enterFrameHandler(event:Event):void{
if(up == true && moviePlaying == false){
player.gotoAndStop("jump");
moviePlaying = true;
}
}

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) Functions

I managed to fix the whole null stage error by following MJW's guide on debugging Error #1009. But now the function that initializes the bullets doesn't get called.
Snippets:
if (stage) {
 init();
} else {
addEventListener(Event.ADDED_TO_STAGE, init);
}
...
private function init(event:Event = null) {
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.addEventListener(Event.ENTER_FRAME, shoot);
}
...
private function shoot(event:Event) {
var bullet:EnemyBullet = new EnemyBullet();
stage.addChild(bullet);
bullet.x = enemy.x;
bullet.y = enemy.y;
bullet.theta = Math.random() * 360;
bManager.bulletVector.push(bullet);
}
Note that when I put trace() within the second two functions, nothing happens, but the addEventListener() in the first snippet does get called (or so I think).
As a general practice, stage should not be referenced - especially in your case, where your reference is solely to add instances of your bullet class. If it's a matter of z-index, you could instead have a layer in which bullets are placed on top of other display objects on the display list.
Besides complexities loading multiple SWFs on a single stage, your code would become nice isolated functional units by adding display objects to their own hierarchy of the display list. Or, you could leverage a MVC pattern whereby a controller manipulated views.
In order for your code to work, that class must either be the main function of the SWF or added to stage.
If it's the main function of the SWF, init() will be called.
Otherwise, assure it's getting added to the display list via an addChild().
Do you really intend to fire a bullet every frame? That could be 24 to 60 bullets a second. You might want to throttle that with some probability whether a bullet with fire.
Say this was a battlefield, and your battlefield class was added to stage, it could be implemented as this:
package
{
import flash.display.Sprite;
import flash.events.Event;
[SWF(percentWidth = 100, percentHeight = 100, backgroundColor = 0x0, frameRate = 30)]
public class Battlefield extends Sprite
{
public function Battlefield()
{
if (stage)
init();
else
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
protected function addedToStageHandler(event:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
init();
}
protected function init():void
{
addEventListener(Event.ENTER_FRAME, frameHandler);
}
protected function frameHandler(event:Event):void
{
var odds:Number = Math.random();
trace((odds < 0.1 ? "Fire! " : "Skip...") + "Odds were: " + odds);
}
}
}
Which would output:
Skip... Odds were: 0.3539872486144304
Skip... Odds were: 0.742108017206192
Fire! Odds were: 0.025597115512937307
Skip... Odds were: 0.7608889108523726
Fire! Odds were: 0.08514392375946045
Skip... Odds were: 0.27881692815572023
Beyond Stage3D, I've never been fond of this initialization pattern, as you could just as easily rely on stage events, as in:
package
{
import flash.display.Sprite;
import flash.events.Event;
[SWF(percentWidth = 100, percentHeight = 100, backgroundColor = 0x0, frameRate = 30)]
public class Battlefield extends Sprite
{
public function Battlefield()
{
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
protected function addedToStageHandler(event:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);
addEventListener(Event.ENTER_FRAME, frameHandler);
}
protected function removedFromStageHandler(event:Event):void
{
removeEventListener(Event.ENTER_FRAME, frameHandler);
removeEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
protected function frameHandler(event:Event):void
{
var odds:Number = Math.random();
trace((odds < 0.1 ? "Fire! " : "Skip...") + "Odds were: " + odds);
}
}
}
Therefore, upon added to stage the class initiates its actions, and upon removed from stage the class terminates its actions.
I think the issue is in the first block.
you are checking for stage, if stage is not null, then use a added to stage listener.
you should only be using addEventListener(Event.ADDED_TO_STAGE, init);
however, this is assuming that the class is DisplayObject subclass, objects that do not get added to stage cannot call the ADDED_TO_STAGE listener

Loading external SWF and last version of FD

(I'm working with FlashDevelop)
I'm having issue loading some external swfs in my project. This worked great until a few month back when they switched the preloader integration with :
[Frame(factoryClass="Preloader")]
Since then my swf loaded with a Loader() doesn't show.
Any idea of what changed ?
Thanks !
Code :
public class Main extends Sprite
{
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);
// entry point
loadMovie("Dots.swf");
}
private function loadMovie(url:String):void {
var mLoader:Loader = new Loader();
mLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
mLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgressHandler);
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteHandler);
mLoader.load(new URLRequest(url));
}
private function onCompleteHandler(loadEvent:Event):void {
trace("COMPLETE");
addChild(loadEvent.currentTarget.content);
}
private function onProgressHandler(event:ProgressEvent):void {
trace("progressHandler: bytesLoaded=" + event.bytesLoaded + " bytesTotal=" + event.bytesTotal);
}
private function ioErrorHandler (e:IOErrorEvent):void {
trace("ERROR");
}
}
Is "COMPLETE" getting traced out? I can't tell too much from the code you posted here, there could be something else going on, particularly in Dots.swf.
The one thing I see right off the bat is that your loader object may be getting garbage collected, but if it is tracing out "COMPLETE" that definitely is not the case. Try adding loader to the display list right away and see if that makes a difference. eg:
var mLoader:Loader = new Loader();
addChild(mLoader);
I do all my work in Flash Develop and have not had any issues with this. If you are able to share more code, or example project, I could investigate further.

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.