A Flash Developer Resource Site

Results 1 to 5 of 5

Thread: Dynamically add addEventListener in a for statement

  1. #1
    Junior Member
    Join Date
    Jul 2012
    Posts
    3

    Dynamically add addEventListener in a for statement

    Hi

    im building a simple xml based balloon race

    im using a single MovieClip (a balloon that moves from bottom to top over 100 frames).

    i've exported the MovieClip to Action Script an created Linkage

    inside a loop..
    i want to add an instance of the balloon for each player in a xml output file using addChild(mcClip);

    and also add an addEventListener for each mcClip to stop(); the mcClip at a certain frame for each player (the value is also extracted from the xml file)

    the movie works! the correct number of balloons are added...but only 1 of the instances stops moving! the other balloons keep playing over and over!

    so only 1 of the addEventListener events is working???

    for(var i:Number=0; i<xmlData.players.playerName.length(); i++){
    var mcClip:flyingBalloon = new flyingBalloon();
    mcClip.name = "balloon" + i
    addChild();

    mcClip.addEventListener(Event.ENTER_FRAME,stopAtFr ame,false,0,true);

    function stopAtFrame(evt:Event):void{
    if(mcClip.currentFrame==xmlPlayerPosition){
    mcClip.stop();
    mcClip.removeEventListener(Event.ENTER_FRAME,stopA tFrame);
    }
    }
    }

    this works but only 1 clip stops!

    Note: i've type this code into here manually, so if there's other errors (typo's ect), please ignore.


    Thanks, hope the above makes sense!

  2. #2
    Senior Member Awoogamuffin's Avatar
    Join Date
    Nov 2008
    Posts
    208
    Hey there Jado!

    You're almost there - all the balloons are created and have event listeners added to them. The problem is that you're not keeping track of your balloons.

    It's an annoying issues with asynchronous data - even though your handler function is nested within the for loop, the value for mcClip is not kept unique for each loop - rather mcClip points to the last flyingBalloon made. With asynchronous functions (which is what is happening here - the next frame event is called after the forloop has ended) nesting functions doesn't really help.

    This means that when you call the event handler, mcClip is only pointing to the last balloon that you created. The others don't have anything pointing to them anymore. This is why you should avoid weak reference event listeners - you could have lost your balloon to garbage collection! Though of course in this case no, because even though no variable referenced your balloons, they were on the stage and therefore protected from GC... still, be careful with weak references!

    There are a few ways to keep track of the ballons. I'll first give you 2 that don't really help in this situation, but probably will in another situation, then the third will be what's needed here.

    1- Create an array that stores each of the balloons. But in the handler, you would still have to loop through the array to find the balloon you want, but still, it's nice to keep track of them.

    2- You can get a child by name (And I see you've named each of your balloons uniquely) using the getChildByName() function of DisplayContainer (MovieClips and Sprites inherit DisplayContainer)

    http://help.adobe.com/en_US/FlashPla...Container.html

    3- Finally, and this is really useful, use the "target" property of the event to find the balloon. Look up the event class:

    http://help.adobe.com/en_US/FlashPla...nts/Event.html

    In the event handler, using evt.target will point you at the balloon you need. In this case, this is what you want to use.

    PHP Code:
    //Inside the for loop:
    var mcClip:flyingBalloon evt.target as flyingBalloon
    So to make your code work, I'd do something like this, though I haven't tested it or anything and it almost certainly contains bugs:

    PHP Code:
    for(var i:int=0i<xmlData.players.playerName.length(); i++)
    {
       var 
    mcClip:flyingBalloon = new flyingBalloon();
       
    addChild(mcClip);
       
    mcClip.addEventListener(Event.ENTER_FRAME,stopAtFrame);
    }

    function 
    stopAtFrame(evt:Event):void
    {
       var 
    mcClip:flyingBalloon evt.target as flyingBalloon;
       if(
    mcClip.currentFrame==xmlPlayerPosition)
       {
           
    mcClip.stop();
           
    mcClip.removeEventListener(Event.ENTER_FRAME,stopAtFrame);
       }

    Check out my blog showing the development of my flash game, the Dregs of War

  3. #3
    Junior Member
    Join Date
    Jul 2012
    Posts
    3
    Thanks! that works a treat!

    although now i'm struggling with the xmlPlayerPosition in the if statement.

    in my first post of this code xmlPlayerPositon was just a place holder (i was actually using a static value of 70)

    so the movie works but all the balloons now stop at frame 70.

    i've tried if(mcClip.currentFrame==xmlData.players.playerPosi tion[i])

    this doesn't work

    if i change mcClip.name = "balloon" + [i]

    to..
    mcClip.name = xmlData.players.playerPosition[i]

    and then in the if statement..
    if(mcClip.currentFrame==mcClip.name)

    this does work!

    i know this is not the way to go about this, plus it only works if i need to access 1 fixed value from each mcClip!, so i would like to explore 2 methods to do this better..

    1. get the xml statement to work
    if(mcClip.currentFrame==xmlData.players.playerPosi tion[i])

    2. assign attributes to each mcClip as they are created and then call them when needed.
    something like..

    mcClip.property("playerPOS") = xmlData.players.playerPosition[i])

    and then

    if(mcClip.currentFrame==mcClip.property("playerPOS "))

    is it possible to add custom properties to each mcClip as they are created? and then call them?

    Thanks

  4. #4
    Senior Member Awoogamuffin's Avatar
    Join Date
    Nov 2008
    Posts
    208
    Hey there!

    I'm glad it worked. As for your next question, the solution you've come with is fine - to be honest, I almost never use the .name attribute of MovieClips, so why not use it to store a variable you need?

    I guess issues arise when you have more complex objects that need more variables stored. I don't know how familiar you are with programming classes, but you could write a simple class that extends MovieClip and contains all the variables and methods you might need to access. If you're interested in that, there's loads of stuff online to help. A long time ago I wrote a series of tutorials on setting up a proper object-orientated workflow in flash which you can read here:

    http://flashgametutorials.blogspot.c...mmend-you.html

    But yeah, if the only variable you wish to store in each balloon is the frame at which it needs to stop, then I think that using the name variable is fine. But doesn't it cause problems if you have to MCs with the same name? I haven't tried, but certainly within the Flash editor it doesn't like it if you give two objects the same name...
    Check out my blog showing the development of my flash game, the Dregs of War

  5. #5
    Junior Member
    Join Date
    Jul 2012
    Posts
    3
    Thanks again!

    FYI: it seems mcClip.name does not have to be unique when loading/setting it's name in this way. i changed the xml data to use duplicate values and the movie still ran correctly

    But i've scraped that as you gave me an idea, and it seems to work!

    set the mcClip.name as the current cycle position of [i]

    then use..

    if(mcClip.currentFrame==xmlData.players.playerPosi tion[mcClip.name])

    to get the playerPosition of the related balloon.

    I can then use mcClip.name to get all the other player attributes i need from the xml file.

    i've never make a Class,i'm not a programmer , but i will check out your tutorials and give it a try!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center