How to put "i" into a loop in Actionscript 3 - actionscript-3

I'm trying loops a bunch of buttons as below. I understand how loops work, but I'm not sure how to change the numbers below to 'i's in the loop if it were something like:
for (var i:Number=1; i<=10;i++){ }
Any help would be greatly appreciated! Thanks!
eyes1.addEventListener(MouseEvent.CLICK, eyes1action);
function eyes1action(event:MouseEvent):void{
eyes.gotoAndStop(1);
}
eyes2.addEventListener(MouseEvent.CLICK, eyes2action);
function eyes2action(event:MouseEvent):void{
eyes.gotoAndStop(2);
}

To answer the question directly, you can do something like this:
for (var i:int = 1; i <= 10; i++) {
this['eyes' + i].addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void {
eyes.gotoAndStop(i);
});
}
However, this is an awful idea. It would be better to assign a variable e.g. tf to each button and use that instead, with a single more generic handler. For example:
eyes1.tf = 1;
eyes2.tf = 2; // etc
Then:
function handleClick(event:MouseEvent):void {
var frame:int = event.target.tf;
eyes.gotoAndStop(frame);
}
And obviously:
eyes1.addEventListener(MouseEvent.CLICK, handleClick); // etc

You can extend SimpleButton and then add properties. Listener's function who created like this never remove.

Related

AS3 .addEventListener in a loop?

I am creating a line of Sprite elements. Every sprite element has different job, when it is clicked. How can I make the function inside the addEventListener to know which button was clicked?
In this case, the traced value of i when it is cliicked is always 6. Which is wrong, because 6 is only the last element of the array. What about the rest of them, the beginning?
for (var i:int = 0; i < 6; i++) {
var barPart:Sprite = new Sprite();
barPart.x = i * (30);
barPart.y = 0;
barPart.graphics.beginFill(0x000000, 0.2);
barPart.graphics.drawRect(0, 0, 10, 10);
barPart.graphics.endFill();
barPart.addEventListener(MouseEvent.CLICK, function(_event:MouseEvent):void {
trace(i);
});
}
When the application is build and the listeners are added, the loop has already executed, so the index "i" will always be six by the time the user ends up clicking the button.
To distinguish between the different items, use their "name" property (prop of DisplayObject) like shown ...
Try not to have listener function as a method closure in a loop, instead do this:
for (...)
{
... code
barPart.name = "barPart-" +i;
barPart.addEventListener(MouseEvent.CLICK, barPart_clickHandler);
}
and implement the function (event handler separately) like:
private function barPart_clickHandler(e:MouseEvent):void
{
// the event's target will let you know who dispatched the function
var name:String = Sprite(e.currentTarget).name;
name = name.replace("barpart-", "");
switch(name)
{
case '0':
// your code
break;
.
.
}
}
#Shally Virk - My mistake. I was thinking of MovieClip which is a dynamic object so it allows adding arbitrary fields. You are right, there are lots of ways to get around this problem, but your suggestion works fine.
While the cause is not clear to me, the answer is a little more simple,
The events are registered correctly, but flash takes the last computed value.
Knowing that we can work around.
The work around can either do like Shally Virk wrote, but that tends to get confusing on bigger scale. So we want something more general and simple.
Now here are the steps taking this in mind:
1. We know sprite are not dynamic, so we make class to extend spirte and make it dynamic. Since the class has basically 0 code, the only difference being the dynamic , the amount of memory added is small
2. Having the class here's the code:
for (var i:int = 0; i < 6; i++) {
var barPart:CustomSprite = new CustomSprite();
barPart.x = i * (30);
barPart.y = 0;
barPart.graphics.beginFill(0x000000, 0.2);
barPart.graphics.drawRect(0, 0, 10, 10);
barPart.graphics.endFill();
barPart.i = i;
barPart.addEventListener(MouseEvent.CLICK, function(_event:MouseEvent):void {
trace(_event.currentTarget.i);
});
}
:)

