AS3 How to remove objects from the stage from various classes - actionscript-3

So I'm Creating a game that generates different types of fish. I have the main class initilize everything then the fish are generated with another class. I then have another class listen for when they are added to the stage that controls their movement. After the fish leaves the scene I have gotten them to be deleted but I cannot get them all to be deleted once the fish is clicked. I have a listener that gets when a fish is clicked but I am having trouble deleting all the other generated fish so that I can load the fish information.
I probably have tons of problems but here is my Main class:
package
{
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.display.*;
import flash.events.*;
import flash.ui.*;
import Crappie;
/*import Bass;
import Bluegill;
import LongGar;
import Muskellunge;
import Perch;
import PumpkinSeed;
import ShortGar;
import SpotGar;*/
import GenerateFish;
public class FishGame extends MovieClip
{
private var randomFish:Number;
public function FishGame() //First function to be called
{
startMenu();
}
public function startMenu() //Loads the start menu
{
gotoAndStop("Start Menu");
StartButton.addEventListener(MouseEvent.CLICK, gotoStartGame);
}
private function gotoStartGame(evt:MouseEvent) //links to the start of th game
{
StartButton.removeEventListener(MouseEvent.CLICK, gotoStartGame);
gotoAndStop("Game");
game();
}
public function game() /generates fish
{
var genFish:GenerateFish = new GenerateFish();
this.addChild(genFish);
var genFish2:GenerateFish = new GenerateFish();
this.addChild(genFish2);
}
//This is where I need help. All the fish are children of other class. I tried deleting them in their own class but it seems like it would work best if it was in this class but I'm having trouble calling this class.
public function removeFish()
{
trace("Here");
}
}
}
Here is the generating fish class:
package {
import flash.display.MovieClip;
import flash.events.*;
import flash.display.*;
import Crappie;
//import Bass;
//import Bluegill;
//import LongGar;
//import Muskellunge;
//import Perch;
//import PumpkinSeed;
//import ShortGar;
//import SpotGar;
import FishGame;
public class GenerateFish extends MovieClip {
private var randomFish:Number;
public function GenerateFish() //When this is added via addchild it adds a fish
{
this.addEventListener(Event.ADDED_TO_STAGE, addFish, false, 0, true);
//addFish();
}
private function addFish(e:Event) //adds fish to scrence
{
this.removeEventListener(Event.ADDED_TO_STAGE, addFish);
randomFish = Math.floor(Math.random() * 2);
randomFish = 0; //for testing purposes
switch(randomFish)
{
case 0:
var crappie:Crappie = new Crappie();
this.addChild(crappie); //Calls the crappy funciton
break;
case 1:
var longgar:LongGar = new LongGar();
this.addChild(longgar);
break;
case 2:
var bluegill:Bluegill = new Bluegill();
this.addChild(bluegill);
break;
case 3:
var spotgar:SpotGar = new SpotGar();
this.addChild(spotgar);
break;
case 4:
var muskellunge:Muskellunge = new Muskellunge();
this.addChild(muskellunge);
break;
case 5:
var pumpkinseed:PumpkinSeed = new PumpkinSeed();
this.addChild(pumpkinseed);
break;
case 6:
var bass:Bass = new Bass();
this.addChild(bass);
break;
case 7:
var perch:Perch = new Perch();
this.addChild(perch);
break;
case 8:
var pike:Pike = new Pike();
this.addChild(pike);
break;
default:
break;
}
}
}
}
And here is one of the specific fish classes:
package
{
import flash.display.MovieClip;
import flash.events.*;
import flash.display.*;
import FishGame;
import GenerateFish;
public class Crappie extends MovieClip
{
private var Speed:Number;
private var randomBoolean:Boolean = (Math.random() > .5) ? true : false;
private var fishOnScreen:Boolean = false;
//public var remFish:FishGame = new FishGame();
public function Crappie() //Adds event listeners to control the fish
{
this.addEventListener(Event.ADDED_TO_STAGE, Setup, false, 0, true);
this.addEventListener(MouseEvent.CLICK, GoToFishInfo);
fishOnScreen =true;
}
public function GoToFishInfo(evt:MouseEvent):void //When fish is clicked Info pops up. It is here i want every fish to be deleted.
{
this.removeEventListener(Event.ADDED_TO_STAGE, Setup);
/*while (MovieClip(root).numChildren >= 1) //What I tried to delete all objects
{
MovieClip(root).removeChildAt(1);
}*/
var remFish:FishGame = new FishGame(); //Creates The SWF file file:///FishGame/classes/FishGame.swf contains invalid data.
remFish.removeFish();
MovieClip(root).gotoAndStop("FishInfo", "Scene 1");
var crappieinfo:CrappieInfo = new CrappieInfo();
stage.addChild(crappieinfo);
crappieinfo.x = 512;
crappieinfo.y = 384;
crappieinfo.alpha = 100;
}
private function Setup(e:Event) //Setup the fish position and adds info for movement
{
var randomBoolean:Boolean = (Math.random() > .5) ? true : false;
//true forwards
//false is backwards
if (randomBoolean)
{
this.x = 1030;
}
else
{
this.scaleX = -1;
this.x = -10;
}
this.y = this.GetRandomYPosition();
this.alpha = 100;
this.addEventListener(Event.ENTER_FRAME, MoveCircle);
Speed = GetRandomSpeed();
if (randomBoolean)
{
Speed *= -1
}
}
private function GetRandomSpeed():Number
{
return (Math.floor(Math.random() * 5) +5);
}
private function GetRandomYPosition():Number
{
//
//basic formula: Math.floor(Math.random()*(1+High-Low))+Low;
//
return (Math.floor(Math.random() * (650-this.height)) + 230);
}
public function MoveCircle(e:Event) //Moves the fish
{
if (fishOnScreen)
{
this.x += Speed;
if (this.x >1024 || this.x < -10 || this.y >768 || this.y < 200)
{
var genExtraFish:GenerateFish = new GenerateFish();
stage.addChild(genExtraFish);
this.parent.removeChild(this);
fishOnScreen = false;
this.removeEventListener(MouseEvent.CLICK, GoToFishInfo);
}
}
}
}
}
Thanks I'd appreciate all the help I can get!
////////
//Edit//
////////
I have modified my main class to package
{
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.display.*;
import flash.events.*;
import flash.ui.*;
import BaseFish;
import GenerateFish;
public class FishGame extends MovieClip
{
private var randomFish:Number;
private var basefish:BaseFish = new BaseFish();
public function FishGame()
{
startMenu();
}
public function startMenu()
{
gotoAndStop("Start Menu");
StartButton.addEventListener(MouseEvent.CLICK, gotoStartGame);
}
private function gotoStartGame(evt:MouseEvent)
{
StartButton.removeEventListener(MouseEvent.CLICK, gotoStartGame);
gotoAndStop("Game");
basefish.StartFish();
}
}
}
And I Created the basefish class as so:
package
{
import flash.display.MovieClip;
import flash.events.*;
import flash.display.*;
import FishGame;
public class BaseFish extends MovieClip
{
public var FishOnScreen:Array = new Array();
public var FishSpeed:Array = new Array();
private var Speed:Number;
private var randomBoolean:Boolean = (Math.random() > .5) ? true : false;
public var NumFish:int = -1;
private var randomFish:Number;
public function BaseFish()
{
}
public function StartFish()
{
addFish(5);
this.addEventListener(Event.ENTER_FRAME, MoveCircle);
}
public function addFish(NumAdd:Number)
{
for (var i:Number = 0; i < NumAdd; i++)
{
randomFish = Math.floor(Math.random() * 2);
randomFish = 0;
switch(randomFish)
{
case 0:
var crappie:Crappie = new Crappie();
this.addChild(crappie);
crappie.addEventListener(MouseEvent.CLICK, GoToFishInfo);
FishOnScreen.push(crappie);
trace(FishOnScreen[1]);
Setup(crappie);
NumFish += 1;
break;
case 1:
var longgar:LongGar = new LongGar();
this.addChild(longgar);
longgar.addEventListener(MouseEvent.CLICK, GoToFishInfo);
FishOnScreen.push(longgar);
Setup(longgar);
NumFish += 1;
break;
case 2:
var bluegill:Bluegill = new Bluegill();
this.addChild(bluegill);
bluegill.addEventListener(MouseEvent.CLICK, GoToFishInfo);
FishOnScreen.push(bluegill);
Setup(bluegill);
NumFish += 1;
break;
case 3:
var spotgar:SpotGar = new SpotGar();
this.addChild(spotgar);
spotgar.addEventListener(MouseEvent.CLICK, GoToFishInfo);
FishOnScreen.push(spotgar);
Setup(spotgar);
NumFish += 1;
break;
case 4:
var muskellunge:Muskellunge = new Muskellunge();
this.addChild(muskellunge);
muskellunge.addEventListener(MouseEvent.CLICK, GoToFishInfo);
FishOnScreen.push(muskellunge);
Setup(muskellunge);
NumFish += 1;
break;
case 5:
var pumpkinseed:Pumpkinseed = new Pumpkinseed();
this.addChild(pumpkinseed);
pumpkinseed.addEventListener(MouseEvent.CLICK, GoToFishInfo);
FishOnScreen.push(pumpkinseed);
Setup(pumpkinseed);
NumFish += 1;
break;
case 6:
var bass:Bass = new Bass();
this.addChild(bass);
bass.addEventListener(MouseEvent.CLICK, GoToFishInfo);
FishOnScreen.push(bass);
Setup(bass);
NumFish += 1;
break;
case 7:
var perch:Perch = new Perch();
this.addChild(perch);
perch.addEventListener(MouseEvent.CLICK, GoToFishInfo);
FishOnScreen.push(perch);
Setup(perch);
NumFish += 1;
break;
case 8:
var pike:Pike = new Pike();
this.addChild(pike);
pike.addEventListener(MouseEvent.CLICK, GoToFishInfo);
FishOnScreen.push(pike);
Setup(pike);
NumFish += 1;
break;
default:
this.addChild(crappie);
crappie.addEventListener(MouseEvent.CLICK, GoToFishInfo);
FishOnScreen.push(crappie);
Setup(crappie);
NumFish += 1;
break;
}
}
}
private function Setup(mc: MovieClip)
{
var randomBoolean:Boolean = (Math.random() > .5) ? true : false;
//true forwards
//false is backwards
if (randomBoolean)
{
MovieClip(mc).x = 1030;
}
else
{
MovieClip(mc).scaleX = -1;
MovieClip(mc).x = -10;
}
MovieClip(mc).y = GetRandomYPosition();
MovieClip(mc).alpha = 100;
FishSpeed[NumFish] = GetRandomSpeed();
if (randomBoolean)
{
FishSpeed[NumFish] *= -1
}
}
private function GetRandomSpeed():Number
{
return (Math.floor(Math.random() * 5) +5);
}
private function GetRandomYPosition():Number
{
//
//basic formula: Math.floor(Math.random()*(1+High-Low))+Low;
//
return (Math.floor(Math.random() * (650-this.height)) + 230);
}
public function MoveCircle(e:Event)
{
//trace(FishOnScreen.length);
for (var i:Number = 0; i < FishOnScreen.length; i++)
{
if (FishOnScreen[i]!=null)
{
MovieClip(FishOnScreen[i]).x += FishSpeed[i];
if (MovieClip(FishOnScreen[i]).x >1024 || MovieClip(FishOnScreen[i]).x < -10 || MovieClip(FishOnScreen[i]).y >768 || MovieClip(FishOnScreen[i]).y < 200)
{
addFish(1);
this.removeChild(MovieClip(FishOnScreen[i]));
MovieClip(FishOnScreen[i]).removeEventListener(MouseEvent.CLICK, GoToFishInfo);
FishOnScreen.splice(i, 1);
FishSpeed.splice(i,1);
}
}
//else trace("null");
}
}
public function GoToFishInfo(evt:MouseEvent):void
{
dispose();
MovieClip(root).gotoAndStop("FishInfo", "Scene 1");
var crappieinfo:CrappieInfo = new CrappieInfo();
stage.addChild(crappieinfo);
crappieinfo.x = 512;
crappieinfo.y = 384;
crappieinfo.alpha = 100;
}
public function dispose():void
{
for (var i : int = this.numChildren-1 ; i >= 0 ; i--)
{
if(this.getChildAt(i) is MovieClip)
{
this.removeChildAt(i);
MovieClip(FishOnScreen[i]).removeEventListener(Event.ADDED_TO_STAGE, Setup);
MovieClip(FishOnScreen[i]).removeEventListener(MouseEvent.CLICK, GoToFishInfo);
}
}
}
}
}
It doesn't give me any errors but it doesn't display any fish. If you could take a look at my updated code I would be grateful!

