I have an array of Movie Clips that are added to the stage by a timer event. This Movie Clip is called mSquare.Now I wanted to set up a EventListener for the Movie clip so whenever the user clicks on the Movie Clip then it is destroyed, But I am having trouble setting this up since there is an Array of them Added to the stage.
I keep getting this Error:
Cannot access a property or method of a null object reference.
Here is what I got so far:
mSquare.addEventListener(MouseEvent.CLICK, mIsDown);
Now in the mIsDown Function I know I have to go through the array so i tried to set up something like this:
private function mIsDown(e:MouseEvent):void
{
for (var i:int = 0; i < aSquareArray.length; i++)
{
//Get current Square in i loop
var currentSquare:mcSquare = aSquareArray[i];
if ( )
{
trace(currentSquare + "Mouse Is Down");
}
}
}
Also here is how my Square is added to the stage:
private function addSquare(e:TimerEvent):void
{
mSquare = new mcSquare();
stage.addChildAt(mSquare, 0);
mSquare.x = (stage.stageWidth / 2);
mSquare.y = (stage.stageHeight / 2) + 450;
aSquareArray.push(mSquare);
// trace(aSquareArray.length);
}
Any help would be appreciated on what i need to do in order for the user to be able to MOUSE.click or MouseDown for the array of movie clips thanks!
**************** Here is how I am doing it now***************
stage.addEventListener(MouseEvent.MOUSE_DOWN, movieClipHandler);
private function movieClipHandler(e:MouseEvent):void //test
{
mouseIsDown = true;
mSquare.addEventListener(MouseEvent.MOUSE_DOWN, squareIsBeingClicked);
}
private function squareIsBeingClicked(e:MouseEvent):void
{
var square:DisplayObject = e.target as DisplayObject; // HERE is your clicked square
var i:int = aSquareArray.indexOf(square); // and HERE is your index in the array
if (i < 0)
{
// the MC is out of the array
trace("Clicked");
checkSquareIsClicked();
} else
{
// the MC is in the array
}
}
private function checkSquareIsClicked():void
{
for (var i:int = 0; i < aSquareArray.length; i++)
{
var currentSquare:mcSquare = aSquareArray[i];
if (mouseIsDown)
{
aSquareArray.splice(i, 1);
currentSquare.destroySquare();
nLives --;
mouseIsDown = false;
}
}
}
The simplest answer is to use the target property of the event passed into the listener. This way you don't need to traverse the array in order to find what MC was clicked, you get it as target and go. To get the position of the targetted MC in the array, call indexOf function.
private function mIsDown(e:MouseEvent):void
{
var mc:DisplayObject = e.target as DisplayObject; // HERE is your clicked square
var i:int=aSquareArray.indexOf(mc); // and HERE is your index in the array
if (i<0) {
// the MC is out of the array
} else {
// the MC is in the array
}
}
Related
I have a gameObject with an ID, the gameObjects are spawned by giving initial ID: 1 , then any after spawned will be +1 so next is ID: 2.
I have two buttons that check current gameObjects ID#, BackOneButton (-1) and PlusOneButton (+1).
Currently it works but only if the array of gameObjects have IDs in order like for example [gameObject-ID:1], [gameObject-ID:2], [gameObject-ID:3]
But since you can self destruct a certain gameObject, here is where the error is --->
Now the array is not in order for example [gameObject-ID:1], [gameObject-ID:3], [gameObject-ID:4]. So if I'm currently in [gameObject-ID:3] and I use the BackOneButton and looks for ID: 2 it won't find it BUT there is ID:1. That's my error, I can't seem to figure out how to handle this.
Basically, How do I handle missing increments and skip over the missing?
Left Button (MinusOneButton)
void ButtonAction_LeftMinusOne()
{
// Get list of all gameObjects and -1 current to switch
string objName = manager.currentObjectTransform.name;
string[] splitArray = objName.Split('_');
string idObjNumber = splitArray[1];
switch (idObjNumber)
{
case "0":
// not supposed to be ID: 0
break;
case "1":
// nothing to go back to, this is ID: 1
break;
default:
// currently in (ID: 2 & Up) second object
int currentID = int.Parse(idObjNumber);
string idBackOne = (currentID - 1).ToString();
GameObject[] allObjInFull = GameObject.FindGameObjectsWithTag("Object");
if (allObjInFull.Length >= 2)
{
for (int i = 0; i < allObjInFull.Length; i++)
{
if (allObjInFull[i].transform.name.Contains(idBackOne))
{
// Set Camera
camera.transform.parent = allObjInFull[i].transform.GetChild(0).GetChild(1);
camera.transform.position = allObjInFull[i].transform.GetChild(0).GetChild(1).position;
camera.transform.rotation = allObjInFull[i].transform.GetChild(0).GetChild(1).rotation;
}
}
}
break;
}
}
Right Button (PlusOneButton)
void ButtonAction_RightPlusOne()
{
// Get list of all objects and +1 current to switch
string objName = manager.currentObjectTransform.name;
string[] splitArray = objName.Split('_');
string idObjNumber = splitArray[1];
switch (idObjNumber)
{
case "0":
// not supposed to be ID: 0
break;
default:
// currently in (ID: 1 & Up) object
int currentID = int.Parse(idObjNumber);
string idPlusOne = (currentID + 1).ToString();
GameObject[] allObjInFull = GameObject.FindGameObjectsWithTag("Object");
if (allObjInFull.Length >= 2)
{
for (int i = 0; i < allObjInFull.Length; i++)
{
if (allObjInFull[i].transform.name.Contains(idPlusOne))
{
// Set Camera
camera.transform.parent = allObjInFull[i].transform.GetChild(0).GetChild(1);
camera.transform.position = allObjInFull[i].transform.GetChild(0).GetChild(1).position;
camera.transform.rotation = allObjInFull[i].transform.GetChild(0).GetChild(1).rotation;
}
}
}
break;
}
}
It would be way better (especially regarding maintenance) and more efficient to have a central manager class with a List<GameObject> where you simply Add and Remove items dynamically. (Since you already seem to have one in manager I would rather extend that one)
public static class ObjectsManager
{
// If you are not concerned about
// capsulation you could ofcourse make this public as well
// but I thought this is cleaner
private static List<GameObject> objects;
// Read-only property
public static int Count
{
get
{
Initialize();
return objects.Count;
}
}
// initialize the list once
// I first had this in e.g. Awake
// but now you can easily use this in multiple scenes
public static void Initialize(bool force reinitialize = false)
{
if(objects != null && ! reinitialize) return;
objects = FindObjectsWithTag("Object").ToList();
}
public static void Add(GameObject newObject)
{
Initialize();
if(objects.Contains(newObject) return;
objects.Add(newObject);
}
public static void Destroy(GameObject toDestroy)
{
Initialize();
if(objects.Contains(toDestroy)
{
objects.Remove(toDestroy);
}
Object.Destroy(toDestroy);
}
public static int IndexOf(GameObject obj)
{
Initialize();
return objects.IndexOf(obj);
}
public static GameObject GetByIndex(int index)
{
Initialize();
// Use modulo to wrap around the index in case
// +1 or -1 exceeds the list ends
// in your case you might not need it
// but I decided to add it to be more flexible
var nextIndex = (index + 1) % objects.Count;
return objects[index];
}
}
Everytime you Instantiate a new object make sure to also call
ObjectsManager.Add(newObject);
and everytime where you destroy an object rather use
ObjectsManager.Destroy(objectToDestroy);
so it is also removed from the list first.
Then you can easily use
var currentIndex = ObjectsManager.IndexOf(certainObject);
to get the current index of an object and simply move through the index (+1, -1)
var nextObject = ObjectsManager.GetByIndex(currentIndex + 1);
var lastObject = Objects manager.GetByIndex(currentIndex - 1);
In case you switch the scene you have reinitialize the list once in order to get rid of null references
ObjectsManager.Initialize(true);
In your example code you would e.g. use something like
void ButtonAction_LeftMinusOne()
{
GameObject currentObject = manager.currentObjectTransform.gameObject;
int currentIndex = ObjectsManager.IndexOf(currentObject);
if(currentIndex < 0)
{
Debug.LogErrorFormat(this, "Object {0} is not in list!", currentObject.name);
return;
}
if(currentIndex == 0)
{
// nothing to do go back to
// Except you want wrap around then simply remove this check
Debug.Log("Already is first object in list", this);
return;
}
GameObject newObject = ObjectsManager.GetByIndex(currentIndex - 1);
Transform childOfNewObject = newObject.GetChild(0).GetChild(1);
// Set Camera
// Using simply SetParent with parameter worldPositionStays=false
// reduces it to one single call
camera.transform.SetParent( childOfNewObject, false);
}
And accordingly
void ButtonAction_RightPlusOne()
{
GameObject currentObject = manager.currentObjectTransform.gameObject;
int currentIndex = ObjectsManager.IndexOf(currentObject);
if(currentIndex < 0)
{
Debug.LogErrorFormat(this, "Object {0} is not in list!", currentObject.name);
return;
}
if(currentIndex == ObjectsManager.Count - 1)
{
// nothing to do go forward to
// Except you want wrap around then simply remove this check
Debug.Log("Already is last object in list", this);
return;
}
GameObject newObject = ObjectsManager.GetByIndex(currentIndex + 1);
Transform childOfNewObject = newObject.GetChild(0).GetChild(1);
// Set Camera
// Using simply SetParent with parameter worldPositionStays=false
// reduces it to one single call
camera.transform.SetParent( childOfNewObject, false);
}
I'm trying to create a drag and drop game in Actionscript 3 using mostly arrays. I'm doing it on a simpler game first before going to the main game because I need to know how the codes work first.
The simpler game is just there are two squares and two circles. The two squares are on a different array while the two circles are in the same one. What should happen is that when either circles hit (hitTestPoint) the right square, their x and y becomes the center of the square. (like it clicks to the center). And when either circles hit the left square, it should return the circles to their last position (doesn't have to be their original position).
Here's the code:
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.display.DisplayObject;
import flash.geom.Point;
import flash.events.Event;
public class MC_MAIN extends MovieClip
{
var mc1:mc_circle;
var mc2:mc_circle;
var mc3:mc_square;
var mc4:mc_square;
var Shapes:Array;
var Target:Array;
var WTarget:Array;
var newPlace:Point;
public function MC_MAIN()
{
// constructor code
init();
}
function init():void
{
Shapes = new Array ;
Target = new Array ;
WTarget = new Array ;
mc3 = new mc_square();
mc3.height = 75;
mc3.width = 75;
mc3.x = 400;
mc3.y = 200;
Target.push(mc3);
addChild(mc3);
mc4 = new mc_square();
mc4.height = 75;
mc4.width = 75;
mc4.x = 150;
mc4.y = 200;
WTarget.push(mc4);
addChild(mc4);
mc1 = new mc_circle();
mc1.height = 25;
mc1.width = 25;
mc1.x = 100;
mc1.y = 100;
Shapes.push(mc1);
addChild(mc1);
mc2 = new mc_circle();
mc2.height = 25;
mc2.width = 25;
mc2.x = 200;
mc2.y = 200;
Shapes.push(mc2);
addChild(mc2);
for (var i:int = 0; i<Shapes.length; i++)
{
Shapes[i].addEventListener(MouseEvent.MOUSE_DOWN, DRG);
Shapes[i].addEventListener(MouseEvent.MOUSE_UP, SDRG);
}
}
function DRG(e:MouseEvent):void
{
e.currentTarget.startDrag();
}
function SDRG(e:MouseEvent):void
{
e.currentTarget.stopDrag();
for (var m:int = 0; m<Shapes.length; m++)
{
newPlace = new Point(Shapes[m].x,Shapes[m].y);
}
trace(newPlace);
for (var a:int = 0; a<Target.length; a++)
{
for (var b:int = 0; b<Shapes.length; b++)
{
if (Target[a].hitTestPoint(Shapes[b].x,Shapes[b].y))
{
Shapes[b].x = Target[a].x;
Shapes[b].y = Target[a].y;
}
}
}
for (var c:int = 0; c<WTarget.length; c++)
{
for (var d:int = 0; d<Shapes.length; d++)
{
if (WTarget[c].hitTestPoint(Shapes[d].x,Shapes[d].y))
{
Shapes[d].x = newPlace.x;
Shapes[d].y = newPlace.y;
}
}
}
}
}
}
What happens is that the code for the left square doesn't work but their are no syntax errors. Nothing happens when either circles hit the left square.
And when I'm trying to trace the position of the circles, It just shows the x & y coordinate of only one of them. (I guess it's tracing the first object of the array which is at index 0. I'm just asking if I guessed right for this part.)
I is a bit difficult to follow the logic and there are some points that doesn't make much sense like:
for (var m:int = 0; m<Shapes.length; m++)
{
newPlace = new Point(Shapes[m].x,Shapes[m].y);
}
newPlace will be the position of the last shape in Shapes, so the loop is fairly useless.
I guess what you need is something like that:
public class MC_MAIN extends MovieClip
{
private leftSquares:Array;
private rightSquares:Array;
//more of the members from above
private startPos:Point;
//init the thing and add left and right squares
//to there respective Array
function DRG(e:MouseEvent):void
{
var t:DisplayObject = e.currentTarget;
//save the starting position
startPos = new Point(t.x,t.y);
t.startDrag();
}
function SDRG(e:MouseEvent):void {
var t:DisplayObject = e.currentTarget;
//find all squares from the left
//the target »hits«
var leftHits:Array = leftSquares.filter(
function (square:DisplayObject) {
return square.hitTestPoint(t.x, t.y);
});
//same for the right
var leftHits:Array = rightSquares.filter(
function (square:DisplayObject) {
return square.hitTestPoint(t.x, t.y);
});
//now you can apply the logic
//based on the hit Test result
//this way you can handle the case
//if it hits both, to throw an error
//or alike
if(leftHits.length > 0) {
//reset position
t.x = startPos.x;
t.y = startPos.y;
}
else if (rightHits.length > 0) {
//set the position tp the desired item in rightHits
}
else {
}
}
}
Please not that my Action Script skills haven't been used for a long time, so the code above might not compile. It is meant to illustrate the idea. Important are the following steps:
1. Save the starting position, to be able to reset it
2. Sort the `squares` in respective lists for left and right
3. Hit test both and apply the logic.
Im making a game and i complete the level1 at frame1.
When im trying to make the level2 to frame2 i dont know how to transfer my Arrays
to frame2.All the other buttons and functions are working(i copy the eventListeners to frame2)but my enemies wich are in Arrays does nothing!!
Thanks a lot!!!
import flash.events.Event;
stop();
//variables the helicopters
var enemy1Array:Array = new Array();
for (var e1:int = numChildren - 1; e1 >= 0; e1--)
{
var child:DisplayObject = getChildAt(e1);
if (child.name == "enemy1")
{
enemy1Array.push(child);
}
}
stage.addEventListener(Event.ENTER_FRAME, allloop);
function allloop(event:Event):void
{
//move the helicopters
for each(var enemy1:Sprite in enemy1Array)
{
enemy1.x = enemy1.x -= enemy1speed;
if(enemy1.hitTestObject(defense))
{
addChild(explotionbonus3);
explotionbonus3.gotoAndPlay(2);
explotionbonus3.x = enemy1.x;
explotionbonus3.y = enemy1.y;
enemy1.y = 1000;
score -=5;
scoretxt.text = String (score);
}
}
}
I'm using a tutorial I found on Google - which works well. However, I have a few issues to make it work how I would like. This code uses a MovieClip for the card faces with the back of the card on frame1 and 2-17 different pictures or movieclips.
The questions are - Is there a way to get the ActionScript to choose from the whole array? But still produce pairs to choose from. As it stands now - If I select the game to be 4 across by 2 down (8 cards in total) It has the back of card (frame1) and will then randomly select, but only from frames 2-5 . If I modify these lines...
public function MatchingGameObject10():void {
// make a list of card numbers
var cardlist:Array = new Array();
for(var i:uint=0;i<boardWidth*boardHeight/2;i++) {
cardlist.push(i);
cardlist.push(i);
}
to
public function MatchingGameObject10():void {
// make a list of card numbers
var cardlist:Array = new Array(0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17);
}
I get random cards - but no pairs...
If I can ask another question here - it is - how to add a seperate sound to each card..So if it shows a Bee - the Bee.mp3 is played.. Here's the whole code..
package {
import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.utils.getTimer;
import flash.utils.Timer;
import flash.media.Sound;
import flash.media.SoundChannel;
public class MatchingGameObject10 extends MovieClip {
// game constants
private static const boardWidth:uint = 4;
private static const boardHeight:uint = 2;
private static const cardHorizontalSpacing:Number = 500;
private static const cardVerticalSpacing:Number = 700;
private static const boardOffsetX:Number = 50;
private static const boardOffsetY:Number = 70;
private static const pointsForMatch:int = 10;
private static const pointsForMiss:int = -1;
// variables
private var firstCard:Card10;
private var secondCard:Card10;
private var cardsLeft:uint;
private var gameScore:int;
private var gameStartTime:uint;
private var gameTime:uint;
// text fields
private var gameScoreField:TextField;
private var gameTimeField:TextField;
// timer to return cards to face-down
private var flipBackTimer:Timer;
// set up sounds
var theFirstCardSound:FirstCardSound = new FirstCardSound();
var theMissSound:MissSound = new MissSound();
var theMatchSound:MatchSound = new MatchSound();
// initialization function
public function MatchingGameObject10():void {
// make a list of card numbers
var cardlist:Array = new Array();
for(var i:uint=0;i<boardWidth*boardHeight/2;i++) {
cardlist.push(i);
cardlist.push(i);
}
// create all the cards, position them, and assign a randomcard face to each
cardsLeft = 0;
for (var x:uint=0; x<boardWidth; x++) {// horizontal
for (var y:uint=0; y<boardHeight; y++) {// vertical
var c:Card10 = new Card10();// copy the movie clip
c.stop();// stop on first frame
c.x = x*cardHorizontalSpacing+boardOffsetX;// set position
c.y = y*cardVerticalSpacing+boardOffsetY;
var r:uint = Math.floor(Math.random()*cardlist.length);// get a random face
c.cardface = cardlist[r];// assign face to card
cardlist.splice(r,1);// remove face from list
c.addEventListener(MouseEvent.CLICK,clickCard);// have it listen for clicks
c.buttonMode = true;
addChild(c);// show the card
cardsLeft++;
}
}
// set up the score
gameScoreField = new TextField();
addChild(gameScoreField);
gameScore = 0;
showGameScore();
// set up the clock
gameTimeField = new TextField();
gameTimeField.x = 450;
addChild(gameTimeField);
gameStartTime = getTimer();
gameTime = 0;
addEventListener(Event.ENTER_FRAME,showTime);
}
// player clicked on a card
public function clickCard(event:MouseEvent) {
var thisCard:Card10 = (event.target as Card10); // what card?
if (firstCard == null) { // first card in a pair
firstCard = thisCard; // note it
thisCard.startFlip(thisCard.cardface+2);
playSound(theFirstCardSound);
} else if (firstCard == thisCard) { // clicked first card again
firstCard.startFlip(1);
firstCard = null;
playSound(theMissSound);
} else if (secondCard == null) { // second card in a pair
secondCard = thisCard; // note it
thisCard.startFlip(thisCard.cardface+2);
// compare two cards
if (firstCard.cardface == secondCard.cardface) {
// remove a match
removeChild(firstCard);
removeChild(secondCard);
// reset selection
firstCard = null;
secondCard = null;
// add points
gameScore += pointsForMatch;
showGameScore();
playSound(theMatchSound);
// check for game over
cardsLeft -= 2; // 2 less cards
if (cardsLeft == 0) {
MovieClip(root).gameScore = gameScore;
MovieClip(root).gameTime = clockTime(gameTime);
MovieClip(root).gotoAndStop("gameover");
}
} else {
gameScore += pointsForMiss;
showGameScore();
playSound(theMissSound);
flipBackTimer = new Timer(2000,1);
flipBackTimer.addEventListener(TimerEvent.TIMER_COMPLETE,returnCards);
flipBackTimer.start();
}
} else { // starting to pick another pair
returnCards(null);
playSound(theFirstCardSound);
// select first card in next pair
firstCard = thisCard;
firstCard.startFlip(thisCard.cardface+2);
}
}
// return cards to face-down
public function returnCards(event:TimerEvent) {
firstCard.startFlip(1);
secondCard.startFlip(1);
firstCard = null;
secondCard = null;
flipBackTimer.removeEventListener(TimerEvent.TIMER_COMPLETE,returnCards);
}
public function showGameScore() {
gameScoreField.text = "Score: "+String(gameScore);
}
public function showTime(event:Event) {
gameTime = getTimer()-gameStartTime;
gameTimeField.text = "Time: "+clockTime(gameTime);
}
public function clockTime(ms:int) {
var seconds:int = Math.floor(ms/1000);
var minutes:int = Math.floor(seconds/60);
seconds -= minutes*60;
var timeString:String = minutes+":"+String(seconds+100).substr(1,2);
return timeString;
}
public function playSound(soundObject:Object) {
var channel:SoundChannel = soundObject.play();
}
}
}
Here's Card10 class
package {
import flash.display.*;
import flash.events.*;
public dynamic class Card extends MovieClip {
private var flipStep:uint;
private var isFlipping:Boolean = false;
private var flipToFrame:uint;
// begin the flip, remember which frame to jump to
public function startFlip(flipToWhichFrame:uint) {
isFlipping = true;
flipStep = 10;
flipToFrame = flipToWhichFrame;
this.addEventListener(Event.ENTER_FRAME, flip);
}
// take 10 steps to flip
public function flip(event:Event) {
flipStep--; // next step
if (flipStep > 5) { // first half of flip
this.scaleX = .20*(flipStep-6);
} else { // second half of flip
this.scaleX = .20*(5-flipStep);
}
// when it is the middle of the flip, go to new frame
if (flipStep == 5) {
gotoAndStop(flipToFrame);
}
// at the end of the flip, stop the animation
if (flipStep == 0) {
this.removeEventListener(Event.ENTER_FRAME, flip);
}
}
}
}
So without completely re-factoring how this game works, the best way to make it dynamic based off the amount of frames (card faces) in your Card10 Clip, is change this code:
var cardlist:Array = new Array();
for(var i:uint=0;i<boardWidth*boardHeight/2;i++) {
cardlist.push(i);
cardlist.push(i);
}
To the following:
var allCards:Array = new Array(); //an array of all available frame numbers
var cardlist:Array = new Array(); //an array of just those cards to show
var tmpCard:Card10 = new Card10(); //create a temporary card for the sole purpose of counting how many frames it has
var i:int;
//populate the array with all the frames from the Card MC
for (i = 0; i < tmpCard.totalFrames;i++) {
allCards.push(i);//add card frame to allCards array
}
//now create the list of cards to show (since the amount of cards may be more than the amount you want to show
for (i = 0; i < (boardWidth * boardHeight) / 2; i++) {
var cardIndex:int = Math.floor(Math.random() * allCards.length);// get a random card from the all card list
//add the card twice (so there is a pair) in the list of cards to show
cardlist.push(cardIndex);
cardlist.push(cardIndex);
//remove it from the all cards array so it doesn't come up again in the random bit above
allCards.splice(cardIndex,1);
}
I am using math.random to randomly drop objects from the top of the stage. I had it working with one object. But as I wanted to increase the number to 6 objects, I added the following code: But I am "stuck" and so are the 6 objects at the top of the stage. What am I doing wrong here? I appreciate the help.
private function bombInit(): void {
roachBombArray = new Array();
for (var i:uint =0; i < numBombs; i++) {
roachBomb= new RoachBomb();
roachBomb.x = Math.random() * stage.stageWidth;
roachBomb.vy = Math.random() * 2 -1;
roachBomb.y = -10;
addChild(roachBomb);
roachBombArray.push(roachBomb);
}
addEventListener(Event.ENTER_FRAME, onEntry);
}
private function onEntry(event:Event):void {
for (var i:uint = 0; i< numBombs; i++) {
var roachBomb = roachBombArray[i];
vy += ay;
roachBombArray[i] += vy;
if (roachBombArray[i] > 620) {
removeChild(roachBombArray[i]);
removeEventListener(Event.ENTER_FRAME, onEntry);
You are trying to add the velocity to the RoachBomb rather than to the RoachBomb y position.
roachBombArray[i] += vy;
should be
roachBombArray[i].y += vy;
Additionally you create a local variable:
var roachBomb = roachBombArray[i];
but you never manipulate it.
Perhaps you meant to do something like this?
var roachBomb:RoachBomb = roachBombArray[i]; // I added the type to the local variable
roachBomb.vy += ay;
roachBomb.y += vy; // Manipulate the local variable
if (roachBomb.y > 620) {
removeChild(roachBomb);
}
You're removing your enterFrame listener when the first bomb goes off the bottom, at which point you're no longer listening for ENTER_FRAME events and updating any of your bombs.
You don't want to remove this listener until you're done animating ALL the bombs.
UPDATE: How I would expect things to look, incorperating Ethan's observation that you ought to use the local roachBomb that you declare...
public class BombDropper extends Sprite {
private static const GRAVITY:int = 1; // Set gravity to what you want in pixels/frame^2
private static const BOTTOM_OF_SCREEN:int = 620;
private var numBombs:int = 6;
private var roachBombArray:Array;
// ... constructor and other class stuff here
private function bombInit(): void
{
roachBombArray = new Array();
for (var i:int =0; i < numBombs; ++i)
{
var roachBomb:RoachBomb = new RoachBomb();
roachBomb.x = Math.random() * stage.stageWidth;
roachBomb.vy = Math.random() * 2 -1;
roachBomb.y = -10;
this.addChild(roachBomb);
roachBombArray.push(roachBomb);
}
this.addEventListener(Event.ENTER_FRAME, onEntry);
}
private function onEntry(event:Event):void
{
for each ( var roachBomb:RoachBomb in roachBombArray)
{
roachBomb.vy += GRAVITY;
roachBomb.y += vy;
if (roachBomb.y > BOTTOM_OF_SCREEN)
{
this.removeChild(roachBomb);
roachBombArray.splice(roachBombArray.indexOf(roachBomb),1);
if (roachBombArray.length == 0)
{
this.removeEventListener(Event.ENTER_FRAME, onEntry);
}
}
}
}
}