A Flash Developer Resource Site

Results 1 to 7 of 7

Thread: Weird for loop issue

  1. #1
    Ryan Thomson EvolveDesigns's Avatar
    Join Date
    Oct 2001
    Location
    British Columbia
    Posts
    3,338

    Weird for loop issue

    Hey all, I'm new to as3 and I can't understand why this doesn't work. Here's the code:

    Actionscript Code:
    for(var i:Number=0;i<def.length;i++)
    {
        this["term" + i].addEventListener(MouseEvent.MOUSE_DOWN, function(evt:MouseEvent){
        startMove(evt, i)});

        this["term" + i].addEventListener(MouseEvent.MOUSE_UP, function(evt:MouseEvent){
        stopMove(evt, i)});
    }

    Expected outcome:
    Actionscript Code:
    this.term0.addEventListener(MouseEvent.MOUSE_DOWN, function(evt:MouseEvent){
        startMove(evt, 0)});

    this.term1.addEventListener(MouseEvent.MOUSE_DOWN, function(evt:MouseEvent){
        startMove(evt, 1)});

    What is actually happening:
    Actionscript Code:
    this.term0.addEventListener(MouseEvent.MOUSE_DOWN, function(evt:MouseEvent){
        startMove(evt, 7)});

    this.term1.addEventListener(MouseEvent.MOUSE_DOWN, function(evt:MouseEvent){
        startMove(evt, 7)});

    So somehow the startMove/stopMove is always being sent the last number in my sequence, but the term variable is being sent the correct sequence and yet they are both populated by 'i'...

    Can anyone provide any views on this for me? I don't see how this outcome is even possible!

    Thanks!
    Evolve Designs Interactive Media
    the natural selection

  2. #2
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    The variable i is a single variable. Each of the anonymous functions you set as listeners in the loop uses the same i. You could have another function which takes i and outputs a function to use as a listener, but I am sure there's a better way to do whatever it is you're trying to do. The solution will probably use the currentTarget property of event rather than trying to pass an index to some function.

    Some other things that look fishy:
    1. sequentially named instances. Put them in an array instead. That is, instead of having independent things called term0 through term7, have an array terms with all your terms in it.
    2. You are testing against the length of def, but not using def anywhere in your loop. What is def, and what makes it the same length as the number of terms? And why aren't you actually using it?

  3. #3
    Ryan Thomson EvolveDesigns's Avatar
    Join Date
    Oct 2001
    Location
    British Columbia
    Posts
    3,338
    Thanks! I'm going to have to think about your reply for a bit... In particular, the currentTarget property which I've never heard of haha.

    1. sequentially named instances. Put them in an array instead.

    - These are movieclips which house a text field. I named them that way so the array index that passes the term to the movieclip corresponds with the number associated with the given movieclip label (if that sentence makes any sense).

    2. You are testing against the length of def, but not using def anywhere in your loop. What is def, and what makes it the same length as the number of terms? And why aren't you actually using it?

    - I'm making a term/definition drag and drop interactive. Def is an array of definitions, term is an array of terms and both make up a 2-d array called termAndDef. I set the for loop based on the amount of definitions which allows me to dynamically pass the code to each listener function without having to hard code each.

    If I hard code all the listeners my interactive works perfectly, I'm just trying to find a way to create them (and the draggable movieclips) based on the amount of term/definitions rather than forcing the person populating the drag and drop (xml) to always use a set amount of terms.

    I come from the past when I could spaghetti code my way though action script 2...
    Evolve Designs Interactive Media
    the natural selection

  4. #4
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Putting things on the display through the IDE and giving them sequential names makes sense only because the IDE does not provide a way to say "these things are all part of a collection. So, create a collection as soon as you can.

    Either I don't get what you mean by termAndDef, or 2-d array doesn't mean what you think it does. Do you have something in your 2-d array for term 3 and def 0? Or just term 1 / def 1, term2 / def 2, etc?

    Code:
    var terms:Array = [];
    for (var i:int = 0; i < 8; i++){
      terms.push(getChildByName("term"+i));
    }
    Now if you need to do something with all your terms, you have them in a real array. Of course, if all you do with them is the initial adding of listeners, then this doesn't actually buy you anything except my approval.

    Code:
    function startMove(evt:MouseEvent):void{
      var thing:MovieClip = MovieClip(evt.currentTarget);
      //do stuff with thing.  thing will be the clip which was moused down on.
    }

  5. #5
    Ryan Thomson EvolveDesigns's Avatar
    Join Date
    Oct 2001
    Location
    British Columbia
    Posts
    3,338
    Thanks so much, this part below is a game changer for me:
    Actionscript Code:
    function startMove(evt:MouseEvent):void{
      var thing:MovieClip = MovieClip(evt.currentTarget);
      //do stuff with thing.  thing will be the clip which was moused down on.
    }

    As to your term array, where would you store the definition to each term then?

    This is how I've set up my arrays presently. First I create my 2-d (or perhaps a better name) array
    Actionscript Code:
    var termAndDef:Array = new Array(term,def);

    THen I pull everything from the xml

    Actionscript Code:
    var myxml = new XML(e.target.data);
        var questionLoop = myxml.question.length();
       
        for (var i=0; i<questionLoop; i++)
        {
            for(var j:Number=0; j<myxml.question[i].q.length(); j++)
            {
                if(myxml.question[i].attribute("type") == "td")
                {
                    term.push(myxml.question[i].q[j].attribute("term"));
                    def.push(myxml.question[i].q[j]);
                }
            }
        }

    So if termAndDef[0][0] = dog i know that termAndDef[1][0] will be the correct definition. termAndDef[0][1] = cat, termAndDef[1][1] = cat definition

    Here's a sample node from my xml:
    Code:
    	<question type="td">
    	<q term="brown">The colour of my eyes.</q> 
    	<q term="blue">The colour of my pants.</q> 
    	<q term="techno">The make of my bike.</q> 
    	<q term="shawnigan">Where I live.</q> 
    	<q term="water">Where fish live.</q>
    	<q term="car">A thing that people drive around.</q>
    	<q term="square">A four sided shape.</q>
    	<q term="ninja">The most powerful animal on Earth.</q> 
    	</question>
    Last edited by EvolveDesigns; 03-24-2011 at 03:58 PM.
    Evolve Designs Interactive Media
    the natural selection

  6. #6
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Parallel arrays (which is essentially what you have there in termAndDef) are a very poor substitute for a proper class. termAndDef is fairly useless. All you've done is provide an alias for term (termAndDef[0]) and an alias for def (termAndDef[1]). If you had multiple sets of these, maybe that would be something. Or if you were passing them around together, maybe.

    Apparently you have various MovieClip termXs which control the visual appearance of a term(?), you have an array called term which contains a series of Strings, and an array called def which contains a series of "correct answers". And all three of these collections are only associated by the fact that the corresponding entries happen to be at the same indices in each.

    By contrast, here is a simple class which defines the relationship between all that information. You could have an array of these instead of 3 fragile-ly associated arrays of stuff.

    Code:
    public class TermClip extends Sprite {
      public var def:String;
      private var termtf:TextField;
    
      public function TermClip(t:String, d:String){
        termtf = new TextField();
        addChild(termtf);
        termtf.text = t;
        def = d;
    
        addEventListener(MouseEvent.MOUSE_DOWN, startMove);   
      }
    
      private function startMove(e:MouseEvent):void{
        //whatever startMove is supposed to do.  
        // in here, you can use "this" to refer to this particular TermClip.
      }
    
      public function get term():String{
        return termtf.text;
      }
    }
    Code:
    var myxml = new XML(e.target.data);
    var questionLoop = myxml.question.length(); 
       
    for (var i=0; i<questionLoop; i++){
       for(var j:Number=0; j<myxml.question[i].q.length(); j++){
          if(myxml.question[i].attribute("type") == "td"){
              var aTerm:TermClip = new TermClip(myxml.question[i].q[j].attribute("term"), myxml.question[i].q[j]);
              terms.push(aTerm);
              addChild(aTerm);
              //you'll probably want to position these, so that they're not all in the same place.
          }
       }
    }

  7. #7
    Ryan Thomson EvolveDesigns's Avatar
    Join Date
    Oct 2001
    Location
    British Columbia
    Posts
    3,338
    Thank you!
    Evolve Designs Interactive Media
    the natural selection

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