To make things better and avoid duplication of code, extend all your classes such as Crappie, Bass etc from a Base Class, call it BaseFish for example. You should create a dispose() method in this base class. That way this dispose method will be automatically available to all classes extending it. In fact, you can use this method to write common code at one place and avoid duplication.
Also, if you feel it suits the need, extend GenerateFish also from the base class, or create a similar method called dispose() in this class.
Then when you call your removeFish() method, you can call these dispose methods for your individual classes.
Create the method like this (this is just to get you started):
public function dispose():void
{
for (var i : int = this.numChildren-1 ; i >= 0 ; i--)
{
if(this.getChildAt(i) is MovieClip)
{
this.removeChildAt(i);
}
}
}
This code removes every child which is a movie clip. You may also want to remove any Event Listeners which are added in your class inside this method.
Then, move your variables genFish and genFish2 to class variables, and not declare them inside your method game()
Now in your removeFish() method do this:
public function removeFish()
{
genFish.dispose();
genFish2.dispose();
}
Follow the same logic inside your GenerateFish class to dispose all the children as they will now be instances of the same base class.
Another thing, which could be very important from a performance perspective is the ENTER_FRAME event that you are adding. Notice that this event is being added to each instance that you create inside GenerateFish. So, every instance will have its own enter frame. Maybe it will work ok in your current situation as the number of instances may be less, but this approach is not scalable, and tomorrow if you have many instances, it will certainly hinder performance.
Ideally, you should try to have only one ENTER_FRAME event listener in your main class and use the handler to change things inside your child classes.
Hope this helps you.

