Actionscript 3, access Symbol properties (AS Linkage) - actionscript-3

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.

Related

How can i change a couple of MovieClip instance properties in mainTimeline by ActionScript 3

I'm a beginner at ActionScript 3. I want to change a MovieClip property. Also I want to give different names for every instance. So basically I want to reach all instances by one name.
A possible solution is writing code inside the MovieClip timeline with --this--.
But I want to do that in root area.
This a picture of my scene:
https://drive.google.com/file/d/0BzXd1GMzUo9HUWozdkJjYkxXSEk/view?usp=sharing
trace(ins1.alpha); // reaching with instance name without problem
trace(ins2.alpha); // reaching with other instance name without problem
/*
trace(MovieClip("mnsmb").alpha); // trying to reach with linkage name is not working
trace(MovieClip(mnsmb).alpha); // trying to reach with linkage name is not working
trace(MovieClip("menusembolu").alpha); // trying to reach with library symbol name is not working
trace(MovieClip(menusembolu).alpha); // trying to reach with library symbol name is not working
trace(mnsmb.alpha); // trying to reach with linkage name is not working
trace(menusembolu.alpha); // trying to reach with library symbol name is not working
*/
If you need to modify the alpha property of one instance (named inst1 in the Properties panel):
ins1.alpha = 0.1;
If you want modify the alpha of all the instances of your class, you can use the is operator (mnsmb is your AS Linkage):
var inst:DisplayObject;
for(var i:int = 0; i < numChildren; i++)
{
inst = this.getChildAt(i) as DisplayObject;
if (inst is mnsmb) inst.alpha = 0.1;
}
Note : In ActionScript 3.0 the instanceof operator should not be used to test for data type membership. See Adobe help about the is operator.

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.

Creating Classes and Properties in AS3

