removing multiple movieclips - actionscript-3

I'm developing a game.I've attached random movieClips from library. I've movieClips named picLeft1, picLeft2, picLeft3 and so on in library. Its working fine but i'm having problem removing it. the code below is for the attachment of movieclip. Here ranque is an array which stores randomly generated numbers up to 5 and HolderL is the movieClip in which I want to attach the movieClip. And q is a sprite.
for (var i:int = 0; int<3; i++) {
que_mc.push("picLeft"+ranque[i]);
var que_mc_class:Class = getDefinitionByName(que_mc[i]) as Class;
q = new que_mc_class();
this["HolderL"+(i+1)].addChild(q);
}
my code for removing the movieclip is given below.I want to remove all the movieclip attached in HolderL. but this code is not working.
for(var j:int = 1; j<=3; j++) {
this["HolderL"+j].removeChild(q);
}

Flash Player 11 allows you to use this:
for (var j:int = 1; j<=3; j++) {
var container : DisplayObjectContainer = this["HolderL"+j];
container.removeChildren();
}
Earlier versions don't have the removeChildren() command; you have to have two loops: One to loop to iterate over the container movie clips, one to traverse the display list and remove all children.
Shortest way to remove all children of a container prior to FlashPlayer 11:
while (container.numChildren > 0) container.removeChildAt(0);

It's not clear from your code what q is, but basically if you want to remove all the children from one movie clip, the simplest is to loop through all the children and remove them one by one. For example:
for (var i:int = container.numChildren - 1; i >= 0; i--) {
container.removeChildAt(i);
}

Related

AS3 - How to animate all movie clips in the stage if i click a certain button

