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

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);
}

Related

How to put "i" into a loop in 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.

How do you detect collisions between two arrays?

For future refrence this was the final code
for each (var bullet:Bullet in bulletList)
{
for each (var zombie:Zombie in zombieList)
{
if (zombie.hitTestObject(bullet))
{
stage.removeChild(bullet);
zombie.zombieShot(50);
}
}
}
Original Question Below
for each (var bullet:Bullet in bulletList)
{
if (zombieList.length > 0)
{
if (zombieList[h].hitTestObject(bullet))
{
bulletList[i].deleteBullet();
zombieList[h].zombieShot(50);
}
}
}
This is the code I have but it only detects the first zombie I spawn in, any help is appreciated.
if (countMePls<10)
{
countMePls++;
var zombie:Zombie = new Zombie(stage,Math.random() * stage.width,Math.random()*stage.height);
zombie.addEventListener(Event.REMOVED_FROM_STAGE,zombieRemoved,false,0,true);
zombieList.push(zombie);
stage.addChild(zombie);
}
and then...
function shootBullet():void
{
var bullet:Bullet = new Bullet(stage,Main.player.x,Main.player.y,Main.player.rotation - 90);
bullet.addEventListener(Event.REMOVED_FROM_STAGE,bulletRemoved,false,0,true);
bulletList.push(bullet);
stage.addChildAt(bullet,1);
}
this last bit is in Bullet.as
public function deleteBullet():void
{
this.parent.removeChild(this)
}
I think your issue comes from some basic confusion about for and for each. With for each you have no index variable, each iteration yields a new instance of the type in the collection which is referred to by the name you declare in the loop. In this case that is;
foreach (var bullet in bulletsList)
{
// do something with bullet
}
You probably actually want a nested loop, something that checks every bullet against each zombie to see if there was a hit, that would actually look like this;
foreach (var bullt in bulletsList)
{
foreach (var zombie in zombiesList)
{
if (zombie.hitTestObject(bullet))
{
bulletList.Remove(bullet);
zombie.zombieShot(50);
}
}
}
In your code you have the foreach loop giving you the current bullet object but then you never reference it within the loop, that doesn't make sense. This may not be exactly what you want but hopefully it will get you moving in the right direction. If you want to use those indexers then you need something like;
for (int i = 0; i < bulletsList.Length; i++)
{
for (int h = 0; h < zombiesList.Length; h++)
{
// do stuff with bulletsList[i] and zombiesList[h]
}
}
Note: this was originally tagged as C# and the code I've posted uses C# syntax. The explanation I've provided most likely applies either way, the OP's code doesn't really makes sense in any language I know of and the reasons are the same.

How to compare properties of objects inside a vector?

I have a couple of display objects moving around the screen, the all belong to the same Vector.
I would like to create a function that lets me pick an object with the lowest x value at the moment the function is called.
This is quite easy and if you're into programming, you should be able to do it yourself, but if you're a beginner, I'll give you some code:
var vec:Vector.<DisplayObject> = new Vector.<DisplayObject>();
function getLowestXObject():DisplayObject
{
var minX:DisplayObject = vec[0];
for(var i:int = 1; i < vec.length; i++)
{
if(minX.x > vec[i].x)
{
minX = vec[i];
}
}
return minX;
}

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;
}

Actionscript 3 while loop with indexOf

Is there any reason why this loop is getting stuck? I can't quite get my head around it:
var i:Number = -1;
do
{
i = Math.round(Math.random() * _totalQuestions);
}
while(_usedQuestions.indexOf(i));
Where _usedQuestions is an array of numbers. This array starts empty.
Thanks!
Edit: I want the loop to end if i is NOT found in the array.. this way I know the question I have selected has not previously been asked.
There are really two answers here.
The loop never exits because Array.indexOf() returns -1 if the argument is not found, and -1 is true in a boolean context. The only way your loop will ever exit is if i happens to be equal to _usedQuestions[0].
It may not be obvious, but even if you fix the above problem your loop will still fail to exit once all the questions have been used... and that's your real problem - you're using a confusing algorithm to do something simple.
It would make a lot more sense to simply keep two arrays - one of unseen questions and one of seen questions. Every time you choose a new question, simply remove it from unseen and add it to seen. Like this:
if (unseen.length > 0) {
var i:int = Math.floor( Math.random() * unseen.length );
seen.push( unseen[i] );
unseen.splice(i, 1);
} else // all questions seen...
Remember: writing programs that work correctly is merely the minimum requirement of programming. A good programmer writes programs that are easily understood by people as well! And a big part of that is making sure that simple things are done in simple ways. (Unless performance is an inescapable factor - but in this case, I absolutely promise that it won't!)
Try this.
var i:Number = -1;
var found:Boolean;
do
{
i = Math.round(Math.random() * _totalQuestions);
found = false;
for (var j:int = 0; j < _usedQuestions.length; j++)
{
// assume that _usedQuestions is an array which holds the question
// number that has been selected before
if (_usedQuestions[j] == i)
{
found = true;
// get out of for loop if found, we'll need to get another
// random number
break;
}
}
}
while (found);
I'm not really proficient with AS3 since just started learning it so someone might have a more efficient way to do the above.
indexOf will return -1 if there is nothing found so use that value, also for avoiding an infinite loop check that _useQuestions does not contains all your totalQuestions :
Edit : a more complete version to illustrate:
var checked:int = 0;
var seen:Dictionary = new Dictionary();
while (checked < _totalQuestions) {
var i:int = int(Math.random() * _totalQuestions);
if (_usedQuestions.indexOf(i) < 0) {
break;
} else if (seen[i] === undefined) {
seen[i] = i;
checked++;
}
}
if (checked < _totalQuestions) {
//ok you have found a non used questions
} else {
// all questions have been used
}