AS3 (or AS2) - Global Variables as Local inside Functions

I'm assuming there's something easy i'm overlooking here.
But basically, What i'm trying to do is just simply.. I guess code would be a better explanation, here it goes:
tobj = (an Array containing objects.)
for(i = 0; i < tobj.length; i++) {
tobj[i].func = function() {
trace(i);
}
}
Basically, i understand what happens here.. i as the global variable changes, so if i execute that function it'll retrieve the last value of i regardless of what it was when it was assigned. Basically I'm trying to figure out here is what approach to use to convert i as a global, into a local, so that when i execute the function on the object, it'll output the variable as it was assigned.
Hope it's understandable and straight forward. Thanks in advance.
If you add parenthesis after the closing bracket of your function declaration, it will run the function:
var tobj = [new Object(),new Object(), new Object()];
for(var i = 0; i < tobj.length; i++) {
tobj[i].func = function() {
trace(i);
}() // < ------
This would trace: "0", "1", "2"
Simple Solution... There might be another way, but this is what worked for me. Just took walking away from it for a few minutes.
tobj = (an Array containing objects.)
for(i = 0; i < tobj.length; i++) {
tobj[i].func = function() {
assigner(i);
}
}
function assigner(var) {
trace(var);
}

assign mouse event listener with loop to 10 movieclips

I am trying to loop through my 10 "bomb" movieclips and assign an eventlistener that calls the same function but passes the current movieclips name. the "bomb" movieclip names are incremented.
Below is my try
var i:number;
i=0;
while (i <= 10){
var current_bomb:Movieclip = (movingbomb_+i);
current_bomb.addEventListener(MouseEvent.ROLL_OVER, function updateBomb(current_bomb));
i++
}
function updateBomb(currentBomb):void{
currentBomb.gotoAndPlay(2);
}
Close, but not quite. Also, using a for loop is a much better idea here. With those changes, the code should look something like this:
for (var i:int = 0; i < 10; i++) {
var currentBomb:MovieClip = this["movingbomb_" + i];
currentBomb.addEventListener(MouseEvent.ROLL_OVER, function (evt:MouseEvent):void { updateBomb(currentBomb); });
}
function updateBomb(currentBomb:MovieClip):void {
currentBomb.gotoAndPlay(2);
}
Here's how this works.
The for loop simplifies all your while looping code into a single statement for efficiency.
We then select the current bomb using array-bracket selection syntax. To do this, you use this[name], where name is a string. The string we use will be "movingbomb_" with i tacked on to the end.
Finally, we create a unique anonymous function for each new event listener which redirects the mouse event to your updateBomb function and passes the currentBomb object.

removing event listener

I have learned this method of passing values with addEventLister. Here is the code:
for (var i:uint = 0; i < asteroids.length; i++)
{
asteroids[i].x = Math.random() * 450;
asteroids[i].y = Math.random() * 450;
asteroids[i].addEventListener(MouseEvent.MOUSE_UP, function(e:MouseEvent){
changeValue(e, otherArguments);
});
}
public function changeValue(event:MouseEvent, otherArguments:Object):void
{
playSound(anote);
trace(event.currentTarget);
}
but there is no explanation about how to remove the event listener from
asteroids[i].addEventListener(MouseEvent.MOUSE_UP, function(e:MouseEvent){
changeValue(e, otherArguments);
});
That is because you cannot unhook an anonymous function if you don't have a reference to it. If you'd like, you can always keep a reference around:
asteroidsMouseUpHandler = function(e:MouseEvent){
changeValue(e, otherArguments);
};
asteroids[i].addEventListener(MouseEvent.MOUSE_UP, asteroidsMouseUpHandler);
asteroids[i].removeEventListener(MouseEvent.MOUSE_UP, asteroidsMouseUpHandler);
Of course, if these things are happening in separate member functions, then you need to define a member variable (var asteroidsMouseUpHandler:Function). At that point, you might just want to create it as a named function instead. You'd also only want to do this once (not in a loop) to avoid clobbering your reference. Really, I am showing this code for illustrative purposes only.
Thinking about this further, you might be doing this because the otherArguments is specific to the particular asteroids[i] instance so that you are actually creating a new anonymous function every time you hook it. In that case, if that is what you really want to do, you can keep track of your anonymous functions in a dictionary:
var asteriodsCallbacks:Dictionary = new Dictionary();
Then, you can keep track of the functions there:
asteroidsCallbacks[asteroids[i]] = asteroidsMouseUpHandler;
asteroids[i].addEventListener(MouseEvent.MOUSE_UP, asteroidsMouseUpHandler);
And then when you want to unhook, you can look it up:
asteroids[i].removeEventListener(MouseEvent.MOUSE_UP, asteroidsCallbacks[asteroids[i]]);
Of course, I am ignoring existential checks for simplicity. You'd have to add that as well.
Why don't you declare the function like normal, rather than in the parameter? You can do the following:
for (var i:uint = 0; i < asteroids.length; i++)
{
asteroids[i].x = Math.random() * 450;
asteroids[i].y = Math.random() * 450;
asteroids[i].addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
});
}
public function onMouseUp(e:MouseEvent) {
changeValue(e, otherArguments);
}
public function changeValue(event:MouseEvent, otherArguments:Object):void
{
playSound(anote);
trace(event.currentTarget);
}
You can remove it as follows:
asteroids[index].removeEventListener(MouseEvent.MOUSE_UP, onMouseUp)
When you add an anonymous function as an event listener, the only time you can reasonably remove that event listener is inside the callback.
public function changeValue(event:MouseEvent, otherArguments:Object):void
{
playSound(anote);
trace(event.currentTarget);
event.currentTarget.removeEventListener(MouseEvent.MOUSE_UP, arguments.callee);
}
Otherwise, you need to have a non-anonymous function in order to remove it.