I'm new to AS3. Learning how to create classes. Is comp = new HouseObjects creating a new class? Is comp creating an instance of the HouseObjects? I realize that this is inside public class TreeHouse. I'm thinking that HouseObjects, how I set it up is not a class...not sure what the correct way to set up classes and properties.
Also I noticed, that when I tried to link another movieclip using the same linkage name HouseObjects--it asked to enter a unique class. I'm trying to create multiple instances from the same class called HouseObjects.
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
public class TreeHouse extends MovieClip
{
private var comp:MovieClip;
var powerData:int; // stores user data (of selected data)
//var currentPower:int; // stores current power
public function TreeHouse()
{
comp = new HouseObjects; // linkage in library
comp.power = 2; // amount of power
comp.name = "comp";
comp.buttonMode = true;
comp.bstate = 0; // button state
//add event listeners -- listens to functions that are called
comp.addEventListener(MouseEvent.MOUSE_OVER, rolloverToggle);
comp.addEventListener(MouseEvent.MOUSE_OUT, rolloutToggle);
comp.addEventListener(MouseEvent.CLICK, toggleClick);
comp.addEventListener(MouseEvent.CLICK, toggleClick);
stage.addChild(comp); // add computer to stage -----------------------------------
trace("tracing...");
comp.x = 100;
comp.y = 100;
}
// function rollOver --------------------------------------------------------------
function rolloverToggle(e:MouseEvent) {
if (e.currentTarget.currentFrame == 1)
e.currentTarget.gotoAndStop(2);
if (e.currentTarget.currentFrame == 3)
e.currentTarget.gotoAndStop(4);
}
// function rollOut-- --------------------------------------------------------------
function rolloutToggle(e:MouseEvent) {
if (e.currentTarget.currentFrame == 2)
e.currentTarget.gotoAndStop(1);
if (e.currentTarget.currentFrame == 4)
e.currentTarget.gotoAndStop(3);
}
// function toggleClick-------------------------------------------------------------
function toggleClick(e:MouseEvent) {
// On MouseEvent gotoAndStop(Frame Number)
if (e.currentTarget.currentFrame == 2)
{
e.currentTarget.gotoAndStop(3);
e.currentTarget.bstate = 1;
}
if (e.currentTarget.currentFrame == 4)
{
e.currentTarget.gotoAndStop(1);
e.currentTarget.bstate = 0;
}
//var powerData:int = HouseObjects[e.currentTarget.power]; // set power value
// Find out which object selected-------------------------------------------------
//trace("movieClip Instance Name = " + e.currentTarget); // [object Comp]
//trace(houseArray[e.currentTarget.name]); // comp
trace("using currentTarget: " + e.currentTarget.name); // comp
//trace("powerData: " + powerData); // power of user data
//trace("houseArray: " + houseArray[0]); // the 0 index of house array
trace(e.currentTarget.power); // currentTarget's power************
}
} //end of class
} // end of package
I am not quite sure if I understood your question correctly. comp = new HouseObjects creates a new instance (object) of the type HouseObjects. (A little research on OOP basics would probably make life easier for you.)
Regarding the »Please enter a unique class name« error: You cannot assign the same class to two library symbols because the symbol is hooked up to the class internally so that if you create a new instance (var x = new HouseObjects; addChild(x);), the content from the linked symbol is also added to the display list. If there were multiple library symbols linked to the same class, how would the Flash compiler know which one to choose?
Your question is pretty broad and , as klickverbot suggests, it would be better if you took a little time to understand basic OOP concepts.
There are a lot of resources available to get you started with AS3, check this for instance
http://tv.adobe.com/watch/colin-moocks-lost-actionscript-weekend/course-1-introduction
Colin Moock's tutorial is very easy to follow and will give you most of the tools you need to get started.
If you are new to AS3, and OOP in particular, you should check out Moock's Essential Actionscript 3 which is beyond fantastic for a step by step education in OOP in AS3.
HouseObjects appears to be a class and you are creating a new instance of it for the variable comp
You've got a duplicate definition. It appears that you are trying to use Flash Pro to extend HouseObjects for the lightbulb. It doesn't work like this in Flash Pro. You are creating a MovieClip symbol and giving it a class definition. It has to extend MovieClip and you cannot change this in this case. You could likely extend HouseObjects in an AS3 file and make use of it in your application.
Personally think that if you want to really get your head around OOP with AS3 you should get the book and get out of Flash Pro. Use an IDE like Flash Builder, FDT, Flash Develop, or IntelliJ IDEA. It is a lot easier to understand when you get away from the dialogs and other complications of the Flash Pro IDE :>

How to add all symbols in library folder to stage at runtime

I just submitted this question but i can't see if it posted anywhere, so I apologize if this is a duplicate.
For a Flash CS4 project, I am constantly importing new images, converting them to movieclips and storing them in the library under an "Ornaments" folder. All of these ornaments need to be on the stage in a certain place when the program is initialized. Instead of having to drag the new symbols onto the stage every time I add a new, is it possible to add all of the symbols in the "Ornament" library folder to the stage at runtime?
Thanks
You can do it in code if you wish, but you'd have to still add the names of the symbols to the code. That is, the folder is merely a convenience for organizing within the CS4 library and it does not translate to code (AFAIK).
To instantiate the item in AS3, simply right click the symbol in the library and check the box labelled "Export for ActionScript". If you can't see it, click the Advanced button. It will default the Class to the name of the symbol. That will be the class you can instantiate in ActionScript to put an instance on stage.
You could keep an array of the ornament names and loop through them adding them to the stage:
var ornaments:Array = [OrnamentGold, OrnamentSilver, OrnamentBronze];
for each(var ornament:Class in ornaments)
{
var ornamentClip:MovieClip = new ornament();
addChild(ornamentClip);
}
If you name all of your instances the same with only a trailing digit incremented, you can save yourself some time and just increment a single number:
const NUM_ORNAMENTS:int = 5;
for(var i:int = 0; i < NUM_ORNAMENTS; i++)
{
// ornaments are names Ornament0, Ornament1, Ornament2, etc. in the library
var ornamentClass:Class = new getDefinitionByName("Ornament" + i) as Class;
var ornamentClip:MovieClip = new ornamentClass();
addChild(ornamentClip);
}