when is a good time to use a loop? - actionscript-3

I have been trying to learn actionscript 3 for a while now and there are somethings that get me. Like when should I use a loop(for, while, etc)? I watch videos and read articles on the subject and I always run into this example witch really doesn't help me that much:
for(var i:Number = 0; i < 10; i++)
{
trace(i);
}
If anyone can help me on the subject and maybe let me pick there brain a little I would really appreciate it.
Thank you.

You use loops anytime you need to do repetitive tasks.
So if you had 1000 objects that you needed to perform the same operation on, it will be more practical to use a loop instead of writing variations of the same code 1000 times.
A flash example: Let's say you had 10 movieClips that you wanted to all play on a given action.
you could do this:
mc1.play();
mc2.play();
mc3.play();
mc4.play();
mc5.play();
mc6.play();
mc7.play();
mc8.play();
mc9.play();
mc10.play();
For 10 it's just annoying but not a huge deal. If you had 100, or 1000, or 10000 it would be insane. Plus then what if you need to change your code later?
A better way would be to use a loop. Lets say those 10 clips (or any number of clips) were all the children of a parent object called clips.
for(var i:int=0; i<clips.numChildren;i++){
var mc:MovieClip = clips.getChildAt(i);
mc.play();
}
That code would do the exact same thing. You're looping through all the children of the clips parent, and telling everyone to play. Need to change it to gotoAndPlay(3)? then you just have one line to update.
This is a very simple example (and just one of many reasons you'd use a loop), you can probably guess when you get into working with more complex data and objects how loops help you code repetitive tasks.

In general, I use a for loop when I need an index.
For example I might want an array of indexes that represents which MovieClips in a given array are visible :
var visibleClips:Array = new Array;
for (var index:int = 0;index < arrayOfClips.length;index++)
{
var clip:MovieClip = arrayOfClips[index];
if (clip.visible)
{
visibleClips.push(index);
}
}
A while loop I commonly use for something like removing all the children from a DisplayObject like this :
while (container.numChildren > 0)
{
container.removeChildAt(0);
}
As you can see, I really did not need an index in that situation, so it's simpler to use the while loop.

As my old programming teacher said:
"Use for loops when you know how many iterations you want/need to do"
I.e looping through a list, array, vector etc.
"And use while loops when you are not sure."
I.e looping through a whole file (for reading binary data) or doing continuous events that stops for a certain condition.
That being said you could probably apply both for and while loops for most cases. Personally I mostly use for-loops.
Like prototypical said the while loops is great when removing all children of a container but this could also be achieved using a for loop like:
for(var i:int = 0; i < numChildren; i++)
{
removeChildAt(i); i--;
}

Related

Hiding nodes performance

When hiding nodes, the performance seems to slow down quite a lot with larger IFC HVAC models (80000 nodes and upwards). On a standard computer this takes almost 10 seconds. I have two models and want to hide one of them. Currently this is done with rootId. Is there any modifications to be made to make this faster? What would be the fastest way to hide all the nodes?
var vm = new Autodesk.Viewing.Private.VisibilityManager(viewer.impl, viewer.model);
var instanceTree = viewer.model.getData().instanceTree;
var rootId = instanceTree.getRootId();
vm.hide(rootId);
vm.setNodeOff(rootId, true);
When showing parts of the same file, with few thousand nodes this seems to be quite a bit faster. Eventhough the nodes are shown one by one.
var totalNodes = nodesToIsolate.length;
for (var i = 0; i < totalNodes; i++) {
vm.show(nodesToIsolate[i]);
vm.setNodeOff(nodesToIsolate[i], false); // True = hide completely
}
So you are saying that the second approach is quite faster than the first one... in that case what prevents you to use the second approach over the first? You could traverse the model structure from rootId to determine all the node and then use second approach, or am I missing something?
I am guessing that a faster approach would be to affect a custom ShaderMaterial to each fragment of the model and control the visibility from the shader code, however traversing the model to affect the material would also take time, but the operation could potentially be performed at an earlier stage.
Also you could completely unload the model from the scene with viewer.impl.unloadModel(model), obviously if you need to restore it later it will take time.

How to copy into an array in flex without modifying its reference in an efficient way?

How to copy into an array in flex without modifying its reference in an efficient way? Efficient way needed as the array I am working upon is huge.
I'm not sure what you mean by 'reference' and 'copy'.
var copyArr:Array = oldArr would NOT copy, but copyArr would be same as oldArr in all respect (so much so that changing something in copyArr would change that in oldArr too).
While, OTOH,
for(var i:uint=0; i<oldArr.length; i++)
{
newArr.push(item);
}
would copy each item's reference in oldArr into newArr. But, there is no way to optimize it further.
If you want a deep-copy, then you write oldArr into a ByteArray and then read it back into newArr.

Adding movie clips with for loop action script 3

Hey wondering if anybody can help me, i am trying to add a load of move clips and make them clickable to the stage in action script 3,i can work out the spacing of them later i just keep getting errors while trying to add them using this :
for(var x:int = 1; x <= 10; x++)
{
var this["cardPrint"+x] :MovieClip = new this["card_"+x]();
this.addChild(this["cardPrint"+x]);
this["cardPrint"+x].addEventListener(MouseEvent.CLICK, this["click_"+x]);
}
a point in the right direction would help alot
thank you
this is a scope indicator that indicates the current class. So this["cardPrint"+x] is actually trying to find a variable with that name, but you can't declare a variable that is already a reference.
The only way to do what you want is like this:
public dynamic class Foobar
{
public function Foobar()
{
for(var x:int = 1; x <= 10; x++)
{
this["cardPrint"+x] = new this["card_"+x]();
this.addChild(this["cardPrint"+x]);
this["cardPrint"+x].addEventListener(MouseEvent.CLICK, this["click_"+x]);
}
}
}
The key is making the class dynamic. That allows you to create variable names at run time and to create them in string form using the scope["varName"] syntax. If you are doing this on the timeline in Flash Pro, as I get the feeling you are, this is simply not possible the way you want to do it. You would be better off creating objects in the loop and storing them in an array to access them that way instead of using the syntax described above.
The datatype of each object created will be the same as whatever is instantiated, so you won't be able to set it to be MovieClip or similar.
"card_"+x also needs to be an instantiable object (a Class). If it is not, you cannot instantiate it and it will always error out.
I do want to caution you that is a very poor way of putting this together. The room for error is incredibly large and using this syntax will be difficult to do and difficult to read in your code.

Using references vs getChildByName()

I think of 2 approaches referring to some visual element like movieclip. So suppose i have b_mc ( name="b") lying inside a_mc on the stage :
1st approach :
var mc:MovieClip = a_mc.b_mc
2nd approach :
var mc:MovieClip = a_mc.getChildByName("b")
I generally use 1st approach. What can be good reason to go for 2nd approach. It sometimes seems useless to me, as it involves extra overhead to name the movieclips, when used dynamically.
Thanks
V.
a.getChildByName('b') is slower than getting a.b.
If you don't need to use names it makes no sense to use it, however some programmers might make use of the name, especially when generating content dynamically rather than through the Flash IDE, in which case having this function is helpful, so that the display list doesn't have to be traversed by a custom function (which it does with internal function anyway, ergo it is slower than a.b)
getChildByName is needed if you add something dynamically to a movieclip. For instance:
var mc1:MovieClip = new MovieClip();
var mc2:MovieClip = new MovieClip();
mc2.name = "foobar";
mc1.addChild(mc2);
trace(mc1.foobar); //undefined
trace(mc1["foobar"]); //undefined
trace(mc1.getChildByName("foobar")); //[object MovieClip]
I usually do mc1["foobar"] when referencing objects since that way it's easy to work with items such as mc1["foobar_" + i];
I rarely never use getChildByName since that requires a manual cast whenever you try to pass something as a movieclip/textfield or whatever :)
However, if you do create the instances from the flash editor, then I would usually reference them through some exported class and access them through
mc1.mc2.mc3.optionsView.visible
If you have a list of objects that you need to go through programmatically, getChildByName is great. It would assume you've also named them in some programmatic way to reindex them in the for loop. I can also think of a couple other good ways to use this, like pushing the names or objects in an array, so they wouldn't have to be related, just all have some property or method in common.
for(var i:int = 0;i<numOfMC;i++) {
theParent.getChildByName("child"+i).doSomething();
}