ActionScript - Retrieving Index Of Specific Filter

i have a few filters on a sprite. on mouse over i would like to access one of the filters in the filters array, but i'm having a bit of trouble trying to accomplish this.
mySprite.filters = [new DropShadowFilter(), new GlowFilter(), new BlurFilter()];
mySprite.addEventListener(MouseEvent.MOUSE_OVER, mouseOverEventHandler);
function mouseOverEventHandler(evt:MouseEvent)
{
//obtain indexOf the GlowFilter
trace(evt.currentTarget.filters[evt.currentTarget.filters.indexOf([Object GlowFilter])]));
}
the above code doesn't work. what's the proper way to get the index of a specific filter in a filters array?
If I understand correctly, you're essentially trying to do this:
var index:int = evt.currentTarget.filters.indexOf([Object GlowFilter]);
The bracketed part is not valid Actionscript it shouldn't even compile. What you need to do is to iterate over the filters and test them yourself since there's no way to search for a specific class with indexOf.
Try this instead:
function mouseOverEventHandler(evt:MouseEvent) {
var glowFilter:GlowFilter;
for (var i:int = 0; i < evt.target.filters.length; i++) {
if (evt.target.filters[i] is GlowFilter) {
glowFilter = evt.target.filters[i];
break;
}
}
}
Also, if you're going to fiddle with the filters in the array Flash won't accept in-place modifications, so you need to re-set the array once you've changed it:
function mouseOverEventHandler(evt:MouseEvent) {
var glowFilter:GlowFilter;
for (var i:int = 0; i < evt.target.filters.length; i++) {
if (evt.target.filters[i] is GlowFilter) {
glowFilter = evt.target.filters[i];
break;
}
}
if (!glowFilter) return;
glowFilter.blurX = 10;
var filters:Array = evt.target.filters;
filters[i] = glowFilter;
evt.target.filters = filters;
}