Removing array-objects from DisplayList - actionscript-3

I'm working on a game for the iPhone using flash, and since memory is crucial i want to clean up displayObjects not needed. All the objects i need to delete is MovieClips taken from some array to another using splice(). Here is the code.
public function onTick(e:TimerEvent):void
{
randomNr = Math.random();
if ( randomNr > 0.9 )
{
var newFriend:Friend = new Friend( randomX, -15 );
newFriend.cacheAsBitmap = true;
army.push(newFriend);
addChild(newFriend);
}
for (var i:int = 0; i < army.length;i++)
{
army[i].y += 3;
if (avatar.hitTestObject(army[i]))
{
mood = false;
TweenLite.to(army[i], .3, {x:308, y:458, scaleX:.7, scaleY:.7, ease:Expo.easeOut, onComplete:fadeFace, onCompleteParams:[army[i],mood]});
deleted.push(army.splice(i,1));
}
}
}
private function cleanUp(e:MouseEvent):void
{
var totalDel:int = deleted.length;
for(var i:int = 0; i < totalDel ;i++)
{
removeChild(deleted[i]);
}
trace(totalDel + " Dele from deleted");
}
My problem is that i get an error when trying to use the CleanUp function.
I can trace all objects in the array and they show as [object Friend], but when trying to remove then from the displayList i get this Error: Error #1034: Type Coercion failed: cannot convert []#2c11309 to flash.display.DisplayObject.
Might be the wrong method im using!? Need some guidance please :)

Try casting each "Friend" as a Display Object:
var totalDel:int = deleted.length;
for(var i:int = 0; i < totalDel ;i++) {
var toDelete:DisplayObject = deleted[i] as DisplayObject;
removeChild(toDelete);
trace(totalDel + "Dele from deleted");
}

A friend coder ended up handing me the perfect solution:
private function cleanUp(arr:Array):void
{
var toDelete:DisplayObject;
var totalDel:int = 0;
while(arr.length >0)
{
toDelete = arr[0];
toDelete.parent.removeChild(toDelete);
arr.shift();
totalDel++
}
//trace(totalDel + "deleted from array " + arr.length + " left");
}
This way all objects gets deleted without any collapsing the array, which is exactly what i needed... Hope this will help someone withe the same problem.

Related

How To Link To A Frame Adobe Flash CS6 Action Script 3