Best way to reuse an element from an Array?

I have a Array of Characters objects (extends Sprite).
public static var charlist:Array;
When a Character die, I set a flag to indicate that.
char.die = true;
When I spawn a new player, I check against this flag, to reuse the slot. This is where the problem comes.
What is the best way to do that? Actually I have this approach:
char = new Char();
/* ... */
for (var i:Number = 0; i < Char.charlist.length; i++) {
if (Char.charlist[i].death) {
Char.charlist[i] = char;
return;
}
}
But the problem is that I come from C++ and I think calculating the index every iteration is wasteful.
I would do this, but this doesn't work in AS3, since I can't access by reference the item:
char = new Char();
/* ... */
for (var i:Number = 0; i < Char.charlist.length; i++) {
var char_it:Char = Char.charlist[i];
if (char_it.death) {
char_it = char;
return;
}
}
Just a note: charlist is a static member of class Char.
Do you have any ideas or better approaches?
Thanks!
The "optimized" version doesn't optimize much, I think.
YOur code does not perform 2 accesses in every iteration. It does just when you happen to find a dead Char; and after that you return. So, no big deal, I think.
Personally, I don't think reusing array slots is going to make a big difference either. And, maybe it could be degrade (but the worst part is that your code could be simpler if you avoid it). Suppose you have 100 chars, 60 of which are dead, and you have a loop that runs every frame and performs some check / action on every live char. You'd be looping over 100 chars, when you could loop over 40 if you mantained a list of live objects and a separte list of dead objects, ready to reuse them. Also, the "dead list" could be handled as a stack, so no iteration is needed to get a char.
Anyway, I see 2 things you could easily optimize in your code:
1) retrieve the list length outside the loop:
Do this:
var len:int = Char.charlist.length;
for (var i:Number = 0; i < len; i++) {
Instead of this:
for (var i:Number = 0; i < Char.charlist.length; i++) {
The compiler won't optimize away the call to length (following the ecmascript spec).
2) Avoid static access (for charlist). It's known to be considerably slower than instance access.
Edit:
Re-reading your question, I realize I misunderstood part of it. You're not trying to reuse Char objects, but rather array slots. Still, I don't think reusing array slots is worth it (arrays in Actionscript are non fixed); but something that could help performance is reusing the Char objects themselves. Reseting a Sprite is generally cheaper than creating a new one.
You could manage this with a pool of "dead" objects, from which you can take one and "bring it back to life" when you need, instead of creating a new one.
This post talks about object pools (the blog itself is a good source for Actionscript stuff, especially for performance and data structures topics; worth taking a look):
http://lab.polygonal.de/2008/06/18/using-object-pools/
Why not to use a list instead of array and simply remove dead ones from the list and add new one when needed?
Is there a good reason to try to reuse the slot?
What are you trying to optimize?
Is there a reason you can't just splice out the desired character and push a new character onto the array?
var characters:Array = ["leo", "raph", "don", "mike"];
characters.splice(1, 1);
trace(characters);
characters.push("splinter");
trace(characters);
If you're looking for storage by reference, checkout AS3's Dictionary object or even Flash 10's Vector (if storage is consistent by type; quite fast):
http://www.gskinner.com/blog/archives/2006/07/as3_dictionary.html