AS3 Multiple instance names in one MC - actionscript-3

I apologize for how confusing this question is.
I have a Movie Clip that is a car. In the car movie clip there are four different angles to the car. (e.g. left, right, front back). I dynamically change the body color of the car. In each angle of the car, the body of the car has an instance name "body." I change the color with the code :
var tempcar = "car_mc" + i;
var myNewTransform = new ColorTransform();
myNewTransform.color = 0x000000 //in real life this is a random value
this[tempcar].body.transform.colorTransform = myNewTransform;
Everything works fine, until I tell the car movie clip to gotoAndPlay the frame "front," where we see the front side of the car, and I try and apply the color change again to the body of the front of the car. I get the error :
TypeError: Error #1009: Cannot access a property or method of a null object reference.
Is there a better way to do what I am trying to do?

That's the old ActionScript 2 way of handling things. In ActionScript the container is not always a MovieClip, which would except the hash to access a dynamic field. Also, if you'd added it to the display list via addChild, the result would be different as well, since it is not the case in ActionScript 3, that could address the child automatically.
You should use an Array to store and access dynamically created instances.
// clazz would be the symbol
function createInstance(container:DisplayObjectContainer, clazz:Class, list:Array):Sprite
{
const child:MovieClip = new clazz() as MovieClip;
if (!child) throw new ArgumentError("Wrong type given");
return list[list.length] = container.addChild(child);
}
function getInstanceAt(index:int, list:Array):Sprite
{
return list[index] as Sprite;
}

Related

AS3 MovieClip name ambiguity