i need help with my adobe flash assignment , i m still new to adobe flash :( how to tell the user if they input the wrong keyword how to link them to a frame .
var i:int = 0;
var names:Array = new Array("html","head","body");
var frames:Array = new Array("6","7","8");
searchhtmlll.text ="";
searchhtml.addEventListener(MouseEvent.CLICK, fl_MouseClickHandler_2);
function fl_MouseClickHandler_2(event:MouseEvent):void
{
findInArray(searchhtmlll.text);
gotoAndStop(frames[i]);
}
function findInArray(str:String):int
{
for(i = 0; i < names.length; i++)
{
if(names[i] == str)
{
return i;
}
}
return 0;
}
I am answering based on whatever limited information you have provided in your question, and from what I understand.
Your method findInArray has a return type of int, where as you are just calling it without assigning it to a variable.
So your code should be:
var result:int = findInArray(searchhtmlll.text);
gotoAndStop(frames[result]);
Hope this helps.

HitTest Function with two parameters not initializing

Hey guys so Basically what I'm trying to do is when my player collides with all 5 of the points MovieClips in an array and the Goal Movie Clip i want a text to appear saying "Perfect. But i cant quite accomplish this. I set up the function and it seems like it would but i think what might be wrong is the hitTest with all the Movie clips in the array.
Here is how i set it up:
This is in my loop Function:
private function gameLoop(e:Event):void
{
perfectTextFunction();
}
This is the function:
private function perfectTextFunction():void
{
if (player.hitTestObject(mcGoal_1 && points))
{
trace("perfect Text");
mcPerfect = new perfectText();
mcPerfect.x = (stage.stageWidth / 2);
mcPerfect.y = (stage.stageHeight/ 2);
stage.addChild(mcPerfect);
}
}
The Trace doesn't pick anything up.
Here is how the points are added to the stage if needed:
public function addPointsToStage():void
{
for (var i = 0; i < nPoints; i++)
{
trace(aPointsArray.length);
points = new mcGainPoints();
stage.addChild(points);
points.x = startPoint.x + (xSpacing * i);
points.y = startPoint.y - (ySpacing * i);
aPointsArray.push(points);
}
}
Please any help would be appreciated! THank you!
VESPER here is how I made the NESTED LOOP:
//If all points are hit then Perfect Hit Text
if (player.hitTestObject(mcGoal_1 || mcGoal_2))
{
var weHitAll:Boolean = true;
for (var s in aPointsArray)
{
weHitAll = weHitAll && player.hitTestObject(aPointsArray[s]);
if (!weHitAll)
break;
}
if (weHitAll)
{
trace("perfect Hit");
mcPerfect = new perfectText();
mcPerfect.x = (stage.stageWidth / 2);
mcPerfect.y = (stage.stageHeight/ 2) - 80;
stage.addChild(mcPerfect);
nScore += 25;
updateHighScore();
}
}
var weHitAll:Boolean=true;
for (var s in aPointsArray) {
weHitAll = weHitAll&&player.hitTestObject(aPointsArray[s]);
if (!weHitAll) break; // missed one, drop cycle
}
if (weHitAll) {
trace('Perfect hit!');
... // etc
}
Function hitTestObject accepts only a single object as parameter, in order to check against an array you need to iterate through it, checking against one object at a time (here it's in aPointsArray[s]).

Error joining AS2 with AS3

I have problems joining two scripts into one.
This is main part of the script: AS3.
And this is already joined script.
And here is part of the code that I need to import (AS2) :
stop();
var banners:Array = new Array();
var imagePaths:Array = new Array();
var links:Array = new Array();
var bodyTexts:Array = new Array();
var imageTime:Number;
var numberOfBanners:Number;
var isRandom:String;
var showHeader:String;
var bannersXML:XML = new XML();
bannersXML.ignoreWhite = true;
bannersXML.load("banners.xml");
bannersXML.onLoad = function(success) {
if (success) {
trace("XML LOADED");
imageTime = parseInt(this.firstChild.firstChild.firstChild)*1000;
numberOfBanners = parseInt(this.firstChild.childNodes[1].firstChild);
isRandom = this.firstChild.attributes["isRandom"];
showHeader = this.firstChild.childNodes[2].attributes["showHeader"];
var bannerSequence:Array = new Array();
if (isRandom == "true") {
//Make a random sequence
while (bannerSequence.length<numberOfBanners) {
newRandomNumber = random(numberOfBanners);
//Make sure that the random one chosen is not already chosen
for (var i = 0; i<=bannerSequence.length; i++) {
if (newRandomNumber != bannerSequence[i]) {
alreadyThere = false;
} else {
alreadyThere = true;
break;
}
}
//Add only random values that aren't in the array
if (!alreadyThere) {
bannerSequence.push(newRandomNumber);
}
}
} else {
for (var i = 0; i<numberOfBanners; i++) {
bannerSequence.push(i);
}
}
}
//Read XML in the Random Order Chosen
for (var i = 0; i<numberOfBanners; i++) {
banners.push(this.firstChild.childNodes[2].childNodes[bannerSequence[i]].firstChild.firstChild.toString());
bodyTexts.push(this.firstChild.childNodes[2].childNodes[bannerSequence[i]].childNodes[1].firstChild.nodeValue);
imagePaths.push(this.firstChild.childNodes[2].childNodes[bannerSequence[i]].childNodes[2].firstChild.nodeValue);
links.push(this.firstChild.childNodes[2].childNodes[bannerSequence[i]].childNodes[3].firstChild.nodeValue);
}
play();
};
//Start the image counter at 0
var imageCounter = 0;
I get erorr in this part of the code
function doRandArray(a:Array):Array {//make random array
var nLen:Number = a.length;
var aRand:Array = a.slice();
var nRand:Number;
var oTemp:Object;
for (var i:Number = 0; i < nLen; i++) {
oTemp = aRand[i];
nRand = i + (random(nLen – i));
aRand[i] = aRand[nRand];
aRand[nRand] = oTemp;
}
return aRand;
}
When I run it, I get an error in this place:
nRand = i + (random(nLen – i));
Scene 1, Layer 'Layer 1', Frame 1, Line 265 1084: Syntax error: expecting rightparen before i.
as2 random(random(nLen – i)); is generate 0,1,...nLen-i-1. not floating only int value.
correct as3 code is int(Math.random()*(nLen-i)); or Math.floor(Math.random()*(nLen-i));
as2: random()
as3: Math.random()
In ActionScript 3 the random function is a little bit different from what it was in as2 code, just change the offending line to:
nRand = i + Math.random()*(nLen-1);
This should fix all errors and work just the same.
EDIT: as #bitmapdata.com indicated, for this to run the same as in as2 the random value must be truncated (stripped of its decimal values). Besides the couple of possibilities he suggested, I would personally just change nRand's type to uint on declaration:
var nRand:uint;
You can also change the iterator type to var i:uint. Less memory usage is always good ;)

AS3 Closure Confusion

I have a small loop
var a:Array = [{name:Test1},{name:Test2},{name:Test3},{name:Test4}]
var b:GenericButton; //A pretty basic button component
for(var i:int = 0; i < a.length; i++){
b = new GenericButton(a[i].name, function():void { trace(i) });
this.addChild(b);
}
The function supplied to the GenericButton is executed when the button is pressed.
The problem I am having is that when the no matter what button I press the value of 4 (the length of the array) is always output.
How would I ensure that I trace 0 when the first button is pushed, 1 when the second is pushed, etc?
Well, you can simply do:
var f:* = function():void { trace(arguments.callee.index) };
f.index = i;
b = new GenericButton(a[i].name, f);
Better still:
function createDelegate(obj:Object, func:Function):Function
{
var f:* = function ():* {
var thisArg:* = arguments.callee.thisArg;
var func:* = arguments.callee.func;
return func.apply(thisArg, arguments);
};
f.thisArg = obj;
f.func = func;
return f;
}
...
for (...) {
b = new GenericButton(a[i].name,
createDelegate({index: i}, function():void { trace(this.index) }));
}
And in some (most?) cases it would be even better if you created a separate class and passed i into the constructor.
This is most basic error when using closures. You might be thinking that i is set when GenericButton is created. But closure just get direct link to variable i and uses this link when anonymous function is called. By this time, cycle is finished, and all links to i are pointing to same integer with value = 4.
To fix this, just pass value of i somehow - for example, as an additional argument to GenericButton constructor. In this case, a copy of i will be created on each step, with values of 0, 1, 2, 3 - just like you need.
...
b = new GenericButton(a[i].name, function(i:int):void { trace(i); }, i);
...
Store i in GenericButton and pass into function - this causes anonymous function to stop using context variable i (cycle counter) and forces it to use argument i.
Make a function that returns a function. Here's a FlexUnit test method that demonstrates it.
[Test]
public function closureWin():void
{
var functions:Array = [];
var mkFn:Function = function(value:int):Function
{
return function():int
{
return value;
}
}
var i:int;
for (i = 0; i < 10; i++)
{
functions.push(mkFn(i));
}
var j:int;
for(j = 0; j < 10; j++)
{
assertEquals(j, functions[j]());
}
}
Here's a test method demonstrating the behavior you are seeing:
[Test]
public function closureFail():void
{
// basically to see if this works the same way in as3 as it does in javascript
// I expect that all the functions will return 10
var i:int;
var functions:Array = [];
for (i = 0; i < 10; i++)
{
functions.push(function():int{return i});
}
var j:int;
for each (var f:Function in functions)
{
assertEquals(10, f());
}
}

How to pass argument in addEventListener (Action Script)

How do I pass arguments using ActionScript's event-listener?
I have code, as given below, which creates a label, and I want, when clicked on the label it should pass the toolTip associated with that label.
This is what I was trying to do:
public function create_folderpath():void
{
for(var i:int = 0; i < fm_model.absolute_path_ac.length; i++)
{
var absolutePathToolTip:String = new String;
for(var j:int = 0; j <= i; j++)
{
absolutePathToolTip += fm_model.absolute_path_ac[j].path.toString() + '/';
}
var textItem:Label = new Label();
textItem.data = absolutePathToolTip;
textItem.toolTip = absolutePathToolTip;
textItem.text = fm_model.absolute_path_ac[i].path.toString() + ' /';
textItem.addEventListener(MouseEvent.CLICK, testing)
directoryPathHBox.addChild(textItem);
}
}
public function testing(e:MouseEvent)
var direcoryLabel:Label = e.target as Label;
Alert.show(direcoryLabel.data +"");
}
This does not work, nor do I get any errors.
Please, I need help with this.
Thanks in advance
Zeeshan
Try to use "currentTarget" instead of "target":
var direcoryLabel:Label = e.currentTarget as Label;
Alert.show(direcoryLabel.data +"");
And be sure to add a trace in the listener, to know for sure if it's called or not.