A Flash Developer Resource Site

Page 1 of 2 12 LastLast
Results 1 to 20 of 23

Thread: Arrays & Loops

  1. #1
    Member
    Join Date
    May 2008
    Posts
    59

    Arrays & Loops

    Inside each dataInput is a button that sets the var "varSumNum" to 1 or 2, retain or dismiss respectively. If I set varSumNum to 2 the retain button will hide the corresponding circleMC, but the circles need to toggle visible/invisible individually. This works fine on circleMC1, but I can't get it to check the rest of the dataInputs and toggle their circles.

    To clarify further, it needs to check each dataInput and if 2 & 4 are set to 1 circle 2 & 4 are removed.

    Code:
    var allCircles:Array = [circleMC1, circleMC2, circleMC3, circleMC4, circleMC5, circleMC6, circleMC7, circleMC8, circleMC9, circleMC10];
    var allInputs:Array = [dataInput1, dataInput2, dataInput3, dataInput4, dataInput5, dataInput6, dataInput7, dataInput8, dataInput9, dataInput10];
    
    retainBtn.addEventListener(MouseEvent.CLICK, onRetain);
    function onRetain(evt:MouseEvent):void {
         for(var num:Number=0; num!=allCircles.length; num++){
    		
              if (allInputs[num].varSumNum == 1){
                   removeChild(allCircles[num]);
              }
    		
         }
    }
    Last edited by darngooddesign; 10-14-2009 at 05:51 PM.

  2. #2
    Member
    Join Date
    Oct 2009
    Location
    Ontario
    Posts
    98
    Are you getting any error messages, or is simply nothing happening? Are you sure that the values for dataInput2 and dataInput4 are being set properly?

    I can't find anything else wrong with your code. However, I do suggest you write your loop like this:

    Code:
    for(var num:Number=0; num<allCircles.length; num++)
    It's better practice to continue looping while your iterator is LESS than the number of desired iterations. If the iterator "num" were to somehow be set to a number GREATER than the length of your array or whatever the desired number of iterations were, it would loop infinitely.

    Aside from that, if you could post more code, it might help clarify the issue.

  3. #3
    Member
    Join Date
    May 2008
    Posts
    59
    Wow, stupid error on my part. Because I was still testing my mechanism I hadn't added the necessary code to the other inputs, which is why they didn't do anything. Thanks for jostling my brain. My next question is that right now clicking on the button just hides the other circles leaving the desired ones visible. this means there will be gaps. How can I move the visible circles so they appear one after the other.

    Currently after pressing retainBtn the visible circleMCs look like this:
    Code:
    C1         C3 C4 C5           C9
    I want
    Code:
    C1 C3 C4 C5 C9
    Last edited by darngooddesign; 10-15-2009 at 01:44 AM.

  4. #4
    Member
    Join Date
    Oct 2009
    Location
    Ontario
    Posts
    98
    Are all the circles of the same width? What you can do is loop through the remaining Movie Clip symbols and position them based on their widths apart from one another.

    Code:
    var index = 0;
    ... // do some looping here
    myMovieClip.x = index * myMovieClip.width + someDefaultOffset;
    Does this make sense?

  5. #5
    Member
    Join Date
    May 2008
    Posts
    59
    Code:
    var numCircles:Number = 10;
    var allCircles:Array = [circleMC1, circleMC2, circleMC3, circleMC4, circleMC5, circleMC6, circleMC7, circleMC8, circleMC9, circleMC10];
    var allInputs:Array = [dataInput1, dataInput2, dataInput3, dataInput4, dataInput5, dataInput6, dataInput7, dataInput8, dataInput9, dataInput10];
    
    retainBtn.addEventListener(MouseEvent.CLICK, onRetain);
    function onRetain(evt:MouseEvent):void {
    
         for(var num:Number=0; num<numCircles; num++){
              if (allInputs[num].varSumNum == 0){
                   allCircles[num].visible = false;
              } else if (allInputs[num].varSumNum == 1){
    
    This bit that's throwing me. I want to to check all the circles that are visible and x-offset them by 91.
    col starts at 0, so the first vis circle is x=64, the second on is x=155 (64 + (91*1)), etc.
    
                   for (var col:Number=0; col<num; col++){
                        allCircles[num].x = 64 + (col * 91);
                        allCircles[num].visible = true;
                   }
    				
              } else if (allInputs[num].varSumNum == 2){
                   allCircles[num].visible = false;
              } else if (allInputs[num].varSumNum == 3){
                   allCircles[num].visible = false;
              }
    		
         }
    }

  6. #6
    Member
    Join Date
    Oct 2009
    Location
    Ontario
    Posts
    98
    You shouldn't need a second loop because you are already looping through and finding the circles with a varSumNum of 1.

    All you should need to do is set the x for those circles which are meant to be visible. Your little offsetting equation, using the index, looks good. Take out the second loop and use "num" instead of "col" for your index.

    Try that and let me know if it works.

  7. #7
    Member
    Join Date
    May 2008
    Posts
    59
    Code:
    } else if (allInputs[num].varSumNum == 1){
         allCircles[num].x = 64 + (num * 91);
         allCircles[num].visible = true;
    }...
    The circles don't change their x position.

  8. #8
    Member
    Join Date
    Oct 2009
    Location
    Ontario
    Posts
    98
    Sorry, I've made an error. You will need to create a new array to store all the circles that are visible, THEN loop through those separately (after the initial loop). Otherwise, the circles are retaining their positions because the indices don't change. With a new loop, the index would be re-initialized to 0, and the math to figure out the x position will be correct.

    Code:
    var visibleCircles:Array = new Array();
    ...
    else if (allInputs[num].varSumNum == 1) {
         visibleCircles.push(allCircles[num]);
    }
    ...
    for (var i=0; i<visibleCircles.length; i++) {
         visibleCircles[i].x = 64 + (i * 91);
    }
    This should move the circles. =)

  9. #9
    Member
    Join Date
    May 2008
    Posts
    59
    That got it, and this is what my code looked like.

    retainBtn.addEventListener(MouseEvent.CLICK, onRetain);
    function onRetain(evt:MouseEvent):void {

    // I put this here or it would only move one circle.
    var visibleCircles:Array = new Array();


    for(var num:Number=0; num<numCircles; num++){
    if (allInputs[num].varSumNum == 0){
    allCircles[num].visible = false;

    } else if (allInputs[num].varSumNum == 1) {

    // This sets all circles to visible or when I went to the next button, even though it might move the proper circles, you would't be able to see them since the retain button set them to invisible.
    allCircles[num].visible = true;

    visibleCircles.push(allCircles[num]);
    for (var i=0; i<visibleCircles.length; i++) {
    visibleCircles[i].x = 64 + (i * 91);
    }

    } else if (allInputs[num].varSumNum == 2){
    allCircles[num].visible = false;
    } else if (allInputs[num].varSumNum == 3){
    allCircles[num].visible = false;
    }

    }
    }

    Now I also have an All Button that sets all circles to visible and in the correct order.

    This is what my code looks like (it works):

    Code:
    var visibleCircles:Array = new Array();
    		
    for(var num:Number=0; num<numCircles; num++){		
         allCircles[num].visible = true;
         visibleCircles.push(allCircles[num]);
         for (var i=0; i<visibleCircles.length; i++) {
              visibleCircles[i].x = 64 + (i * 91);
         }
    }
    Last edited by darngooddesign; 10-15-2009 at 03:53 PM.

  10. #10
    Member
    Join Date
    May 2008
    Posts
    59
    One more thing:

    If I want to send the number of visible circles to a dynamic text box named "retainTxt", I tried the method in green but it didn't work. [object.circleMC] is returned to retainTxt

    else if (allInputs[num].varSumNum == 1) {

    allCircles[num].visible = true;
    visibleCircles.push(allCircles[num]);
    retainTxt.text = allCircles[num];
    for (var i=0; i<visibleCircles.length; i++) {
    visibleCircles[i].x = 64 + (i * 91);
    }

    }

    Trying retainTxt.text = visibleCircles.length; gave a string conflict
    Last edited by darngooddesign; 10-15-2009 at 04:16 PM.

  11. #11
    Member
    Join Date
    Oct 2009
    Location
    Ontario
    Posts
    98
    You really shouldn't be looping through the visibleCircles array WITHIN the other loop. What it's doing is looping for every circle in allCircles, so as you continue to loop through allCircles, you are then looping over the same elements of visibleCircles, setting their positions for no reason. The visibleCircles loop should be done after the initial loop, otherwise you're performing unnecessary loops.

    Though it's not intensive now, this would pose a problem in something more graphics-intensive if it was running all the time. It's best to practice good standards now rather than let it cripple your movie at a later date.

    If this new button simply sets ALL circles to visible, you don't need to secondary array or secondary loop at all, as you know that ALL circles will be re-organized in order, since none are left out or invisible:

    Code:
    for(var num:Number=0; num<numCircles; num++){		
         allCircles[num].visible = true;
         allCircles[num].x = 64 + (i * 91);
    }
    In your example, with the loop nested in the main loop, the total iterations would be equal to the number of circles times the number of circles times the number of circles. So, with 10 circles in the allCircles array, the loop runs 1000 times, which is very much unnecessary. A single loop through the final array is all that is necessary and cuts down the total number of loops from 1000 to 10.

    For your latest question, what exactly do you want the retainTxt to display? The number of circles currently visible?

    The reason you're seeing "[object .circleMC]" is because that's exactly what you're setting the text box to. The circle objects are Movie Clip objects that contain no text values. The object itself has no string value.

    Code:
    retainTxt.text = visibleCircles.length.toString();
    You need to explicitly tell the visibleCircles.length, which is of type uint, to "become" a String. You can do this by casting the uint into a String, or by using the toString() method, which belongs to ALL objects, as everything extends the main Object class. AS3 won't do that implicitly, which is what you were doing: "implying" that it should become a String. =)
    Last edited by Nidht; 10-15-2009 at 04:43 PM.

  12. #12
    Member
    Join Date
    May 2008
    Posts
    59
    I wanted to make that action happen when you inputted the data, instead of clicking on the retainBtn...

    On the stage I put:
    Code:
    var retainNum:uint = 0;
    retainTxt.text = retainNum.toString();
    And on each dataInput I put:
    Code:
    On button
    MovieClip(this.parent).retainNum = MovieClip(this.parent).retainNum + 1;
    MovieClip(this.parent).retainTxt.text = MovieClip(this.parent).retainNum.toString();
    Does this look right. I'm going to work on moving the above code to the stage as well.

  13. #13
    Member
    Join Date
    May 2008
    Posts
    59
    Here is that code moved to the stage:
    Code:
    for(var retainNumTxt:Number=0; retainNumTxt<numCircles; retainNumTxt++){
    	allInputs[retainNumTxt].retainBtn.addEventListener(MouseEvent.CLICK, onRetainNumTxt);
    	function onRetainNumTxt(evt:MouseEvent):void {
    		retainNum = retainNum + 1;
    		retainTxt.text = retainNum.toString();
    	}
    }
    for(var unclearNumTxt:Number=0; unclearNumTxt<numCircles; unclearNumTxt++){
    	allInputs[unclearNumTxt].unclearSumBtn.addEventListener(MouseEvent.CLICK, onUnclearNumTxt);
    	function onUnclearNumTxt(evt:MouseEvent):void {
    		unclearNum = unclearNum + 1;
    		unclearTxt.text = unclearNum.toString();
    	}
    }
    for(var staticNumTxt:Number=0; staticNumTxt<numCircles; staticNumTxt++){
    	allInputs[staticNumTxt].strikeBtn.addEventListener(MouseEvent.CLICK, onStrikeNumTxt);
    	function onStrikeNumTxt(evt:MouseEvent):void {
    		strikeNum = strikeNum + 1;
    		strikeTxt.text = strikeNum.toString();
    	}
    }
    Thanks for all you help Nidht.

  14. #14
    Member
    Join Date
    May 2008
    Posts
    59
    I'm running into a conflict now that I moved that button action to the stage. The problem is that if I keep clicking on dataInput.retainBtn the retainTxt number keeps increasing. So I figured I'd just deactivate it after the click.

    This code inside dataInput1 works:
    Code:
    retainBtn.addEventListener(MouseEvent.CLICK, onRetain);
    function onRetain(evt:MouseEvent):void {
         MovieClip(this.parent).retainNum = MovieClip(this.parent).retainNum + 1;
         MovieClip(this.parent).retainTxt.text = MovieClip(this.parent).retainNum.toString();
         retainBtn.mouseEnabled = false;
    }
    However, if I comment out that code and try to control it from the stage I it doesn't and I get a 101 error.

    Code:
    for(var retainNumTxt:Number=0; retainNumTxt<numCircles; retainNumTxt++){
         allInputs[retainNumTxt].retainBtn.addEventListener(MouseEvent.CLICK, onRetainNumTxt);
         function onRetainNumTxt(evt:MouseEvent):void {
              retainNum = retainNum + 1;
              retainTxt.text = "(" + retainNum.toString() + ")";
              allInputs[retainNumTxt].retainBtn.mouseEnabled = false; // Without this line the other stuff works.
         }
    }
    Last edited by darngooddesign; 10-15-2009 at 07:08 PM.

  15. #15
    Member
    Join Date
    Oct 2009
    Location
    Ontario
    Posts
    98
    Why not just have the text field set to the number of elements in visibleCircles after each loop? Then you don't have to bother with changing the button code or incrementing values, as it will rely on the array length.

    Also, when you're declaring functions inside the for-loop, I don't think they "survive" by the next iteration unless they are used right away, as they are event listeners that are garbage collected. You shouldn't declare functions inside of any type of loop, really.

    You don't need to declare the functions if you follow my suggestion above, but if you do ever declare them in this manner in the future, you can store them TO the listener.

    Code:
    myButton.addEventListener(MouseEvent.CLICK, 
    	function(event:MouseEvent):void {
    		trace("Test");
    	}
    );
    I don't recommend this if it's not absolutely necessary, though.

    Try my suggestion by setting the text field to the number of elements in visibleCircles after each loop and let me know how that works. =)

  16. #16
    Member
    Join Date
    May 2008
    Posts
    59
    Where this number is being declared, visibleCircles isn't defined yet.

    visibleCircles is used in the organizational area while this is happening in the data entry area.

    Code:
    declare vs array
    
    onbutton{
         push to vs array
    }
    can i push to the array outside of my function? or shall i just declare a different array for the purpose of this function?

    Also bear in mind that there are three buttons and three text fields to reflect the number of circles in each category. That's why I went with number variables.
    Last edited by darngooddesign; 10-15-2009 at 09:49 PM.

  17. #17
    Member
    Join Date
    Oct 2009
    Location
    Ontario
    Posts
    98
    You can absolutely access the array if it's outside of your function, as long as it's declared properly. Can you show me some of the scope of your code?

  18. #18
    Member
    Join Date
    May 2008
    Posts
    59
    I just PMed you a link to my project file.

  19. #19
    Member
    Join Date
    Oct 2009
    Location
    Ontario
    Posts
    98
    darngooddesign, this is too much code to sift through. Also, I wasn't able to run the Flash movie properly. Some of the buttons didn't seem to work and I was stuck on the first "screen".

    Would you be able to just show me the scope of code where you're performing the loop and where it's failing to update the text field?

    If you're unable to access the visibleCircles array from the "data portion" of your code, you need to declare it globally so that other frames can see the array and access it. This should allow you to update the text field. =)

  20. #20
    Member
    Join Date
    May 2008
    Posts
    59
    The idea is that if you select retain, unclear or strike in one of the dataInputs the respective text box would reflect that. The number increases just fine, but what I'm trying to do is have decrease the number of retains if I change one from retain to unclear, for example, in a dataInput. This code works, and the check if zero works, but I'm having problems making the number decrease only if the summary status, retain/unclear/strike, has been set once before, currently it automatically decreases; otherwise, if the status has not been set before only the number would increase.

    Code:
    var retainNum:Number = 0;
    var unclearNum:Number = 0;
    var strikeNum:Number = 0;
    
    for(var retainNumTxt:Number=0; retainNumTxt<numCircles; retainNumTxt++){
    	allInputs[retainNumTxt].retainBtn.addEventListener(MouseEvent.CLICK, onRetainNumTxt);
    	function onRetainNumTxt(evt:MouseEvent):void {
    		retainNum = retainNum + 1;
    		retainTxt.text = "(" + retainNum.toString() + ")";
    		
    		if (unclearNum > 0) {
    			unclearNum = unclearNum - 1;
    			unclearTxt.text = "(" + unclearNum.toString() + ")";
    		} 
    		if (strikeNum > 0) {
    			strikeNum = strikeNum - 1;
    			strikeTxt.text = "(" + strikeNum.toString() + ")";
    		} 
    	}
    }
    for(var unclearNumTxt:Number=0; unclearNumTxt<numCircles; unclearNumTxt++){
    	allInputs[unclearNumTxt].unclearSumBtn.addEventListener(MouseEvent.CLICK, onUnclearNumTxt);
    	function onUnclearNumTxt(evt:MouseEvent):void {
    		unclearNum = unclearNum + 1;
    		unclearTxt.text = "(" + unclearNum.toString() + ")";
    		
    		if (retainNum > 0) {
    			retainNum = retainNum - 1;
    			retainTxt.text = "(" + retainNum.toString() + ")";
    		} 
    		if (strikeNum > 0) {
    			strikeNum = strikeNum - 1;
    			strikeTxt.text = "(" + strikeNum.toString() + ")";
    		}
    	}
    }
    for(var staticNumTxt:Number=0; staticNumTxt<numCircles; staticNumTxt++){
    	allInputs[staticNumTxt].strikeBtn.addEventListener(MouseEvent.CLICK, onStrikeNumTxt);
    	function onStrikeNumTxt(evt:MouseEvent):void {
    		strikeNum = strikeNum + 1;
    		strikeTxt.text = "(" + strikeNum.toString() + ")";
    		
    		if (retainNum > 0) {
    			retainNum = retainNum - 1;
    			retainTxt.text = "(" + retainNum.toString() + ")";
    		} 
    		if (unclearNum > 0) {
    			unclearNum = unclearNum - 1;
    			unclearTxt.text = "(" + unclearNum.toString() + ")";
    		} 
    	}
    }
    Inside each dataInput is this code:
    Code:
    var varSumNum:uint = 0;
    So I tried surrounding the ifs with:
    Code:
    if (allInputs[retainNumTxt].varSumNum > 0) {
         if (unclearNum > 0) {
    	unclearNum = unclearNum - 1;
    	unclearTxt.text = "(" + unclearNum.toString() + ")";
         } 
         if (strikeNum > 0) {
              strikeNum = strikeNum - 1;
              strikeTxt.text = "(" + strikeNum.toString() + ")";
         }			
    }
    But I get this error:
    Code:
    TypeError: Error #1010: A term is undefined and has no properties.
    at jury9_fla::MainTimeline/onRetainNumTxt()
    Last edited by darngooddesign; 10-18-2009 at 02:51 PM.

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