Related

Score not displaying in AS3

I've got this code that mostly works. I know the ammo is being tracked correctly because I have it to be game over when the ammo runs out. My problem is that neither the score nor the remaining ammo are displaying. I'm not sure what I'm missing. Here's the code that I have relating to the issue.
package {
import flash.display.*;
import flash.events.*;
import flash.utils.Timer;
import flash.text.TextField;
import flash.media.Sound;
import flash.media.SoundChannel;
public class AirRaid extends MovieClip {
private var aagun:AAGun;
private var airplanes:Array;
private var bullets:Array;
public var leftArrow, rightArrow:Boolean;
private var nextPlane:Timer;
private var shotsLeft:int;
private var shotsHit:int;
public function startAirRaid () {
// init score
shotsLeft = 20;
shotsHit = 0;
showGameScore();
}
public function checkForHits (event:Event) {
for(var bulletNum:int = bullets.length - 1; bulletNum >= 0; bulletNum--) {
for (var airplaneNum:int = airplanes.length - 1; airplaneNum >= 0; airplaneNum-- ) {
if ( bullets[bulletNum].hitTestObject(airplanes[airplaneNum])) {
airplanes[airplaneNum].planeHit();
bullets[bulletNum].deleteBullet();
shotsHit++;
showGameScore();
break;
}
}
if ((shotsLeft == 0) && (bullets.length == 0)) {
endGame();
}
}
}
public function fireBullet() {
if (shotsLeft <= 0) return;
var b:Bullet = new Bullet(aagun.x, aagun.y, -300);
addChild(b);
bullets.push(b);
shotsLeft--;
showGameScore();
}
public function showGameScore() {
showScore.text = String("Score: " + shotsHit);
showShots.text = String("Shots Left: " + shotsLeft);
}
}
}
Please check if Font Embedding property on both showScore and showShots text fields are true (checked) in GUI editor in your project. If either text field is not added in GUI, use the approach in this question AS3 - TextField: Embedded font to start embedding fonts, or set a proper defaultTextFormat to either text field somewhere at initialization.

5006: An ActionScript file can not have more than one externally visible definition: AND TypeError: Error #1006: hitTestObject is not a function

