AS3 I can't get removeChild to delete my items when they are listed in Array - actionscript-3

using ActionScript 3 on Animate, I'm trying to delete a bunch of items from the stage using Array and for loop. I actually downloaded this code from this site, but it doesn't seem to work for me. It will only delete one item and won't delete the others. and when I redraw the stage it will then not delete anything at all. I have another function button down the road that will restart (redraw) the game, I'm using the gotoAndPlay() to redraw. FYI, the "squares" are sprites and the "myTFs" are text fields that are 'paired' together to become buttons. What am I doing wrong?
function mainFunc(): void {
var btnsArray: Array = new Array("square", "myTF3", "square2", "myTF2", "square4", "myTF4");
for (var ii = 0; ii < btnsArray.length; ii++) {
removeChildAt(btnsArray[ii]);
btnsArray.length = 0;
}
}

If you have an Array of DisplayObject's names you want to batch operate (e.g. remove from display list or something else) you can do the following:
var A:Array = ["square", "myTF3", "square2", "myTF2", "square4", "myTF4"];
// Iterate over items of the Array.
for each (var aName:String in A)
{
// Obtain a reference to the object by its instance name.
var aChild:DisplayObject = getChildByName(aName);
// Check if it is a valid instance before removing to avoid errors.
if (aChild)
{
removeChild(aChild);
}
}

Related

ActionScript 3: Adding multiple instances of the same object to the stage and removing each separately

I have a piece of code adding three insances of the same MovieClip to the stage. I also added MouseEvent.CLICK listener. Once any of the MovieClips gets clicked, I want it to be removed from the stage. My problem is, whenever any of the elements gets clicked, only the last one gets removed and when I click again on a different instance, I'm getting:
ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
I added these three MovieClips to an array, but I don't know how I can properly identify which instance got clicked and remove only the said instance.
This is the excerpt of code I have:
var myMC: SomeMC;
var myArray: Array = [];
function Loaded(e: Event): void {
for (var i: int = 0; i < 3; i++) {
myMC = new SomeMC();
myMC.addEventListener(MouseEvent.CLICK, Clicked);
myMC.y = 50;
myMC.x = 50 * i;
addChild(myMC);
myArray.push(myMC);
}
}
function imageClicked(e: MouseEvent){
// Only the last instance gets removed.
e.currentTarget.parent.removeChild(myMC);
}
I'd be grateful for any help.
In Loaded function you create 3 instances of the object, but by doing:
myMC = new SomeMC();
you overwrite reference. In first iteration myMC is 1st one, in 2nd 2nd one, etc...
Then in imageClicked you're trying to remove it. 1st time it's working because it's referencing the last object, but after you removed it from stage it won't work anymore.
How about changing e.currentTarget.parent.removeChild(myMC); to e.currentTarget.parent.removeChild(e.currentTarget); ? That should remove clicked one.

AS3 - How to put all instances in one code for hit testing?

