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.
Related
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);
}
}
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])){
}
}
I have created a new Symbol in the Flash IDE, I set it to Export for Actionscript and it has a class name of itemCoin
My stage has now 3 movieclips of that class, how can I:
count how many of itemCoin are on the stage
manipulate them, set and get their x, y individually etc. I tried itemCoin[0].x [1] [2]...etc but it throws an error
remove them from stage when needed
add an event listener that executes a function whenever a itemCoin is removed?
Instance name is used for referencing instances of objects.
For example, if you had a symbol of type ItemCoin (note that naming convention for a type usually starts with a capital letter):
When you place instances on the stage, you give them an instance name to reference them by (note that naming convention for an instance is usually camel case):
Now, properties may be accessed by referencing the instance name from code:
itemCoin1.x = 50;
itemCoin1.y = 25;
Remove it form stage:
removeChild(itemCoin1);
Add an event listener to the itemCoin1 instance for when it is removed:
import flash.events.Event;
itemCoin1.addEventListener(Event.REMOVED, removedHandler);
function removedHandler(event:Event):void {
trace("itemCoin1 was removed");
}
removeChild(itemCoin1);
Although generally a poor practice, you can iterate all children to identify instances. For example, to count the number of ItemCoins:
import flash.display.DisplayObject;
var count:uint = 0;
for (var i:uint = 0; i < numChildren; i++) {
var obj:DisplayObject = getChildAt(i);
if (obj is ItemCoin) {
trace("Found " + ++count + " item coins so far.");
}
}
To comprehensively search the display list, you'd have to traverse children of all display objects.
If knowing the total number of instances on the stage was that important, it might be a better idea to define some ActionScript inside the component or within a Factory class to reference count when added to stage and removed from stage.
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 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.