Forum ActionScript 3.0 Listeners not being fired...

Problems and discussions relating to ActionScript 3.0 here.

Listeners not being fired...

Postby default0 » November 20th, 2010, 1:48 pm

Hey

I've got a very weird problem. It appears that, if my game is loaded over browser cache, some listeners aren't firing (or aren't even created?), but if the SWF is loaded entirely, everything works just fine.

Due to that, my login/register form does not work anymore.

I have it set up so, that first it shows a loading textfield that displays percent of how much has been loaded and after the game has been loaded it fires the CreateLoginForm() function which addChilds all the textfields and their listeners, and those listeners aren't fired for SOME reason if the game SWF isn't being loaded entirely, but by browser cache.

Any clues/ideas/hints are more than welcome, I'm pretty much clueless why this is happening...

EDIT: (Possibly) useful information: I'm using most recent version of Firefox

Best regards
Try to play my Game: -->BlackGalaxy<--
User avatar
default0
 
Posts: 115
Joined: February 2nd, 2010, 6:46 pm
Location: Germany

Re: Listeners not being fired...

Postby azuanagames » November 20th, 2010, 7:01 pm

Welcome to the pain of AS3!

I'm not entirely sure how your code is laid out. But this is what I do:

In my constructor for my Document class file: (Game starts on "preloader" frame)
Code: Select all
  addEventListener(Event.ENTER_FRAME, handleEnterFrame);

  private function handleEnterFrame(event:Event):void {
    if (loaderInfo.bytesLoaded == loaderInfo.bytesTotal) {
      // If fully loaded
      removeEventListener(Event.ENTER_FRAME, handleEnterFrame);
     
      gotoAndStop("game");
      addEventListener(Event.ENTER_FRAME, handleStartGame);
    }
  }

  private function handleStartGame(event:Event):void {
    removeEventListener(Event.ENTER_FRAME, handleStartGame);
    // Player io code here
  }


At times, if I have stage variables, I have found that I need to do this:
Code: Select all
  private function handleStartGame(event:Event):void {
    if (!importantStageVariable) return; // This would return null if Flash has not yet loaded the variable

    removeEventListener(Event.ENTER_FRAME, handleStartGame);
    // Player io code here
  }


Good luck!
azuanagames
 
Posts: 157
Joined: April 29th, 2010, 10:59 pm

Re: Listeners not being fired...

Postby default0 » November 20th, 2010, 11:21 pm

Thx for good luck, guess I'll need it.

My code uses ProgressEvent.PROGRESS to detect load progress and Event.COMPLETE to detect when load is complete, not enterframe handlers, I'm not sure if that's it, but the problem is not sth. not being loaded but listeners acting weird.

The script I fire once the load is complete is this one:

Code: Select all
public function LoadComplete(e:Event):void
{
   gotoAndStop(3); // game frame
         
   Garbage(); // this one just removes the text field showing how much the loading has progressed
   
   CreateLoginForm(); // this one creates the login textfields and such
}


This function works just fine, what is giving me trouble is CreateLoginForm() function, which looks like this (sorry 'bout fat function):
Code: Select all
public function CreateLoginForm():void
      {
         LoginNameTxt = CreateTextField(10, StageHeight * 0.4, StageWidth - 20, 50, GetGlobalTextFormat(40, "left"), "Username");
         LoginNameTxt.background = true;
         LoginNameTxt.backgroundColor = 0x666666;
         LoginNameTxt.type = TextFieldType.INPUT;
         LoginNameTxt.addEventListener(FocusEvent.FOCUS_IN, function(f:FocusEvent):void
         {
            LoginNameTxt.text = "";
            Action = "login";
         }, false, 0, true);
         addChild(LoginNameTxt);
         LoginPasskeyTxt = CreateTextField(10, StageHeight * 0.5, StageWidth - 20, 50, GetGlobalTextFormat(40, "left"), "Passkey");
         LoginPasskeyTxt.displayAsPassword = true;
         LoginPasskeyTxt.setTextFormat(GetGlobalTextFormat(40, "left"));
         LoginPasskeyTxt.background = true;
         LoginPasskeyTxt.backgroundColor = 0x666666;
         LoginPasskeyTxt.type = TextFieldType.INPUT;
         LoginPasskeyTxt.addEventListener(FocusEvent.FOCUS_IN, function(f:FocusEvent):void
         {
            LoginPasskeyTxt.text = "";
            Action = "login";
         }, false, 0, true);
         addChild(LoginPasskeyTxt);
         
         var loginDescriptionTxt:TextField = CreateTextField(10, StageHeight * 0.3, StageWidth - 20, 50, GetGlobalTextFormat(40, "left"), "Login with an existing account.");
         loginDescriptionTxt.selectable = false;
         addChild(loginDescriptionTxt);
         var registerDescriptionTxt:TextField = CreateTextField(10, StageHeight * 0.6, StageWidth - 20, 50, GetGlobalTextFormat(40, "left"), "Or Register a new one.");
         registerDescriptionTxt.selectable = false;
         addChild(registerDescriptionTxt);
         
         RegisterNameTxt = CreateTextField(10, StageHeight * 0.7, StageWidth - 20, 50, GetGlobalTextFormat(40, "left"), "Username"); LoginNameTxt.background = true;
         RegisterNameTxt.background = true;
         RegisterNameTxt.backgroundColor = 0x666666;
         RegisterNameTxt.type = TextFieldType.INPUT;
         RegisterNameTxt.addEventListener(FocusEvent.FOCUS_IN, function(f:FocusEvent):void
         {
            RegisterNameTxt.text = "";
            Action = "register";
         }, false, 0, true);
         addChild(RegisterNameTxt);
         RegisterPasskeyTxt = CreateTextField(10, StageHeight * 0.8, StageWidth - 20, 50, GetGlobalTextFormat(40, "left"), "Passkey");
         RegisterPasskeyTxt.background = true;
         RegisterPasskeyTxt.backgroundColor = 0x666666;
         RegisterPasskeyTxt.type = TextFieldType.INPUT;
         RegisterPasskeyTxt.addEventListener(TextEvent.TEXT_INPUT, function(t:TextEvent):void
         {
            RegisterPasskeyTxt.displayAsPassword = true;
         }, false, 0, false);
         RegisterPasskeyTxt.addEventListener(FocusEvent.FOCUS_IN, function(f:FocusEvent):void
         {
            RegisterPasskeyTxt.text = "";
            Action = "register";
         }, false, 0, false);
         addChild(RegisterPasskeyTxt);
         RegisterPasskeyConfirmTxt = CreateTextField(10, StageHeight * 0.9, StageWidth - 20, 50, GetGlobalTextFormat(40, "left"), "Confirm passkey");
         RegisterPasskeyConfirmTxt.background = true;
         RegisterPasskeyConfirmTxt.backgroundColor = 0x666666;
         RegisterPasskeyConfirmTxt.type = TextFieldType.INPUT;
         RegisterPasskeyConfirmTxt.addEventListener(TextEvent.TEXT_INPUT, function(t:TextEvent):void
         {
            RegisterPasskeyConfirmTxt.displayAsPassword = true;
         }, false, 0, false);
         RegisterPasskeyConfirmTxt.addEventListener(FocusEvent.FOCUS_IN, function(f:FocusEvent):void
         {
            RegisterPasskeyConfirmTxt.text = "";
            Action = "register";
         }, false, 0, false);
         addChild(RegisterPasskeyConfirmTxt);
         
         var logo:Logo = new Logo();
         addChildAt(logo, 0);
         
         stage.addEventListener(KeyboardEvent.KEY_DOWN, LoginOrRegister);
         
         GarbageList.push(logo, LoginNameTxt, LoginPasskeyTxt, loginDescriptionTxt, registerDescriptionTxt, RegisterNameTxt, RegisterPasskeyConfirmTxt, RegisterPasskeyTxt);
      }


Now notice the places where I attach listeners to the text fields to make them behave like they should.
The thing is, when the SWF is loaded entirely, this script works exactly as it should.
But when it is loaded by cache, all listeners I'm attaching are firing once (and this is right the moment where I create them, not when the respective event occurs) and then never again. And this is exactly why I'm that confused. Apparently the logo, the textfields, everything is fine & has loaded (as the screen itself looks just as it should), but the listeners fail.

Still any ideas?
Try to play my Game: -->BlackGalaxy<--
User avatar
default0
 
Posts: 115
Joined: February 2nd, 2010, 6:46 pm
Location: Germany

Re: Listeners not being fired...

Postby azuanagames » November 21st, 2010, 1:52 am

I don't have a firm grasp on when to use weak-referenced listeners. Can you try strong references for this?
azuanagames
 
Posts: 157
Joined: April 29th, 2010, 10:59 pm

Re: Listeners not being fired...

Postby default0 » November 21st, 2010, 12:33 pm

azuanagames wrote:I don't have a firm grasp on when to use weak-referenced listeners. Can you try strong references for this?


I had them originally, didn't work, too.
I just set them back to strong-references and tested again and... oh wonder, it did not work.

You should use Weak-Referenced listeners for unknown functions, like I do there (I'm just assigning it a function, not naming it, so I cannot use removeEventListener() later on, so weak-referenced listeners are actually the better choice here), or when you remove an object and are not sure if all of it's listener removed, just make all the listeners weak-referenced and flash will garbage them automatically a while after your object was removed =)

Thanks for trying to help, I really appreciate it. I've built myself a work-around so it works more or less without the listeners, but this still is bothering me, so any ideas what this could be are welcome.

Best regards
Try to play my Game: -->BlackGalaxy<--
User avatar
default0
 
Posts: 115
Joined: February 2nd, 2010, 6:46 pm
Location: Germany

Re: Listeners not being fired...

Postby Benjaminsen » November 23rd, 2010, 9:53 am

Strange behavior when getting files from cache is nothing new. More often than not they turn out to be because you are trying to interact with an object that has been loaded but not yet initialized. Initialization happens when the loaded object receives it's first enterFrame.

It is possible to write code where this does not happen but you have to make sure everything happen in a very precise order.
In your case a much simpler fix would be:

Code: Select all
public function LoadComplete(e:Event):void
{
   gotoAndStop(3); // game frame
   Garbage(); // this one just removes the text field showing how much the loading has progressed
   setTimeout(function():void{
      CreateLoginForm(); // this one creates the login textfields and such
   },1)
}
Benjaminsen
.IO
 
Posts: 1444
Joined: January 12th, 2010, 11:54 am
Location: Denmark

Re: Listeners not being fired...

Postby default0 » November 23rd, 2010, 3:25 pm

Thanks for explanation and help, really helped in some ways.

But, strangely enough, setTimeout() makes four of the listeners to be actually working, and the rest not :?
Shortly after I figured: "The listeners with strong reference are working, the ones with weak reference not" and confusion rised up, still, I just set all of them to strong-reference and it works, but doesn't clear up my head :?

I would actually prefer to weak-reference them, but they seem to be garbaged in the meantime, making it impossible for me to weak-reference them...
Try to play my Game: -->BlackGalaxy<--
User avatar
default0
 
Posts: 115
Joined: February 2nd, 2010, 6:46 pm
Location: Germany

Re: Listeners not being fired...

Postby azuanagames » November 23rd, 2010, 3:58 pm

default0 wrote:Thanks for explanation and help, really helped in some ways.

But, strangely enough, setTimeout() makes four of the listeners to be actually working, and the rest not :?
Shortly after I figured: "The listeners with strong reference are working, the ones with weak reference not" and confusion rised up, still, I just set all of them to strong-reference and it works, but doesn't clear up my head :?

I would actually prefer to weak-reference them, but they seem to be garbaged in the meantime, making it impossible for me to weak-reference them...


That's exactly what I saw when I tried using weak-references, which is why I don't trust it! I had weak references on my Tweens (to get a notification when the tween was complete,) but they would sometimes work and sometimes not!

Someday I hope to fully understand those weak references! Sheesh.
azuanagames
 
Posts: 157
Joined: April 29th, 2010, 10:59 pm


Return to ActionScript 3.0