I have 2 issues in this code.
The first is:
5006: An ActionScript file can not have more than one externally visible definition: Sprayer, bugs
I've put multiple Actionscripts together to create this, i've seperated out the classes and am hoping to play this on a frame from a symbol.
and the second relates to:
Error #1006: hitTestObject is not a function
For this i'm trying to get the aagun/Sprayer to lose health then lives if the bugs touch it, but i'm not sure why it's saying it's not a function. Am I using the wrong words?
Thanks for your help, here's the code
package Shooter{
import flash.display.*;
import flash.events.*;
import flash.utils.getTimer;
class Sprayer extends MovieClip{
const speed:Number = 150.0;
var lastTime:int; // animation time
function Sprayer() {
// initial location of gun
this.x = 275;
this.y = 340;
// movement
addEventListener(Event.ENTER_FRAME,moveGun);
}
function moveGun(event:Event) {
// get time difference
var timePassed:int = getTimer()-lastTime;
lastTime += timePassed;
// current position
var newx = this.x;
// move to the left
if (MovieClip(parent).leftArrow) {
newx -= speed*timePassed/1000;
}
// move to the right
if (MovieClip(parent).rightArrow) {
newx += speed*timePassed/1000;
}
// check boundaries
if (newx < 10) newx = 10;
if (newx > 540) newx = 540;
// reposition
this.x = newx;
}
// remove from screen and remove events
function deleteGun() {
parent.removeChild(this);
removeEventListener(Event.ENTER_FRAME,moveGun);
}
}
}
package BigBug{
import flash.display.*;
import flash.events.*;
import flash.utils.Timer;
import flash.text.TextField;
import flash.display.MovieClip;
class bugs extends MovieClip {
var dx:Number; // speed and direction
var lastTime:int; // animation time
function bugs(side:String, speed:Number, altitude:Number) {
if (side == "left") {
this.x = -50; // start to the left
dx = speed; // fly left to right
this.scaleX = 1; // reverse
} else if (side == "right") {
this.x = -50; // start to the right
dx = -speed; // fly right to left
this.scaleX = 1; // not reverse
}
this.y = altitude; // vertical position
// choose a random plane
this.gotoAndStop(Math.floor(Math.random()*4+1));
// set up animation
addEventListener(Event.ENTER_FRAME,movePlane);
lastTime = getTimer();
}
function movePlane(event:Event) {
// get time passed
var timePassed:int = getTimer()-lastTime;
lastTime += timePassed;
// move plane
this.x += dx*timePassed/2000;
// check to see if off screen
if ((dx < 0) && (x < -50)) {
deletePlane();
} else if ((dx > 0) && (x > 350)) {
deletePlane();
}
}
}
}
package Missiles{
import flash.display.*;
import flash.events.*;
import flash.utils.Timer;
import flash.text.TextField;
import flash.display.MovieClip;
class Bullets extends MovieClip {
var dx:Number; // vertical speed
var lastTime:int;
function Bullets(x,y:Number, speed: Number) {
// set start position
this.x = x;
this.y = y;
// get speed
dx = speed;
// set up animation
lastTime = getTimer();
addEventListener(Event.ENTER_FRAME,moveBullet);
}
function moveBullet(event:Event) {
// get time passed
var timePassed:int = getTimer()-lastTime;
lastTime += timePassed;
// move bullet
this.x += dx*timePassed/1000;
// bullet past top of screen
if (this.x < 0) {
deleteBullet();
}
}
// delete bullet from stage and plane list
function deleteBullet() {
MovieClip(parent).removeBullet(this);
parent.removeChild(this);
removeEventListener(Event.ENTER_FRAME,moveBullet);
}
}
}
package MainGame{
import flash.display.*;
import flash.events.*;
import flash.utils.Timer;
import flash.text.TextField;
import flash.display.MovieClip;
import Missiles.Bullets;
import Shooter.Sprayer;
import BigBug.bugs;
public class AirRaid extends MovieClip {
private var aagun:Sprayer;
private var airplanes:Array;
private var buggood:Array;
private var bullets:Array;
public var leftArrow, rightArrow:Boolean;
private var nextGbug:Timer;
private var nextPlane:Timer;
private var shotsLeft:int;
private var shotsHit:int;
public function startAirRaid() {
// init score
shotsLeft = 20;
shotsHit = 0;
showGameScore();
// create gun
aagun = new Sprayer();
addChild(aagun);
// create object arrays
buggood = new Array();
airplanes = new Array();
bullets = new Array();
// listen for keyboard
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownFunction);
stage.addEventListener(KeyboardEvent.KEY_UP,keyUpFunction);
// look for collisions
addEventListener(Event.ENTER_FRAME,checkForHits);
// start planes flying
setNextPlane();
setNextGbug();
}
public function setNextPlane() {
nextPlane = new Timer(1000+Math.random()*1000,1);
nextPlane.addEventListener(TimerEvent.TIMER_COMPLETE,newPlane);
nextPlane.start();
}
public function newPlane(event:TimerEvent) {
// random side, speed and altitude
if (Math.random() > .5) {
var side:String = "left";
} else {
side = "right";
}
var altitude:Number = Math.random()*50+20;
var speed:Number = Math.random()*150+150;
// create plane
var p:bugs = new bugs(side,speed,altitude);
addChild(p);
airplanes.push(p);
// set time for next plane
setNextPlane();
}
public function setNextGbug() {
nextGbug = new Timer(1000+Math.random()*1000,1);
nextGbug.addEventListener(TimerEvent.TIMER_COMPLETE,newGbug);
nextGbug.start();
}
public function newGbug(event:TimerEvent) {
// random side, speed and altitude
if (Math.random() > .5) {
var side:String = "left";
} else {
side = "right";
}
var altitude:Number = Math.random()*50+20;
var speed:Number = Math.random()*150+150;
// create Gbug
var p:Good_bug = new Good_bug(side,speed,altitude);
addChild(p);
buggood.push(p);
// set time for next Gbug
setNextGbug();
}
// check for collisions
public function checkForHits(event:Event) {
for(var bulletNum:int=bullets.length-1;bulletNum>=0;bulletNum--){
for (var airplaneNum:int=airplanes.length-1;airplaneNum>=0;airplaneNum--) {
if (bullets[bulletNum].hitTestObject(airplanes[airplaneNum])) {
airplanes[airplaneNum].planeHit();
bullets[bulletNum].deleteBullet();
shotsHit++;
showGameScore();
break;
}
}
for(var bulletNum:int=bullets.length-1;bulletNum>=0;bulletNum--){
for (var Good_bugNum:int=buggood.length-1;Good_bugNum>=0;Good_bugNum--) {
if (bullets[bulletNum].hitTestObject(buggood[Good_bugNum])) {
buggood[Good_bugNum].GbugHit();
bullets[bulletNum].deleteBullet();
shotsHit--;
showGameScore();
break;
}
}
}
if ((shotsLeft == 0) && (bullets.length == 0)) {
endGame();
}
}
if ((shotsLeft == 0) && (bullets.length == 0)) {
endGame();
}
}
// key pressed
public function keyDownFunction(event:KeyboardEvent) {
if (event.keyCode == 37) {
leftArrow = true;
} else if (event.keyCode == 39) {
rightArrow = true;
} else if (event.keyCode == 32) {
fireBullet();
}
}
// key lifted
public function keyUpFunction(event:KeyboardEvent) {
if (event.keyCode == 37) {
leftArrow = false;
} else if (event.keyCode == 39) {
rightArrow = false;
}
}
// new bullet created
public function fireBullet() {
if (shotsLeft <= 0) return;
var b:Bullets = new Bullets(aagun.x,aagun.y,-300);
addChild(b);
bullets.push(b);
shotsLeft--;
showGameScore();
}
public function showGameScore() {
showScore.text = String("Score: "+shotsHit);
showShots.text = String("Shots Left: "+shotsLeft);
}
// take a plane from the array
public function removePlane(plane:bugs) {
for(var i in airplanes) {
if (airplanes[i] == plane) {
airplanes.splice(i,1);
break;
}
}
}
// take a Gbug from the array
public function removeGbug(Gbug:Good_bug) {
for(var i in buggood) {
if (buggood[i] == Gbug) {
buggood.splice(i,1);
break;
}
}
}
// take a bullet from the array
public function removeBullet(bullet:Bullets) {
for(var i in bullets) {
if (bullets[i] == bullet) {
bullets.splice(i,1);
break;
}
}
}
// game is over, clear movie clips
public function endGame() {
// remove planes
for(var i:int=airplanes.length-1;i>=0;i--) {
airplanes[i].deletePlane();
}
for(var i:int=buggood.length-1;i>=0;i--) {
buggood[i].deleteGbug();
}
airplanes = null;
buggood = null;
aagun.deleteGun();
aagun = null;
stage.removeEventListener(KeyboardEvent.KEY_DOWN,keyDownFunction);
stage.removeEventListener(KeyboardEvent.KEY_UP,keyUpFunction);
removeEventListener(Event.ENTER_FRAME,checkForHits);
nextPlane.stop();
nextPlane = null;
nextGbug.stop();
nextGbug = null;
gotoAndStop("gameover");
}
}
}
1.
5006: An ActionScript file can not have more than one externally visible definition: Sprayer, bugs
As it says exactly: you can't have more than one public definition in a file. You have to either split the code to several files or move definitions, that you don't need public, out of the package.
This would be Ok in one file:
package
{
import flash.display.MovieClip;
// public is the default access modifier
public class Test1 extends MovieClip
{
public function Test1()
{
trace("test1");
var t2:Test2 = new Test2();
var t3:Test3 = new Test3();
}
}
}
// Test2 and Test3 are defined outside of the package, otherwise it wouldn't compile.
// These definitions will only be visible to code in this file.
import flash.display.MovieClip;
class Test2 extends MovieClip
{
public function Test2()
{
trace("test2");
}
}
class Test3 extends MovieClip
{
public function Test3()
{
trace("test3");
}
}
2.
Error #1006: hitTestObject is not a function
This usually means that hitTestObject() is not defined on the object (or it's ancestors) you are trying to call it from (although there could be different kinds of errors for that).
hitTestObject() is accessed in two ways in your code: airplanes.hitTestObject() and bullets[bulletNum].hitTestObject(). You will have to debug your code to see what is actually airplanes and bullets[bulletNum], what types they are and whether they inherit hitTestObject() method. You could at least trace() them.

How to add a unique function to all the movieclips in AS3?

I would like to add a specific function to every movieclip. I've added an event listener but all the movieclips are doing the same thing.
I've noticed that I can't do it with the i variable because it's 11 could you help me find another way?
package
{
import flash.desktop.NativeApplication;
import flash.desktop.SystemIdleMode;
import flash.display.MovieClip;
import flash.display.Stage;
import flash.display.StageAlign;
import flash.display.StageOrientation;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.events.StageOrientationEvent;
import flash.system.Capabilities;
import flash.text.TextField;
import flash.ui.Keyboard;
import com.thanksmister.touchlist.renderers.TouchListItemRenderer;
import com.thanksmister.touchlist.events.ListItemEvent;
import com.thanksmister.touchlist.controls.TouchList;
[SWF( width = '480', height = '800', backgroundColor = '#000000', frameRate = '24')]
public class AS3ScrollingList extends MovieClip
{
private var touchList:TouchList;
private var textOutput:TextField;
private var stageOrientation:String = StageOrientation.DEFAULT;
public function AS3ScrollingList()
{
// needed to scale our screen
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
if(stage)
init();
else
stage.addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
stage.removeEventListener(Event.ADDED_TO_STAGE, init);
stage.addEventListener(KeyboardEvent.KEY_DOWN, handleKeyDown);
stage.addEventListener(Event.RESIZE, handleResize);
// if we have autoOrients set in permissions we add listener
if(Stage.supportsOrientationChange) {
stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGE, handleOrientationChange);
}
if(Capabilities.cpuArchitecture == "ARM") {
NativeApplication.nativeApplication.addEventListener(Event.ACTIVATE, handleActivate, false, 0, true);
NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, handleDeactivate, false, 0, true);
}
// add our list and listener
touchList = new TouchList(stage.stageWidth, stage.stageHeight);
touchList.addEventListener(ListItemEvent.ITEM_SELECTED, handlelistItemSelected);
addChild(touchList);
// Fill our list with item rendreres that extend ITouchListRenderer.
for(var i:int = 1; i < 3; i++) {
var item:TouchListItemRenderer = new TouchListItemRenderer();
item.index = i;
item.data = "This is list item " + String(i);
item.itemHeight = 120;
item.addEventListener(MouseEvent.CLICK, gotostore);
item.buttonMode = true;
touchList.addListItem(item);
}
//not nested function
function gotostore (e:MouseEvent) {
switch(e.currentTarget.name) {
case "firstMovieClip":
trace("buton1");
//first movieclip clicked
break;
case "secondMovieClip":
trace("buton2");
//second movieclip clicked
break;
//etc...
}
}
}
/**
* Handle stage orientation by calling the list resize method.
* */
private function handleOrientationChange(e:StageOrientationEvent):void
{
switch (e.afterOrientation) {
case StageOrientation.DEFAULT:
case StageOrientation.UNKNOWN:
//touchList.resize(stage.stageWidth, stage.stageHeight);
break;
case StageOrientation.ROTATED_RIGHT:
case StageOrientation.ROTATED_LEFT:
//touchList.resize(stage.stageHeight, stage.stageWidth);
break;
}
}
private function handleResize(e:Event = null):void
{
touchList.resize(stage.stageWidth, stage.stageHeight);
}
private function handleActivate(event:Event):void
{
NativeApplication.nativeApplication.systemIdleMode = SystemIdleMode.KEEP_AWAKE;
}
private function handleDeactivate(event:Event):void
{
NativeApplication.nativeApplication.exit();
}
/**
* Handle keyboard events for menu, back, and seach buttons.
* */
private function handleKeyDown(e:KeyboardEvent):void
{
if(e.keyCode == Keyboard.BACK) {
e.preventDefault();
NativeApplication.nativeApplication.exit();
} else if(e.keyCode == Keyboard.MENU){
e.preventDefault();
} else if(e.keyCode == Keyboard.SEARCH){
e.preventDefault();
}
}
/**
* Handle list item seleced.
* */
private function handlelistItemSelected(e:ListItemEvent):void
{
trace("List item selected: " + e.renderer.index);
}
}
}
Your gotostore function is a nested function which is a really bad design practice, do not use nested functions. You can check which movieclip did the user click with the e.currentTarget.name, this will give you the INSTANCE NAME of the movieclip which the user "selected".
for(var i:int = 1; i < 11; i++) {
var item:TouchListItemRenderer = new TouchListItemRenderer();
item.index = i;
item.data = "This is list item " + String(i);
item.itemHeight = 120;
item.addEventListener(MouseEvent.CLICK, gotostore);
item.buttonMode = true;
touchList.addListItem(item);
}
//not nested function
function gotostore (e:MouseEvent) {
switch(e.currentTarget.name) {
case "firstMovieClip":
//first movieclip clicked
break;
case "secondMovieClip":
//second movieclip clicked
break;
//etc...
}
}