I have 2.5D game so I cannot put all collision objects in a movieclip container, because I need to keep them as separate display objects. I have multiple instances in the stage. I wouldn't want to go write all the hitTest code for all the objects:
if (player.hitTestObject(object1)
if (player.hitTestObject(object2)
if (player.hitTestObject(object2)... etc
So I would like to know how to hitTest all these instances in one code. I have them added on the stage with instance names, so they are not variables and not added by using the addChild code.
There are plenty of ways to make it less tedious. I'll show a few:
Make a container. You could make a container movie clip and put all the objects in that. Those objects are still individual objects after that (as per your reason in your question for not wanting to go this route). Then you can iterate over all the children of that movie clip:
var i:int = container.numChildren;
while(i--){
if(player.hitTestObject(container.getChildAt(i) as DisplayObject)){
//hit, do something
}
}
Put all the objects in an array, then iterate over that array:
//when you app starts:
var objectArray:Array = [object1,object2,object3]//etc.
//OR, if you have say object1 - object20, you could do something like this:
//vector is basically the same as an array except every item has to be of the same type (on inherit from it)
var objectArray:Vector.<DisplayObject> = new Vector.<DisplayObject>();
for(var i:int=1;i<=20;i++){
var obj:DisplayObject = this.getChildByName("object" + i) as DisplayObject;
if(obj) objectArray.push(obj);
}
//THEN, later, when you do your hit test:
var i:int = objectArray.length;
while(i--){
if(player.hitTestObject(objectArray[i])){
}
}

Adding one sprite multiple times

I'm using a fairly standard piece of code to add a movieclip to the stage using a library link. It's fairly standard code:
var Beat:beat = new beat();
The trouble is, however that it only adds once, where I need it to add multiple times. How would I go about adding many seperate instances of the 'beat' movieclip to the stage, without making more of them/ more variables.
create them in the loop
var _nHowMany:int = 10;
for(var i:int = 0; i < _nHowMany; i++)
{
addChild(new beat() as DisplayObject);
}
also you can store the reference to them if you need to use it later in a list e.g. Vector.<beat> but if not needed then simply create and add to stage (or other container).
best regards
You can't have multiple instances of a movieclip on the stage without declaring multiple instances in your code, you can use a for loop and store all the movie clips in a single array though:
var numOfClips:Number = 5;
var mcArray:Array = new Array();
for(var i=0; i<numOfClips; i++)
{
var newMC:beat = new beat();
addChild(newMC);
mcArray.push(newMC);
}
Using the above code you end up with a single array to access all 5 movie clips (cleaner than having 5 completely seperate objects like beat1, beat2, beat3).
More info on arrays: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Array.html

I can't seem to access automatically named objects (instance##) placed on the stage in AS3, am I missing something?

I have a movieclip in the library that is added to the stage dynamically in the document class's actionscript. This movieclip contains many many child images that were imported directly from photoshop at their original positions (which must be preserved).
I do not want to manually name every single image instance, as there are dozens upon dozens.
I have already gone through and manually converted the images to symbols, as apparently flash won't recognize the "bitmap" objects as children of a parent movieclip in AS3 (numChildren doesn't see the bitmaps, but it sees the symbols).
I have an array filled with references to the dozens of children, and I loop through it, checking if each one is under the mouse when clicked. However, somehow, it is not detecting when I click over the items unless I manually name the child symbols (I tested by manually naming a few of them -- those ones became click-sensitive.)
I have already done trace() debugging all throughout the code, verifying that my array is full of data, that the data is, in fact, the names of the instances (automatically named, IE instance45, instance46, instance47, etc.), verifying that the function is running on click, verifying that the code works properly if I manually name the symbols.
Can any one see what's going wrong, or what aspect of flash I am failing to understand?
Here is the code:
//check each animal to see if it was clicked on
private function check_animal_hits():void
{
var i:int = 0;
var animal:Object = this.animal_container;
for (i=0; i<animal.mussels.length; i++)
{
if (this.instance_under_cursor(animal.mussels[i].name))
{
var animal_data = new Object();
animal_data.animal = "mussel";
this.send_data(animal_data);
}
}
}
Here is the code for the instance_under_cursor() method:
// Used for finding out if a certain instance is underneath the cursor the instance name is a string
private function instance_under_cursor(instance_name)
{
var i:Number;
var pt:Point = new Point(mouseX,mouseY);
var objects:Array = stage.getObjectsUnderPoint(pt);
var buttons:Array = new Array ;
var o:DisplayObject;
var myMovieClip:MovieClip;
// add items under mouseclick to an array
for (i = 0; i < objects.length; i++)
{
o = objects[i];
while (! o.parent is MovieClip)
{
o = o.parent;
}
myMovieClip = o.parent as MovieClip;
buttons.push(myMovieClip.name);
}
if (buttons.indexOf(instance_name) >= 0)
{
return true;
}
return false;
}
Update:
I believe I have narrowed it down to a problem with getObjectsUnderPoint() not detecting the objects unless they are named manually.
That is the most bizarre way to find objects under mouse pointer... There is a built-in function that does exactly that. But, that aside, you shouldn't probably rely on instance names as they are irrelevant / can be changed / kept solely for historical reasons. The code that makes use of this property is a subject to refactoring.
However, what you have observed might be this: when you put images on the scene in Flash CS, Flash will try to optimize it by reducing them all to a shape with a bitmap fill. Once you convert them to symbols, it won't be able to do it (as it assumes you want to use them later), but it will create Bitmpas instead - Bitmap is not an interactive object - i.e. it doesn't register mouse events - no point in adding it into what's returned from getObjectsUnderPoint(). Obviously, what you want to do, is to make them something interactive - like Sprite for example. Thus, your testing for parent being a MovieClip misses the point - as the parent needs not be MovieClip (could be Sprite or SimpleButton or Loader).
But, if you could explain what did you need the instance_under_cursor function for, there may be a better way to do what it was meant to do.

AS3 Targeting Unnamed Timeline Instances

Is there any way to control nested MovieClip instances placed on the timeline without naming them through the Properties panel? Are there any unique identifiers I can refer to?
Using instance names (like instance33, instance12, etc.) doesn't help since names are just properties, but how about references like sprite187_27 (as returned by trace(this) inside a MovieClip on the TimeLine)?
(Using ActionScript3, Automatically declare stage instances disabled)
If [object sprite187_27] is enough in identification, you can just loop through all the objects in your root timeline, like this:
var l:int = this.stage.numChildren;
for (var i:int = 0; i < l; i++)
{
var instance:DisplayObject = this.getChildAt(i);
trace(instance.toString()); // will output [object _whatever_]
}
Looping recursively just means checking if instance.numChildren > 0.