(AS3) Reference to an Array Instance

13 posts

Flag Post

I’m trying to access a single instance in an array, when that single instance is clicked on. For example, I created an array of rectangles to test how I thought it would work, creating several rectangles in the array. I used the below code to check for clicks on each rectangle:

i = array.length - 1;
while(i > -1)
{
   array[i].addEventListener(MouseEvent.CLICK, onClick, false, 0, true);
   i -= 1;
}

This checks if each rectangle is clicked on, and in the event handler is used the line


trace(i);

I thought this would trace the value of i when the rectangle is clicked, however it always traces -1, because it calls the event handler once it is finished with the while loop, which always finished when i reaches -1.

So now I’m unsure how I should go about returning the value of i, exactly when the rectangle is clicked, in order to reference the exact instance in the array that is being clicked (sorry if I’m being too vague, I will elaborate if necessary).

If anyone has any suggestions on how I should do this, they would be greatly appreciated. If you didn’t understand a word I said, I will re-write this post in the morning (I quickly whipped it up before going to bed so it might not make very much sense)

Thanks in advance
-WarriorWhitey

EDIT: If someone could please help me with using code in forum posts, that would be appreciated as well ;)

 
Flag Post

When an object is clicked on, the MouseEvent will know which object this was. So if you’ve made your onClick function like this:

private function onClick(e:MouseEvent):void

The variabele ‘e’ now holds the MouseEvent object. To refer to the object that was clicked, use:

e.currentTarget.

Example:

private function onClick(e:MouseEvent):void
{
e.currentTarget.x = Math.rand() * 100;
}

 
Flag Post

This forum uses pre tags for placing code in the forum.

<pre>

Place code here

</pre>

If you still need the index of the clicked rectangle then you can use array.indexOf(e.currentTarget); in the event handler method.

EDIT: you might have to throw in an as to get that to work properly: array.indexOf(e.currentTarget as Rectangle); assuming they are all instances of the Rectangle Class. If the elements in the array are Sprites then it would be array.indexOf(e.currentTarget as Sprite); Or you can use casting array.indexOf(Sprite(e.currentTarget)); which is faster than using as.

EDIT EDIT:Here’s the link where as was 7 times slower than casting: http://blog.joa-ebert.com/2008/04/26/actionscript-3-optimization-techniques/

Scroll down to the comment made by Erik and Joa’s response to the comment. These comments are 2 years old this month.

 
Flag Post

You only have to recast if you are going to use specific functionality of the class. The target doesn’t need to be a Rectangle in order to be sent to indexOf.

 
Flag Post

Or you can use casting array.indexOf(Sprite(e.currentTarget)); which is faster than using as.

Really?

Just looking up, I’ve found a few sources which say the opposite, yet I honestly don’t think there’d be any significant difference unless you ended up invoking a type conversion instead of just casting.

Could someone post some disassembly of the two different types of cast?

 
Flag Post

Hmm.. I tried what Maqrkk said, which when I used his exact words, worked perfectly.. Except what’ I’m trying to do is set a MovieClip variable to be equal to the array instance that was clicked, so that I can then pass that through to another function to run code for the object that was clicked on. eg.

public function clickObject(e:MouseEvent):void
{
objectInUse = e.currentTarget;
}

where the objectInUse variable was stated as a class-wide MovieClip variable. However, when I run this I get the error message:
1118: Implicit coercion of a value with static type Object to a possibly unrelated type flash.display.MovieClip

however, when I run a similar line, it works with no error (I need both lines running)
public function clickOtherObject(e:MouseEvent):void
{
if(objectInUse != null)
{
objectInUse.target = e.currentTarget;
}
}

where target was declared as a class-wide MovieClip variable in the object’s class.

 
Flag Post

Try adding " as MovieClip" after the e.currentTarget.

public function clickObject(e:MouseEvent):void

{

   objectInUse = e.currentTarget as MovieClip;

}
 
Flag Post

That worked perfectly, thanks for your help!

 
Flag Post

Sorry for trolling around but since all the articles are at least 2 years old, I did some benchmarking and the results are so surprising that i must put it somewhere.

The competitors are:

For loop, implicit conversion:


var x:int;
var l:int=a.length;
for(var i:int=0;i<l;i++)
x=a[i].x;

For loop, typecasting:


var x:int;
var l:int=a.length;
for(var i:int=0;i<l;i++)
x=Sprite(a[i]).x;

For loop, casting with ‘as’ keyword:


var x:int;
var l:int=a.length;
for(var i:int=0;i<l;i++)
x=(a[i] as Sprite).x;

Foreach:


var x:int;
for each(var s:Sprite in a)
x=s.x;

Assigning to a Sprite then getting the property:


var s:Sprite;
var x:int;
var l:int=a.length;
for(var i:int=0;i<l;i++){
s=a[i];
x=s.x;
}

The Ball:


private var a:Array=new Array(500000);
private function appComplete():void{
for(var i:int=0;i<500000;i++)
a[i]=new Sprite();
}

So let’s get ready to rumble with 500.000 distinct Sprites in ‘a’ Array.
(averages of 5 runs)

Content Debugger Arena (Debug build, debug player):
For without any cast:
438ms
For with casting:
547ms
For with as keyword:
328ms
Foreaching:
234ms
Assign to a local sprite:
236ms

(Casual Player’s Arena) Release build, release player:
For without any cast:
235ms
For with casting:
393ms
For with as keyword:
151ms
Foreaching:
136ms
Assign to a local sprite:
122ms

I guess the debug result doesn’t need any explanations, everyone has seen a similar result in a benchmark aricle he or she has read. But in the release version the ancient egyptian saying “the more code, the better performance” is true again, assigning a[i] to the local Sprite and entrusting the compiler with the type check then getting its property seems to be faster than foreaching.

The surprising thing was that the as keyword was also faster in the release player. For me, at least.

 
Flag Post

The surprising thing was that the as keyword was also faster in the release player. For me, at least.

I would suspect that is that the type check itself (which is all as needs to do) is faster than also trying to figure out if there are any type conversions you might be able to do.

 
Flag Post

Yep, i guess it has been enhanced since that test of Joa Egbert that showed that casting was 7 times faster in releases. I thought it was faster in debugs just because of the exception handling overhead and in releases they do the same but nope.

Hell i’ll definitely install KotOR today :)

 
Flag Post

very interesting…

 
Flag Post

Thanks for doing the test curse. One thing I would mention however is that your x variable is of type int, whereas the .x property of a Sprite is of type Number. So it might be even faster if variable x was of type Number to avoid the promotion/demotion to int. But since all the tests had to perform that coercion, the tests would still be meaningful. And since it is a coercion between primitive types ( and the value is 0 ) it might be so fast as to make no difference at all in the final time averages.