Actionscript 3: Trouble with removing child from parent

I am coding for learning purposes and have encountered an apparently unfixable problem.
I will first introduce you to my code.
This is a function in my Main class
public function confirm_route(evt:MouseEvent):void
{
var route = new Route(this, Airport.return_ROUTE);
Airport.return_ROUTE = new Array();
}
"Airport.return_ROUTE" is simply an array and its origin is not really relevant for the problem. In the Main class I'm also declaring my background var, and putting it as a public static var. Since I need to access this background from two other classes, I don't see another option but to declare it as that, even though I think it is not ideal. I will come back to this later in the explaination.
My Route class is dynamically creating new flights on the screen, hence the name. This is based on the Airport.return_ROUTE array. I need these flights to be added as childs to the background, which was created at Main class as mentioned. This is also why I added "this" as a parameter when calling the route function.
this.myparent = pMyParent;
I use the line above to be able to refer to the main instance. Since the Route instance is no movieclip I guess this is the only way to be able to refer to this.
As earlier mentioned the Route instance dynamically creats new_flights.
new_flight = new Flight(infoarray);
myparent.background_mc.addChild(new_flight);
This obviously is purposed to add the new_flight to the background movieclip.
Let us then look at the Flight class, since this is where the problem occurs.
Due to my game concept I need the new_flight to be removed once it reaches a certain point on the background movieclip.
This function is intended to do that job:
private function deleteThis():void
{
this.parent.removeChild(this)
}
This returns TypeError: Error #1009: Cannot access a property or method of a null object reference.
I really don't understand how to solve this differently.
EDIT: As requested, I will post my Route class.
package
{
import flash.events.TimerEvent;
import flash.utils.Timer;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.EventDispatcher;
import Main;
public class Route extends Main
{
public var income:Number;
public var routePoints:Array;
private var routeTimer:Timer;
private var new_flight:Flight;
// ------------
private var myparent:Main;
public function Route(route_array:Array, pMyParent)
{
this.myparent = pMyParent;
this.routePoints = route_array;
routeTimer = new Timer(2000);// 2 second
routeTimer.addEventListener(TimerEvent.TIMER, route_function);
routeTimer.start();
}
private function route_function(event:TimerEvent):void
{
for (var counter:uint = 0; counter < routePoints.length - 1; counter ++)
{
trace("Coords: ", routePoints[counter][0],routePoints[counter][1],routePoints[counter + 1][0],routePoints[counter + 1][1]);
new_flight = new Flight(myparent, routePoints[counter][0],routePoints[counter][1],routePoints[counter + 1][0],routePoints[counter + 1][1]);
myparent.bg_image.addChild(new_flight);
var checkTimer:Timer = new Timer(15);// 1 second
checkTimer.addEventListener(TimerEvent.TIMER, check_function);
checkTimer.start();
function check_function(event:TimerEvent):void
{
if (new_flight.finished = true)
{
checkTimer.stop();
}
}
}
}
}
}
EDIT 2: Posting Flight class aswell
package
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.display.SimpleButton;
import flash.display.Stage;
import flash.events.TimerEvent;
import flash.utils.Timer;
import fl.controls.Button;
import flash.display.DisplayObject;
public class Flight extends MovieClip
{
public static var speed:uint = 1
public var finished:Boolean = false;
protected var absvector:Number;
protected var vector:Array;
protected var myTimer:Timer;
//protected var parentContainer:MovieClip;
protected var utgangspunkt_x;
protected var utgangspunkt_y;
protected var destinasjon_x;
protected var destinasjon_y;
protected var vector_x;
protected var vector_y;
private var myparent:Main
public function Flight(pMyParent, utgangspunkt_x, utgangspunkt_y, destinasjon_x, destinasjon_y):void
{
addEventListener(Event.ADDED_TO_STAGE, init);
this.myparent = pMyParent;
this.utgangspunkt_x = utgangspunkt_x;
this.utgangspunkt_y = utgangspunkt_y;
this.x = utgangspunkt_x;
this.y = utgangspunkt_y;
this.destinasjon_x = destinasjon_x + 10;
this.destinasjon_y = destinasjon_y + 10;
this.vector_x = Math.abs(this.destinasjon_x-this.utgangspunkt_x);
this.vector_y = Math.abs(this.destinasjon_y-this.utgangspunkt_y);
this.height = 20;
this.width = 20;
}
public function init(evt:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
trace(this.parent)
trace("---------------------------------------------------")
if (utgangspunkt_x < destinasjon_x)
{
this.rotation = -(Math.atan((utgangspunkt_y-destinasjon_y)/(destinasjon_x-utgangspunkt_x)))/(Math.PI)*180;
}
else
{
this.rotation = 180-(Math.atan((utgangspunkt_y-destinasjon_y)/(destinasjon_x-utgangspunkt_x)))/(Math.PI)*180;
}
absvector = Math.sqrt(Math.pow((destinasjon_x - utgangspunkt_x),2) + Math.pow((utgangspunkt_y - destinasjon_y),2));
vector = [(destinasjon_x - utgangspunkt_x) / absvector,(utgangspunkt_y - destinasjon_y) / absvector];
stage.addEventListener(Event.ENTER_FRAME, movement)
}
private function movement(evt:Event):void
{
if (this.vector_x > this.vector_y)
{
if (destinasjon_x>utgangspunkt_x)
{
if (this.x < destinasjon_x)
{
this.x += speed*vector[0];
this.y -= speed*vector[1];
}
else
{
deleteThis()
}
}
else if (destinasjon_x<utgangspunkt_x)
{
if (this.x > destinasjon_x)
{
this.x += speed*vector[0];
this.y -= speed*vector[1];
}
else
{
deleteThis()
}
}
}
else
{
if (destinasjon_y>utgangspunkt_y)
{
if (this.y < destinasjon_y)
{
this.x += speed*vector[0];
this.y -= speed*vector[1];
}
else
{
deleteThis()
}
}
else if (destinasjon_y<utgangspunkt_y)
{
if (this.y > destinasjon_y)
{
this.x += speed*vector[ 0];
this.y -= speed*vector[1];
}
else
{
deleteThis()
}
}
}
}
private function deleteThis():void
{
finished = true;
this.parent.removeChild(this)
}
}
}
I suspect your deleteThis method is called more than once. That would explain why you have [object Image] and then nothing...
Is this method called by some kind of event? If that is the case, make sure this event is not triggered more than once.