Hi have been reading on this great website, here is what i want to accomplish,
on this certain page in the app im doing, there are movie clips (buttons, texts, menus) , now what i want is if i click this "close" button, i want everything to animate e.g shrink one by one. Question: Is there a great way to code this efficiently, and not coding it one by one e.g menu_mc.gotoAndPlay("out");, text_mc.gotoAndPlay("out"); image.gotoAndPlay("out"); ...something like that. Sorry im so new to this, any help will be greatly appreciated.
You could iterate the DisplayList, and call your method...
for (var i:int = 0; i < this.numChildren; i++) {
var obj:* = this.getChildAt(i);
if (obj is MovieClip) {
obj.gotoAndPlay("out");
}
}
Or you could animate with an animation library (such as Greensock)...
for (var i:int = 0; i < this.numChildren; i++) {
var obj:* = this.getChildAt(i);
TweenLite.to(obj, .35, {scaleX:0.5, scaleY:0.5, delay:0.25*i});
}
Or you could reference an Array for the objects you want to animate; a superior choice (if your objects aren't in the same container).
var a:Array = [menu_mc, text_mc, image];
for (var i:int = 0; i < a.length; i++) {
TweenLite.to(a[i], .35, {scaleX:0.5, scaleY:0.5, delay:0.25*i});
}

Object removed from screen before the relevant command is called (Error #1009)

I'm sorry if it's asking for too much, but I'm too confused by now. I'm making this really simple shooter game for my nephew in AS3. It all seems to be working just fine, except for one really annoying error that keeps popping up every second or third time the game is launched.
IT is Error #1009: Cannot access a property or method of a null object reference. The problem is always with parent.removeChild(this) command in the relevant class (EnemyClass, BulletClass or MissileClass). This happens in two cases: either when checkFinishConditions method in Main is called and the EnemyClass instance needs to be deleted. So if I get the #1009 error does this mean the instance has already been deleted? The second situation is when inst.hitTestObject(enemyInstance) is checked in Main class. Does this mean the EnemyClass instance has already been deleted somehow? I'm totally lost here to be honest.
private function checkCollision():void
{
//loop through missiles
for (var i:int = 0; i < aMissileArray.length; i++) {
//get the current missile
var currentMissile:missileClass = aMissileArray[i];
//loop through enemies
for (var j:int = 0; j < aEnemyArray.length; j++) {
var thisEnemy:EnemyClass = aEnemyArray[j];
if (currentMissile.hitTestObject(thisEnemy)) {
var thisExplode:ExplosionClass = new ExplosionClass(thisEnemy.x,thisEnemy.y);
addChild(thisExplode);
currentMissile.destroyThis();
aMissileArray.splice(i,1);
thisEnemy.deleteEnemy();
aEnemyArray.splice(j, 1);
aDamageArray.splice(j, 1);
scoreValueText += 1;
j--;
i--;
}
//break;
}
}
//loop through bullets
for (var l:int = 0; l < aBulletArray.length; l++) {
//get the current missile
var currentBullet:BulletClass = aBulletArray[l];
//loop through enemies
for (var k:int = 0; k < aEnemyArray.length; k++) {
var currentEnemy:EnemyClass = aEnemyArray[k];
if (currentBullet.hitTestObject(currentEnemy)) {
currentBullet.destroyThis();
aBulletArray.splice(l, 1);
aDamageArray[k] -= 1;
l--;
if (aDamageArray[k] < 1) {
//create an explosion
var thisBulletExplode:ExplosionClass = new ExplosionClass(currentEnemy.x,currentEnemy.y);
addChild(thisBulletExplode);
currentEnemy.deleteEnemy();
aEnemyArray.splice(k, 1);
aDamageArray.splice(k, 1);
scoreValueText += 1;
k--;
}
break;
}
}
}
}
There is alot of code to look over, but one potential issue I see is here :
for each(var currentDieEnemy:EnemyClass in aEnemyArray) {
aEnemyArray.splice(0, 1);
currentDieEnemy.deleteEnemy();
}
The potential issue is that you are 'assuming' that the order of this loop is sequential based on the actual index order of the Array. You might want to stick a trace in there to verify that is actually what is happening, because I believe it's possible that they can be out of order.
See this question for details -- For-Each Loop AS3: Is the direction guaranteed?
So imagine the scenario where the 3rd item in the array is first and you splice the item at the 0 index. Now, you have an item in the array that is removed from the display list, but not from the array. So what happens when you get to that item ? Pretty much what you are describing will happen since the parent property is null, since you already removed it from the display list.
The way to fix that is to do something like this :
while (aEnemyArray.length > 0)
{
var currentDieEnemy:EnemyClass = aEnemyArray[0];
currentDieEnemy.deleteEnemy();
aEnemyArray.splice(0,1);
}
I found another issue in this block of code :
for (var j:int = 0; j < aEnemyArray.length; j++) {
var thisEnemy:EnemyClass = aEnemyArray[j];
if (currentMissile.hitTestObject(thisEnemy)) {
var thisExplode:ExplosionClass = new ExplosionClass(thisEnemy.x,thisEnemy.y);
addChild(thisExplode);
currentMissile.destroyThis();
aMissileArray.splice(i,1);
thisEnemy.deleteEnemy();
aEnemyArray.splice(j, 1); // now array composition is different.
aDamageArray.splice(j, 1);
scoreValueText += 1;
}
}
When you loop through an Array and splice an item at the loop index, you have to realize what happens to the composition of the array. Here's an example
Suppose enemy3 needs to be spliced because of a collision. Given your code, this is what happens :
Before (j == 2)
(0) enemy1
(1) enemy2
(2) enemy3
(3) enemy4
(4) enemy5
AFTER
(0) enemy1
(1) enemy2
(2) enemy4
(3) enemy5
So when the loop continues, j will now increment and equal 3.
The result is that enemy4 doesn't get evaluated as the composition of the array collapses to fill the hole created by the splice and you didn't adjust your loop index variable.
So, what you can do in that situation is simply decrement the loop index variable at the end of the block like so :
aEnemyArray.splice(j, 1); // now array composition is different.
aDamageArray.splice(j, 1);
scoreValueText += 1;
j--; // decrement loop index variable.
So while this is one solution, the main point to take away here is the change in the composition of your Array after a splice.
Yep, you are splicing your objects from arrays in a weird way. First, you are traversing the array forwards and splicing in the loop. This can lead to issues of several bullets not trigger collisions when they should, or say not move. See, if you are running your loop for bullets at index i, once you call bullets.splice(i,1); the bullet that was to be iterated next becomes at position i, then you increment i and that bullet remains unprocessed.
Next, you have nested loops, and in the inner loop you are removing an object from OUTER loop. This means once you did a removal of the outer loop's object, your inner loop is now invalidated, you have to preemptively terminate inner loop.
//loop through bullets
for (var l:int = aBulletArray.length-1; l>=0; l--) {
// first, traverse both arrays backwards
//get the current missile
var currentBullet:BulletClass = aBulletArray[l];
//loop through enemies
for (var k:int = aEnemyArray.length-1; k>=0; k--) {
var currentEnemy:EnemyClass = aEnemyArray[k];
if (currentBullet.hitTestObject(currentEnemy)) {
currentBullet.destroyThis();
aBulletArray.splice(l, 1);
aDamageArray[k] -= 1;
if (aDamageArray[k] < 1) {
//create an explosion
var thisExplode:ExplosionClass = new ExplosionClass(currentEnemy.x,currentEnemy.y);
addChild(thisExplode);
currentEnemy.deleteEnemy();
aEnemyArray.splice(k, 1);
aDamageArray.splice(k, 1);
scoreValueText += 1;
}
// and since we don't have "currentBullet" anymore, do this
break;
}
}
}
Fix all the other iterations through your arrays where you do splicing, like I did in this part of code, and you should avoid 1009 errors in these loops.
Also, you should not post your entire project code, but instead post only relevant parts, say an entire function that's reported as throwing an error, and explain which line is producing the error - it's written as number in the error's stack trace.

Order of instances in 3D Flash

I'm making cube of 9 cubes in Flash As3. However i cant rotate it properly due to order of indexes whole adding then to stage.
First im creating cube of 6 squares, then wall of 9 cubes, and at the end cube of 3 walls.
It is all fine, however when i rotate it to the left, order of cubes is inverted and it ruins whole composition. I know i coul dinamicly change index based on rotation but it would be a loooooooot of work.
Any ideas how could i do it better way?
Here is actual model:
http://test.mrowa.topdivision.pl/kostka/3DTest.html
If you are using the Flash's display list you would have to sort the sprites based on their z.
Here is some code that would sort the children of a DisplayObjectContainer based on their z position, call this whenever some object changes its position.
public function sortChildren(container:DisplayObjectContainer):void
{
var objects:Vector.<DisplayObject> = new Vector.<DisplayObject>;
for (var i:int = 0; i < container.numChildren; i++)
{
objects.push(container.getChildAt(i));
}
objects.sort(sortCompare);
var index:int = 0;
for (var j:int = 0; j < objects.length; j++)
{
index = container.getChildIndex(objects[j]);
if (index != j)
container.setChildIndex(objects[j], j);
}
}
private function sortCompare(a:DisplayObject, b:DisplayObject):int
{
return (a.z - b.z);
}
You can move the objects member to be a class member and add/remove items to it whenever you add/remove items to/from the stage so that you don't have to fill the whole array every time this function is called.

actionscript for loop iterator to change movie clip name

I have a bunch of movie clips I created in flash CS5 and are all placed within the stage. I control each one of them dynamically with code using ActionScript 3. However I want to control all of them at the same time using a for loop and just change the width of each element but its not working.
Here is my code:
for(var i:Number = 0; i < 100; i++)
{
leftBar+i.width = ( Math.round(channel.rightPeak * 1.1) ) + 60;
}
So I have 100 bars each called leftBar and their number. So the firstBar is leftBar1, then leftBar2 and so on. I cant get it to work however. I have tried "leftBar"+i and also leftBari but none of them seem to work.
The correct way to select each of those MovieClips in your loop is:
this["leftBar" + i]
New code:
// Note: We've changed the initial value of i to 1 because you mentioned that
// your first MovieClip was called 'leftBar1' rather than 'leftBar0'.
for(var i:int = 1; i <= 100; i++)
{
var current:MovieClip = this["leftBar" + i];
current.width = Math.round(channel.rightPeak * 1.1) + 60;
}
Basically you want to select the property leftBar0, leftBar1, etc from this using square brackets. It is the same as doing this:
this.leftBar0
And can also be used for any properties or methods of any other class:
// Example of Square Bracket notation.
var sprite:Sprite = new Sprite();
sprite["x"] = 10;
trace(sprite.x);
this["addChild"](sprite);

Problems getting objects in Stage

So, im using this code to remove a couple of movie clips from my stage:
for (var i:uint = 0; i < this.numChildren; i++)
{
if (this.getChildAt(i) is MovieClip
&& pecasInGame.indexOf(this.getChildAt(i)) >= 0)
{
removeChild(this.getChildAt(i));
}
}
But its not really working well... I have 5 movie clips to remove and they are all added dinamically, when these movieclips are added i insert then into this array "pecasInGame", and when there is five of then I try to remove using the aforementioned loop.
The problem is, it only removes 3 of then, the 0, 2 and 4 objects.. The 1 and 3 arent even listed in the loop. Any idea why would that happen??
You're removing the display objects, so the indexes are changing WHILE your loop goes on.
Change it this way:
for (var i:uint = this.numChildren-1; i >= 0 ; i--)
{
if (this.getChildAt(i) is MovieClip && pecasInGame.indexOf(this.getChildAt(i)) >= 0)
{
removeChild(this.getChildAt(i));
}
}
Other option: use your array to remove the objects, like this
for (var i:int=0; i<pecasInGames.length; i++) {
removeChild (pecasInGames[i]);
}
The problem is you are iterating over the children and removing at the same time, so the indices of the children are changing, which is causing the problem.
If you want to remove all the movie clips from the display list, do something like this :
for each(var mc:MovieClip in pecasInGame)
{
if(getChildIndex(mc) != -1)
removeChild(mc);
}