Summary: I create instances of various MovieClips via AS3, using MovieClip class objects that are defined in the library.
As each MC is instantiated, I push it into an array for later reference.
Finally I create an XML file that contains data related to each MC, including its name. This is the problematic part – the name has to be able to identify the respective MC when the XML is read back in. I don’t want “instance17” etc, which I assume will be meaningless in another session.
Background: I am not a career OO programmer and this is a temporary assignment, forming only a very small part of my long-term interests. It will probably be a couple of years before my next Flash project.
Create instance
Library object
Type: MovieClip, linkage _brakepipe
Instantiation
var brakepipe: _brakepipe = new _brakepipe();
shapes.push(brakepipe);
Then later
var clip: MovieClip = shapes(i);
Trace (clip);
This yields
[object _breakpipe]
So it is giving me the class name, not the MC instance name. What property or method of MC would yield “breakpipe”? (Or even "_breakpipe" - without the "object" prefix?)
You can use an associative array. It could look like this:
var shapes:Array = new Array();
and then
shapes.push({item:_brakepipe,_name:"brakepipe"};
Essentially the curly brackets create an Object instance and the name before the colon (:) is the name you create that you want associated with the value after the colon.
so now you can do this in a loop
trace(shapes[i]._name+"\n"+shapes[i].item);
// output:
// brakepipe
// [object _brakepipe]
The nice thing about this method is you can extend it for any number of properties you want to associate with your array element, like this:
shapes.push({item:_brakepipe,_name:"brakepipe",urlLink:"http://www.sierra.com",_status:"used",_flagged:"false"};
and now
shapes[i]._status
would return the string "used". And you could change that value at runtime to "new" by doing
shapes[i]._status = "new";
The Instantiation / Then later / This yields... Seems to be unclear for me, but you may try this and change the code...
Because I'm not sure not sure about the instance name you want to store...
In your loop you may do this if clip is a MovieClip! :
var clip: MovieClip = shapes(i);
clip.name = "breakpipe_" + i
trace (clip.name);
// will output : breakpipe_1 - > breakpipe_n...
You may deal with the clip.name later by removing the extra "_number" if you want.
If i == 13
var clip: MovieClip = new MovieClip();
clip.name = "breakpipe_" + 13
trace(clip.name);
// output breakpipe_13
var pattern:RegExp = /_\d*/g;
trace(clip.name.replace(pattern,""));
//output :
//breakpipe
So here, you may push your Array or Vector with the instance name.
Am I wrong?

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.

AS3 - Trying to declare the value of a Movie Clip

Okay, I have the following code in my Bullet.as file:
public var impact:MovieClip;
public function Bullet():void
{
addEventListener(Event.ADDED_TO_STAGE, whenAdded);
}
function whenAdded(e:Event)
{
if(this is zArrow){
power = -1;
speed = 15;
impact = arrowImpact;
trace(impact);
}
if(this is Dice){
power = -Math.round(Math.random()*5 + 1);
speed = 10;
impact = diceImpact
}
}
See, I am trying to set the value of "public var impact:MovieClip" as the movie clip "arrowImpact" or "diceImpact". What I want is whenever a bullet collides with an enemy, it leaves an impact image behind and I'm trying to change what impact is shown depending on what bullet is colliding.
I am able to change all of the other variables like power and speed using this setup, but I can't declare which impact movie clip the "impact" movie clip variable is.
From the way I understand your question now, you want to pull these specific movie clips from the Library. If I am not mistaken. To do this, you need to pair each of the movie clips in the library to an AS class that extends MovieClip.
Make sure you check "Export for Actionscript" and create the class you want for each. Then, in your code for the Bullet, you can create a new instance of them. So have it say:
impact = new ArrowImpact)();
or DiceImpact depending on your classes.
Hope this is along the lines of what you wanted.
In order to use these, I would recommend creating a getImpact method along the lines of:
public function getImpactMC():MovieClip
{
return impact;
}
Then all you need to do in your main Document is addChild the proper impact from this method. However, be aware that you need to adjust the x and y values of the impactMC before adding it as a child on the stage to make sure that it displays in the proper position.
Glad this helps!

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.

Is graphic object bitMapData type the same as bitmapData type?

The title might be a little misleading. Look at my code and I will explain
public static function loadTile(tileDir:String = "empty"):void
{
if(tileDir != "empty")
{
tPoint = new Point(0,0);
tRect = new Rectangle(0,0,30,30);
//load in tile sheet image
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT,tilesLoadInit);
loader.load(new URLRequest(tileDir));
}
}
private static function tilesLoadInit (e:Event):void {
tileImage = Bitmap(loader.content).bitmapData;
tileReady.dispatchEvent(new Event("TileReady"));
}
var tImage:BitmapData = new BitmapData(30,30);
tileNum = tileNumber;
tPoint.x = 0;
tPoint.y = 0;
tRect.x = 0;
tRect.y = 0;
tImage.copyPixels(tileImage,tRect,tPoint);
this.graphics.beginBitmapFill(tImage);
this.graphics.drawRect(0, 0,tWidth ,tHeight );
I create a empty bitMapData called tImage. I then take a predefined variable called tileImage which is a bitMapData as well and contains a picture of an image. tRect is predefined as well its width and height is 30x30. I copy a piece of the image and I put it in tImage. problem is that AS3 throws an error saying that tImage is a incorrect type
ArgumentError: Error #2015: Invalid BitmapData.
But clearly it isnt. my question is that is there something different about the data type of bitMapData and bitMapData type that the graphic object accepts ?
I am trying to do tiling with sprites. I want my tiles to be interactive, so that is why I am using the sprite object instead of using regular bitMaps to represent my tiles. You might be wondering why I wouldnt just use graphics.beginBitmapFill(tImage); and graphics.drawRect(0, 0,tWidth ,tHeight ); to pick out the tiles I want to use. Well reason being is because it turns out that drawRect() first and second parameters actually alter the location of where the actual sprite sits at.
So if I set the x and y properties of the sprite to x = 20, and y = 20. then I set my drawRect(20,20). it actually adds an extra 20 pixels to my x and y coords of my sprite. And I know the reason why, I just need to know a better way. Sorry for so much writing and thanks for your time!
It's not saying the type is wrong, it's saying the object is invalid. I expect you'd get a TypeError if the type was wrong.
You've also not stated where exactly the error is thrown, and are assuming the problem is with tImage on the 8th line. It looks more likely that the problem is with tileImage (which you've given no details about) on line 7.
This is probably because of Flash's inbuilt limit to the size of BitmapData objects. If the total number of pixels is larger than 16,777,215, Error #2015 is thrown.
You can read up on it in the docs: BitmapData, Right above "View the examples".
Here's a trick that used to work if you want to give it a shot: BitmapData workaround