Actionscript 3: Error #1009: Cannot access a property or method of a null object reference. (parent)

This is a bit difficult to explain, but I will try.
In my Main() class, let's say I have the main movieclip (bg_image) being created, and also some lines that create an instance of another class. (look at the code below)
var route = Route(Airport.return_Route);
This route instance, is then purposed to dynamically add sprite-childs to the main background from the Main() class.
I have tried to to this with the following line:
new_flight = new Flight(coordinates)
Main.bg_image.addChild(new_flight);
This seem to work pretty fine. Let's switch focus to the new_flight instance. At the Flight class, this line trace(this.parent) would return "[object Image]".I would consider this successful so far since my intention is to add the new_flight as child to bg_image, which I guess is an "object image".
The problem, however, occurs when trying to delete the "new_flight"-instance. Obviously the ideal way of doing this would be through bg_image with removeChild.
But, when my script reaches this line: Main.bg_image.removeChild(this), my script stops and returns ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller., at that line. I have also tried replacing Main.bg_image.removeChild(this) with this.parent.removeChild(this), with no luck.
I think the solution may be to use some sort of "EventDispatching"-method. But I haven't fully understood this concept yet...
The code follows. Please help. I have no idea how to make this work...
Main class:
package
{
import flash.display.MovieClip;
import flash.utils.Dictionary;
import flash.events.MouseEvent;
import flash.display.Sprite;
import flash.text.TextField;
import fl.controls.Button;
import flash.display.DisplayObject;
import Airport;
public class Main extends Sprite
{
// ------------------------
// Buttons
public var create_new_route;
public var confirm_new_route;
// images
public static var bg_image:MovieClip;
public var airport:MovieClip;
//-------------------------------
public var routeArray:Array;
public static var airportDict:Dictionary = new Dictionary();
public static var collectedAirportArray:Array = new Array();
public function Main()
{
addEventListener(Event.ADDED_TO_STAGE, init);
create_new_route = new Button();
create_new_route.label = "Create new route";
create_new_route.x = 220;
create_new_route.y = 580;
this.addChild(create_new_route)
create_new_route.addEventListener(MouseEvent.CLICK, new_route)
confirm_new_route = new Button();
confirm_new_route.label = "Confirm route";
confirm_new_route.x = 220;
confirm_new_route.y = 610;
this.addChild(confirm_new_route)
confirm_new_route.addEventListener(MouseEvent.CLICK, confirm_route)
}
public function init(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
bg_image = new Image();
addChild(bg_image);
S_USA["x"] = 180.7;
S_USA["y"] = 149.9;
S_USA["bynavn"] = "New York";
S_Norway["x"] = 423.7;
S_Norway["y"] = 76.4;
S_Norway["bynavn"] = "Oslo";
S_South_Africa["x"] = -26;
S_South_Africa["y"] = 146;
S_South_Africa["bynavn"] = "Cape Town";
S_Brazil["x"] = 226;
S_Brazil["y"] = 431.95;
S_Brazil["bynavn"] = "Rio de Janeiro";
S_France["x"] = 459.1;
S_France["y"] = 403.9;
S_France["bynavn"] = "Paris";
S_China["x"] = 716.2;
S_China["y"] = 143.3;
S_China["bynavn"] = "Beijing";
S_Australia["x"] = 809.35;
S_Australia["y"] = 414.95;
S_Australia["bynavn"] = "Sydney";
// ----------------------------------------------------
airportDict["USA"] = S_USA;
airportDict["Norway"] = S_Norway;
airportDict["South Africa"] = S_South_Africa;
airportDict["Brazil"] = S_Brazil;
airportDict["France"] = S_France;
airportDict["China"] = S_China;
airportDict["Australia"] = S_Australia;
for (var k:Object in airportDict)
{
var value = airportDict[k];
var key = k;
startList.addItem({label:key, data:key});
sluttList.addItem({label:key, data:key});
var airport:Airport = new Airport(key,airportDict[key]["bynavn"]);
airport.koordinater(airportDict[key]["x"], airportDict[key]["y"]);
collectedAirportArray.push(airport);
airport.scaleY = minScale;
airport.scaleX = minScale;
bg_image.addChild(airport);
}
// --------------------------------------------
// --------------------------------------------
// -----------------------------------------------
}
private function new_route(evt:MouseEvent):void
{
Airport.ROUTING = true;
}
public function confirm_route(evt:MouseEvent):void
{
Airport.ROUTING = false;
trace(Airport.return_ROUTE);
var route = new Route(Airport.return_ROUTE); // ***
this.addChild(route); // **
Airport.return_ROUTE = new Array();
}
}
}
Airport class:
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.display.SimpleButton;
import flash.display.Stage;
import flash.text.TextField;
import flash.text.TextFormat;
import flashx.textLayout.formats.Float;
public class Airport extends MovieClip
{
public static var ROUTING = false;
public static var return_ROUTE:Array = new Array();
//-----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
protected var navn:String;
protected var bynavn:String;
// ----------------------------------------------------------------------------
public function Airport(navninput, bynavninput)
{
this.bynavn = bynavninput;
this.navn = navninput;
this.addEventListener(MouseEvent.CLICK, clickHandler);
this.addEventListener(MouseEvent.MOUSE_OVER, hoverHandler);
}
public function zoomHandler():void
{
trace("testing complete");
}
public function koordinater(xc, yc)
{
this.x = (xc);
this.y = (yc);
}
private function clickHandler(evt:MouseEvent):void
{
trace(ROUTING)
if (ROUTING == true)
{
return_ROUTE.push([this.x, this.y])
}
}
private function hoverHandler(evt:MouseEvent):void
{
if (ROUTING == true)
{
this.alpha = 60;
this.width = 2*this.width;
this.height = 2*this.height;
this.addEventListener(MouseEvent.MOUSE_OUT, awayHandler);
}
}
private function awayHandler(evt:MouseEvent):void
{
this.width = 13;
this.height = 13;
}
}
}
Route class
package
{
import flash.events.TimerEvent;
import flash.utils.Timer;
import flash.display.MovieClip;
import Main;
public class Route
{
public var income:Number;
public var routePoints:Array;
private var routeTimer:Timer;
private var new_flight:Flight;
public function Route(route_array:Array)
{
this.routePoints = route_array
routeTimer = new Timer(2000);// 2 second
routeTimer.addEventListener(TimerEvent.TIMER, route_function);
routeTimer.start();
}
private function route_function(event:TimerEvent):void
{
for (var counter:uint = 0; counter < routePoints.length - 1; counter ++)
{
trace("Coords: ", routePoints[counter][0],routePoints[counter][1],routePoints[counter + 1][0],routePoints[counter + 1][1]);
new_flight = new Flight(routePoints[counter][0],routePoints[counter][1],routePoints[counter + 1][0],routePoints[counter + 1][1]);
Main.bg_image.addChild(new_flight);
var checkTimer:Timer = new Timer(15);// 1 second
checkTimer.addEventListener(TimerEvent.TIMER, check_function);
checkTimer.start();
function check_function(event:TimerEvent):void
{
if (new_flight.finished = true)
{
checkTimer.stop();
}
}
}
}
}
}
Flight class
package
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.display.SimpleButton;
import flash.display.Stage;
import flash.events.TimerEvent;
import flash.utils.Timer;
import fl.controls.Button;
import flash.display.DisplayObject;
public class Flight extends MovieClip
{
public static var speed:uint = 1
public var finished:Boolean = false;
protected var absvector:Number;
protected var vector:Array;
protected var myTimer:Timer;
//protected var parentContainer:MovieClip;
protected var utgangspunkt_x;
protected var utgangspunkt_y;
protected var destinasjon_x;
protected var destinasjon_y;
protected var vector_x;
protected var vector_y;
public function Flight(utgangspunkt_x, utgangspunkt_y, destinasjon_x, destinasjon_y):void
{
addEventListener(Event.ADDED_TO_STAGE, init);
this.utgangspunkt_x = utgangspunkt_x;
this.utgangspunkt_y = utgangspunkt_y;
this.x = utgangspunkt_x;
this.y = utgangspunkt_y;
this.destinasjon_x = destinasjon_x + 10;
this.destinasjon_y = destinasjon_y + 10;
this.vector_x = Math.abs(this.destinasjon_x-this.utgangspunkt_x);
this.vector_y = Math.abs(this.destinasjon_y-this.utgangspunkt_y);
this.height = 20;
this.width = 20;
}
public function init(evt:Event):void
{
trace(this.parent)
if (utgangspunkt_x < destinasjon_x)
{
this.rotation = -(Math.atan((utgangspunkt_y-destinasjon_y)/(destinasjon_x-utgangspunkt_x)))/(Math.PI)*180;
}
else
{
this.rotation = 180-(Math.atan((utgangspunkt_y-destinasjon_y)/(destinasjon_x-utgangspunkt_x)))/(Math.PI)*180;
}
absvector = Math.sqrt(Math.pow((destinasjon_x - utgangspunkt_x),2) + Math.pow((utgangspunkt_y - destinasjon_y),2));
vector = [(destinasjon_x - utgangspunkt_x) / absvector,(utgangspunkt_y - destinasjon_y) / absvector];
stage.addEventListener(Event.ENTER_FRAME, movement)
}
private function movement(evt:Event):void
{
if (this.vector_x > this.vector_y)
{
if (destinasjon_x>utgangspunkt_x)
{
if (this.x < destinasjon_x)
{
this.x += speed*vector[0];
this.y -= speed*vector[1];
}
else
{
finished = true
Main.bg_image.removeChild(this)
}
}
else if (destinasjon_x<utgangspunkt_x)
{
if (this.x > destinasjon_x)
{
this.x += speed*vector[0];
this.y -= speed*vector[1];
}
else
{
finished = true
Main.bg_image.removeChild(this)
}
}
}
else
{
if (destinasjon_y>utgangspunkt_y)
{
if (this.y < destinasjon_y)
{
this.x += speed*vector[0];
this.y -= speed*vector[1];
}
else
{
finished = true
Main.bg_image.removeChild(this)
}
}
else if (destinasjon_y<utgangspunkt_y)
{
if (this.y > destinasjon_y)
{
this.x += speed*vector[0];
this.y -= speed*vector[1];
}
else
{
finished = true
Main.bg_image.removeChild(this)
}
}
}
}
}
}
I am confused what your asking and what your trying to do, but I will give it my best shot.
this.addchild(new_class2)
This line adds your object to the display list. Adding another object to the display is done the same way you added the first. Flash adds objects in the sequentially, so the objects you want in the back need to be declared and added first.
This is probably what you want:
var new_flight:Flight = new Flight();
this.addchild(new_flight);
Also you forgot your type declaration for Class2:
var new_class2:Class2 = new Class2();
Try replacing:
Main.bg_image.addChild(new_flight);
with
Main(this.parent).bg_image.addChild(new_flight);
... assuming the 'main' class you refer to is infact named 'Main' and it has a named instance called 'bg_image'
Please leave a comment if it works, I can explain in more detail what is actually happening here.
Why you are adding new_flight to bg_image?
Anyway, if you are adding new_flight to bg_image, then you have bg_image already declared as public static (which I do not recommend),
Try removing the flight in your Flight class it-self like so,
Main.bg_image.removeChild(this) // *
You can also use Event Dispatching instead of declaring bg_image as static.
If you want to remove flight then dispatch event from Flight class to Route class and there you again dispatch event to main class.
And, inside main class capture this event and access the MovieClip.