Remove Child of Root actionscript3 - actionscript-3

I've created 4 instances of Notes and I have them moving to the right until their x value is greater than 100. Once they're there, how do I remove them? I ran a trace statement and confirmed that the parent of these instances is root (root1 to be exact). If I type
root.removeChild(this);
I get an error saying "call to a possibly undefined method removeChild"
If I type
removeChild(this);
I get an error saying "The supplied DisplayObject must be a child of the caller". Full code is posted below. The last line before the }'s at the end is the problem line. Thanks so much for the help!
package
{
import flash.display.Bitmap;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.utils.getDefinitionByName;
import flash.utils.Timer;
import flash.events.TimerEvent;
[Frame(factoryClass="Preloader")]
public class Main extends Sprite
{
private var speed:int = 8;
[Embed(source="../lib/Dodgethis.jpg")]
public var Notes:Class;
public var numnotes:Number;
public var timer:Timer = new Timer(500, 1)
public var rootContainer:DisplayObjectContainer = DisplayObjectContainer (root);
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
timer.start();
timer.addEventListener(TimerEvent.TIMER, testevent);
}
private function testevent(e:Event = null):void {
trace("testevent has run");
appear();
}
private function appear() {
var arr1:Array = new Array;
numnotes = 4;
for (var i = 0; i < numnotes; i++)
{
trace (i);
var nbm:Bitmap = new Notes;
stage.addChild(nbm);
nbm.y = i * 50;
arr1.push(nbm);
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
}
private function loop (e:Event):void {
this.x += speed;
trace(this.x) ;
if (this.x > 100) {
removeEventListener(Event.ENTER_FRAME, loop);
trace ("Event listener was removed");
//removeChild(this);
//rootContainer.removeChild (nbm);
/*trace(this.contains)
trace(this.name)
trace(this)*/
trace(this.parent.name); //root
removeChild(this);
}
}
}
}

Try using this in the loop function
e.target.parent.removeChild(e.target);
//or
stage.removeChild(e.target);

You're adding the notes to stage. So you need to remove them from stage.
stage.removeChild( note );
You can only remove a child from its parent, not from any other container. So calling removeChild on a different container will always fail

Related

AS3 - Space Shooter Enemy Shots

I'm very new to AS3 and programming in general and I've been developing a space shooter game in AS3 and have run into trouble regarding the enemy shots. The enemies fly vertically down from the top of the screen and should fire two shots (one going left and one going right) once their y coordinates equal that of the player. This works fine, except after anything from 30 seconds to 2 minutes, the following errors occur.
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at EnemyShip2/fireWeapon()[G:\Games Related\1942\src\EnemyShip2.as:78]
at EnemyShip2/loop2()[G:\Games Related\1942\src\EnemyShip2.as:65]
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at EnemyShot/removeSelf()[G:\Games Related\1942\src\EnemyShot.as:43]
at EnemyShot/loop()[G:\Games Related\1942\src\EnemyShot.as:36]
Below is the relevant code, for the enemy ship class as well as the enemy shot class.
Enemy Ship
package
{
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.Stage;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.Timer;
/**
* ...
* #author D Nelson
*/
[Embed(source = "../assets/enemyship2.png")]
//This enemy moves relatively slowly and fires horizontal shots
public class EnemyShip2 extends Bitmap
{
private var vy:Number = 3;
//private var ay:Number = .2;
private var target:HeroShip;
private var enemyShip2:EnemyShip2;
private var enemyfireTimer:Timer;
private var enemycanFire:Boolean = true;
public function EnemyShip2(target:HeroShip):void
{
this.target = target;
scaleX = 0.3;
scaleY = 0.3;
x = Math.floor(Math.random() * 550);
y = -105;
addEventListener(Event.ENTER_FRAME, loop2, false, 0, true);
enemyfireTimer = new Timer(1000, 1);
enemyfireTimer.addEventListener(TimerEvent.TIMER, handleenemyfireTimer, false, 0, true);
}
private function handleenemyfireTimer(e:TimerEvent) : void
{
//the timer runs, so a shot can be fired again
enemycanFire = true;
}
private function removeSelf2():void
{
removeEventListener(Event.ENTER_FRAME, loop2);
if (stage.contains(this))
{
stage.removeChild(this);
}
}
private function loop2 (e:Event):void
{
//vy += ay;
y += vy;
if (y > stage.stageHeight)
{
removeSelf2();
}
if (y >= target.y && (enemycanFire))
{
fireWeapon();
enemycanFire = false;
enemyfireTimer.start();
}
if (this.x > 540 || this.x < 10)
{
removeSelf2();
}
}
private function fireWeapon():void
{
stage.addChild(new EnemyShot(target, x, y, -4));
stage.addChild(new EnemyShot(target, x, y, +4));
}
}
}
Enemy Shot
package
{
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.events.Event;
import flash.display.Stage;
/**
* ...
* #author D Nelson
*/
[Embed(source="../assets/enemyshot.png")]
public class EnemyShot extends Bitmap
{
private var speed:Number;
private var target:HeroShip;
private var vx:Number;
public function EnemyShot(target:HeroShip, x:Number, y:Number, vx:Number)
{
this.target = target;
this.x = x;
this.y = y;
this.vx = vx;
scaleX = 0.3;
scaleY = 0.3;
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
private function loop(e:Event) : void
{
x += vx;
if (x >= 600 || x <= -50)
{
removeSelf();
}
}
private function removeSelf():void
{
removeEventListener(Event.ENTER_FRAME, loop);
if (stage.contains(this))
{
stage.removeChild(this);
}
}
}
}
Also provided is the main class, in case that is of any help.
package
{
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.display.DisplayObject;
import flash.display.Stage;
import flash.events.*;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.KeyboardEvent;
import flash.events.TimerEvent;
import flash.ui.Mouse;
import flash.utils.*;
import flash.utils.ByteArray;
import flash.utils.Timer;
import flash.text.*;
import flash.media.Sound;
import flash.media.SoundChannel;
/**
* ...
* #author D Nelson
*/
public class Main extends MovieClip
{
[Embed(source = "snd/gamemusic2.mp3")]
private var MySound : Class;
private var mainsound : Sound;
private var shootsound: Sound = new ShootSound;
private var sndChannel:SoundChannel = new SoundChannel;
public var heroShip:HeroShip;
public var enemyShip1:EnemyShip1
public var enemyShip2:EnemyShip2
public var enemyShip3:EnemyShip3
public var enemyShip4:EnemyShip4
public var bossShip: BossShip
public var enemyShot: EnemyShot;
public var playerShot: PlayerShot;
private var background1:Background1;
private var background2:Background2;
public static const scrollspeed:Number = 2;
public var playerShotArray:Array = new Array()
public var enemyShotArray:Array = new Array()
public var enemies1Array:Array = new Array()
public var enemies2Array:Array = new Array()
private var fireTimer:Timer; //this creates a delay between each shot
private var canFire:Boolean = true; //this checks if a shot can be fired
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
mainsound = (new MySound) as Sound;
shootsound = (new ShootSound) as Sound;
mainsound.play();
background1 = new Background1();
background2 = new Background2();
//setting the backgrounds one below another
background1.y = 0;
background2.y = background1.height;
//add background at the lowest depth level
stage.addChildAt(background1,0);
stage.addChildAt(background2, 0);
//sets up the timer and its listener
fireTimer = new Timer(250, 1);
fireTimer.addEventListener(TimerEvent.TIMER, handlefireTimer, false, 0, true);
stage.addEventListener(KeyboardEvent.KEY_DOWN, handleCharacterShoot);
//background scrolling effect
stage.addEventListener(Event.ENTER_FRAME, backgroundScroll);
//loop for enemy1 variety
stage.addEventListener(Event.ENTER_FRAME, loop1, false, 0, true);
//loop for enemy2 variety
stage.addEventListener(Event.ENTER_FRAME, loop2, false, 0, true);
//speed of player shots
setInterval(playerShootMovement, 10);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
//entry point
heroShip = new HeroShip();
stage.addChild(heroShip);
//test values for enemies
/*enemyShip1 = new EnemyShip1();
stage.addChildAt(enemyShip1, 2);
enemyShip1.y = stage.stageWidth * 0.3;
enemyShip1.x = 300;
enemyShip2 = new EnemyShip2();
stage.addChildAt(enemyShip2, 2);
enemyShip2.y = stage.stageWidth * 0.3;
enemyShip2.x = 200;
enemyShip3 = new EnemyShip3();
stage.addChildAt(enemyShip3, 2);
enemyShip3.y = stage.stageWidth * 0.3;
enemyShip3.x = 100;
enemyShip4 = new EnemyShip4();
stage.addChildAt(enemyShip4, 2);
enemyShip4.y = stage.stageWidth * 0.3;
enemyShip4.x = 400;
bossShip = new BossShip();
stage.addChildAt(bossShip, 1);
bossShip.y = 10;
bossShip.x = 130;*/
Mouse.hide();
}
private function handlefireTimer(e:TimerEvent) : void
{
//the timer runs, so a shot can be fired again
canFire = true;
}
public function playerShoot():void
{
//if canFire is true, allow a shot to be fired, then set canFire to false and start the timer again
//else, do nothing
if (canFire)
{
//Add new line to the array
playerShotArray.push(playerShot = new PlayerShot);
//Spawn missile in ship
playerShot.y = heroShip.y;
playerShot.x = heroShip.x+11;
addChild(playerShot);
canFire = false;
fireTimer.start();
sndChannel = shootsound.play();
}
}
public function playerShootMovement():void
{
//code adapted from the Pie Throw tutorial
for (var i:int = 0; i < playerShotArray.length; i++)
{
playerShotArray[i].y -= 10;
if (playerShotArray[i].y == 850)
{
playerShotArray.shift();
}
}
}
public function handleCharacterShoot(e:KeyboardEvent):void
{
/**
* SpaceBar = 32
*/
if (e.keyCode == 32)
{
playerShoot();
}
}
public function backgroundScroll (evt:Event):void
{
background1.y += scrollspeed;
background2.y += scrollspeed;
if (background1.y >= stage.stageHeight)
{
//the background is below the visible stage area, put it above the other background
background1.y = background2.y - background2.height;
}
else if (background2.y >= stage.stageHeight)
{
background2.y = background1.y - background2.height;
}
}
//EnemyShip 1 spawning
private function loop1(e:Event):void
{
//generates probability for the ship to spawn (lower number to increase odds, decrease it to decrease odds)
if (Math.floor(Math.random() * 55) == 5)
{
var enemyShip1:EnemyShip1 = new EnemyShip1(heroShip);
enemyShip1.addEventListener(Event.REMOVED_FROM_STAGE, removeEnemy1, false, 0, true);
enemies1Array.push(enemyShip1);
stage.addChild(enemyShip1);
}
}
private function removeEnemy1(e:Event):void
{
//removes the enemy that most recently left the screen from the array
enemies1Array.splice(enemies1Array.indexOf(e.currentTarget), 1);
}
//EnemyShip2 spawning
private function loop2(e:Event):void
{
if (Math.floor(Math.random() * 40) == 5)
{
var enemyShip2:EnemyShip2 = new EnemyShip2(heroShip);
enemyShip2.addEventListener(Event.REMOVED_FROM_STAGE, removeEnemy2, false, 0, true);
enemies2Array.push(enemyShip2);
stage.addChild(enemyShip2);
}
}
private function removeEnemy2(e:Event):void
{
enemies2Array.splice(enemies2Array.indexOf(e.currentTarget), 1);
}
}
}
Initially I thought it was to do with enemies firing shots while being too far to either side of the screen, but that doesn't seem to be the case. Any help would be greatly appreciated.
You need to make sure you remove the ENTER_FRAME listeners whenever you remove the object.
Actually, my advise is to not add ENTER_FRAME handlers throughout your game objects. This gets hard to manage and leads to bugs like you've encountered. Instead, add a single ENTER_FRAME as your core game loop, and update objects by calling an update() function on a list of game objects you maintain in your main game class. When you remove an object you simply won't call update() anymore. It also becomes easy to pause the game by just removing the ENTER_FRAME handler.
For example, here's a pattern I like to use for simple games:
interface IGameObject {
update():void;
}
class Enemy extends Sprite implements IGameObject {
public update():void {
// move, fire, etc
}
}
class Player extends Sprite implements IGameObject {
public update():void {
// move, fire, etc
}
}
class Bullet extends Bitmap implements IGameObject {
public update():void {
// move, collide, etc
}
}
class Main extends Sprite {
private objects:Vector.<IGameObject> = new <IGameObject>[];
public start():void {
addEventListener(Event.ENTER_FRAME, update);
}
public stopGame():void {
removeEventListener(Event.ENTER_FRAME, update);
}
private function update(e:Event):void {
for each (var object:IGameObject in objects) {
object.update();
}
}
public addObject(object:IGameObject):void {
objects.push(object);
addChild(object as DisplayObject);
}
public removeObject(object:IGameObject):void {
objects.splice(objects.indexOf(object), 1);
removeChild(object as DisplayObject);
}
}
Add and remove objects using addObject and removeObject. You can invoke them through a reference to Main or through event handlers you dispatch from your objects.

Adding EventListener to Sprites in other classes does not work in AS3

I have my main class where I add EventLisitener to Sprites in other classes Like so:
public function Main() {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
addChild(Menu.menuBackground);
addChild(Menu.startButton);
//Adds event Listener to Menu's Sprite startButton.
Menu.startButton.addEventListener(MouseEvent.CLICK, startGame);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
}
This all works Fine and Dandy but later I try to do it again, the same way. But, clicking on the sprites does nothing. Here is the full Main Class code. Along with the code for the other three Sprite classes.
Full Main:
package {
//Other Files
import Menu;
import CrossHair;
import Birds;
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.ui.Mouse;
public class Main extends Sprite {
//Game values
public static var gameWidth:int = 750;
public static var gameHeight:int = 750;
[Embed (source = "lib/background.png")]
public var backgroundClass:Class;
public var background:Bitmap = new backgroundClass();
public function Main() {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
addChild(Menu.menuBackground);
addChild(Menu.startButton);
Menu.startButton.addEventListener(MouseEvent.CLICK, startGame);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
}
//Function starts game
public function startGame(Evt:Event):void {
Mouse.hide(); //Hides Mouse
removeChild(Menu.startButton); //Get rid of startButton
Menu.startButton.removeEventListener(MouseEvent.CLICK, startGame);
reRender();
//Add eventListiners
addEventListener(Event.ENTER_FRAME, update);
Birds.bird.addEventListener(MouseEvent.CLICK, Birds.shot);
EnterShopButton.shopButton.addEventListener(MouseEvent.CLICK, enterShop);
}
public function reRender():void {
addChild(background); //Add background
addChild(Birds.bird); //Add birds.
addChild(EnterShopButton.shopButton); //Add UpgradeMenuButton
addChild(CrossHair.crossHair); //Add crosshair
}
public function enterShop():void {
stage.removeChildren(); //Removes all children from stage.
}
public function update(evt:Event):void {
Birds.update();
CrossHair.crossHair.x = mouseX - (CrossHair.crossHairImg.width / 2);
CrossHair.crossHair.y = mouseY - (CrossHair.crossHairImg.height / 2);
}
}
}
Event Lisitners:
package {
//Other files
import flash.events.Event;
import Main;
import flash.display.Sprite;
import flash.display.Bitmap;
public class Menu extends Sprite {
//create menbu background Bitmap
[Embed (source = "lib/menubackground.png")]
public static var menuBackgroundClass:Class;
public static var menuBackground:Bitmap = new menuBackgroundClass();
//create startButton Bitmap
[Embed (source = "lib/menustartbutton.png")]
public static var startButtonClass:Class;
public static var startButtonImg:Bitmap = new startButtonClass();
public static var startButton:Sprite = new Sprite();
//Set startButton's values
startButton.addChild(startButtonImg);
startButton.x = (Main.gameWidth / 2) - (startButtonImg.width / 2);
startButton.y = (Main.gameHeight / 2) - (startButtonImg.height / 2);
}
}
package {
//Other files
import Main;
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.events.MouseEvent;
public class Birds extends Sprite {
public static var xSpeed:int = 10;
public static var ySpeed:int = 10;
public static var dead:Boolean = false;
//Create bird Sprite
[Embed (source = "lib/bird.png")]
public static var birdClass:Class;
[Embed (source = "lib/birdead.png")]
public static var deadBirdClass:Class;
public static var birdImg:Bitmap = new birdClass();
public static var deadBirdImg:Bitmap = new deadBirdClass();
public static var bird:Sprite = new Sprite();
//Sets Sprite's values
bird.addChild(birdImg);
bird.buttonMode = true;
bird.x = 0;
bird.y = 0;
public static function update():void {
bird.x += Math.random() * xSpeed;
bird.y += Math.random() * ySpeed;
if (!dead) {
if (bird.x >= (Main.gameWidth - birdImg.width) || bird.x <= 0) {
xSpeed = xSpeed * -1;
}
if (bird.y >= (Main.gameHeight - birdImg.height) || bird.y <= 0) {
ySpeed = ySpeed * -1;
}
} else {
if (bird.y > (Main.gameHeight - deadBirdImg.height)) {
resetBird();
}
}
}
public static function shot(evt:MouseEvent):void {
if (!dead) {
bird.removeChild(birdImg);
bird.addChild(deadBirdImg);
dead = true;
xSpeed = 0;
ySpeed = 50;
}
}
public static function resetBird():void {
bird.removeChild(deadBirdImg);
bird.addChild(birdImg);
dead = false;
bird.x = 0
bird.y = 0;
xSpeed = 10;
ySpeed = 10;
}
}
}
package {
//Other Files
import Main;
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.events.Event;
import flash.events.MouseEvent;
public class EnterShopButton extends Sprite{
//Create crossHair
[Embed (source = "lib/shopbutton.png")]
public static var shopButtonClass:Class;
public static var shopButtonImg:Bitmap = new shopButtonClass();
public static var shopButton:Sprite = new Sprite();
//Set CrossHair's values
shopButton.addChild(shopButtonImg);
shopButton.buttonMode = true;
shopButton.x = Main.gameWidth - shopButtonImg.width;
shopButton.y = Main.gameHeight - shopButtonImg.height;
}
}
Same problem, same answer. Your previous question was answered the same way but you still persist on doing the exact same thing and getting into the exact same problem.
Stop trying to run code in static scope! addChild can't work in that scope and any other type of code.
Not sure why I was voted down. There's not much to answer here since the same problem with the same user was answered in another post.
This is really not difficult, user wants to run code at class definition scope. At class definition scope you can instantiate variable yes but that's all you can do. User wants to run code and logic at that scope and this is just completely ignored by the compiler. This was already pointed out to him in his previous question and he was even given the advice to stop trying to run code at that scope to avoid further problem. This is really simple to understand:
[Embed (source = "lib/menubackground.png")]
public static var menuBackgroundClass:Class;
public static var menuBackground:Bitmap = new menuBackgroundClass();
//instantiation is allowed at that scope and will work
//create startButton Bitmap
[Embed (source = "lib/menustartbutton.png")]
public static var startButtonClass:Class;
public static var startButtonImg:Bitmap = new startButtonClass();
//instantiation is allowed at that scope and will work
public static var startButton:Sprite = new Sprite();
//instantiation is allowed at that scope and will work
//COMPILER WILL IGNORE AT THAT SCOPE ANY CODE THAT IS NOT INSTANTIATION
//SO ALL FOLLOWING LINES ARE IGNORED AND PRODUCE NO RESULT
//EVEN TRACING WOULD NOT WORK HERE
// (Main.gameWidth / 2) WILL NOT BE CALCULATED AND DOES NOT PRODUCE ANY VALUE
// startButton.x WILL NOT BE SET AND WILL STAY AT DEFAULT VALUE 0
// FINALLY startButton WILL NOT addChild ANYTHING.
//ANY FORM OF CODE LOGIC IS IGNORED AT THAT SCOPE AND WILL NEVER PRODUCE ANY RESULT
startButton.addChild(startButtonImg);
startButton.x = (Main.gameWidth / 2) - (startButtonImg.width / 2);
startButton.y = (Main.gameHeight / 2) - (startButtonImg.height / 2);

How to define that a child should only appear in one scene?

We are making an space impact game. Here are 3 of our classes. Our problem is that when we create our InimigoNoite, they appear all over the game(menus, other levels, etc), instead of only appearing in the Scene that we want. How should we restrict the child to only appear in the CenárioCidade?
We've tried to use gotoandPlay, addChildAt, and also tried to create the Inimigo not in the Main class, but in the Inimigo class itself, but it doesnt appear at all. Please can someone help us? Thank you very much!
KEY.as
package {
import flash.display.Stage;
import flash.events.Event;
import flash.events.KeyboardEvent;
public class Key {
private static var initialized:Boolean = false;
private static var keysDown:Object = new Object();
public static function initialize(stage:Stage) {
if (!initialized) {
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
stage.addEventListener(Event.DEACTIVATE, clearKeys);
initialized = true;
}
}
public static function isDown(keyCode:uint):Boolean
{
return Boolean(keyCode in keysDown);
}
private static function keyPressed(event:KeyboardEvent):void {
keysDown[event.keyCode] = true;
}
private static function keyReleased(event:KeyboardEvent):void {
if (event.keyCode in keysDown) {
delete keysDown[event.keyCode];
}
}
private static function clearKeys(event:Event):void {
keysDown = new Object();
}
}
}
INIMIGO NOITE.as
package{
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.Timer;
public class InimigoNoite extends MovieClip{
var speed:Number;
static var list:Array = new Array();
var balaTimer: Timer;
function InimigoNoite(){
list.push(this);
this.x = 1160;
this.y = 150 + (450-150) * Math.random();
speed = Math.random()*5 + 5;
addEventListener("enterFrame", enterFrame);
var intervalo: Number = Math.random()*500 + 1000;
balaTimer = new Timer(intervalo);
balaTimer.addEventListener("timer", bala);
balaTimer.start();
}
function enterFrame (e:Event){
this.x -= speed;
if(this.x < -100){
matar();
return;
}
if(this.hitTestObject(SpaceImpact.navecnoite)){
matar();
}
}
function matar(){
var explosao = new ExplosaoNoite();
stage.addChild(explosao);
explosao.x = this.x;
explosao.y = this.y;
balaTimer.stop();
balaTimer.removeEventListener("timer",bala);
removeEventListener("enterFrame", enterFrame);
stage.removeChild(this);
for(var i in list){
if(list[i] == this){
delete list[i];
}
}
}
function bala(e:Event){
var b = new BalaInimigo();
b.x = this.x -50;
b.y = this.y;
stage.addChild(b);
}
}
}
MAIN.as
package{
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.Timer;
public class SpaceImpact extends MovieClip{
static var navecnoite:MovieClip;
var inimigoNoiteTimer:Timer;
function SpaceImpact(){
Key.initialize(stage);
inimigoNoiteTimer = new Timer(8000);
inimigoNoiteTimer.addEventListener("timer", criaInimigo);
inimigoNoiteTimer.start();
}
function criaInimigo(e:Event){
var inimigo = new InimigoNoite();
stage.addChild(inimigo);
addChildAt(inimigo, 3);
}
}
}
You never stop the timer. So your inimigo is created and added every 8seconds.
Stop the timer in criaInimigo and/or use the timerComplete Event
function SpaceImpact(){
Key.initialize(stage);
inimigoNoiteTimer = new Timer(8000,1);
inimigoNoiteTimer.addEventListener(TimerEvent.TIMER_COMPLETE, criaInimigo);
inimigoNoiteTimer.start();
}
function criaInimigo(e:Event){
//inimigoNoiteTimer.stop();//only needed if you use the 'timer'-Event
var inimigo = new InimigoNoite();
stage.addChild(inimigo);
addChildAt(inimigo, 3);
}
Right when you application starts, you are creating a new InimigoNoite every 8 seconds. Since you are adding them to the stage, they will appear over top anything you have on your timeline.
The issue (besides creating them when the application starts and never stopping your timer), is that when you through code use addChild, that child will stay on the screen until it's explicitly removed via removeChild (or one of it's parents are - but since the parent is stage that isn't going to happen).
I see that your have a hit test in the InimigoNoite class that can potentially remove it, but I don't see anywhere else where you remove it (so if the hit test never happens, it will never be removed from the stage regardless of scene).
It seem though that the solution to your problem is more advice on how to architect your application.
Don't use scenes.
Your best bet is to create a class file for each distinct state of your game. So something like this as a basic example:
Main Menu State
Game Play State(either 1 game state that encompasses all levels, or one state for each level - or both - depending on how much functionality changes between levels)
Game Over State
Make your game state class files extend Sprite or MovieClip, and if you want you can even create a new MovieClip in flash pro and attach the class to that (thereby being able to drop visual assets on the timeline).
So then your Main class would just be in charge of managing states (and any anything else that is global to the application)
package{
import flash.display.MovieClip;
import flash.events.Event;
public class SpaceImpact extends MovieClip {
private var menu:Menu; //Assumes you have a Menu.as class file
private var game:MainGame; //MainGame.as file
private var gameOver:GameOver; //GameOver.as file
public function SpaceImpact(){
Key.initialize(stage);
goMenu();
}
public function goMenu(e:Event = null):void {
removeAll();
menu = new Menu();
addChild(menu);
menu.addEventListener(Event.COMPLETE, startGame,false,0,true);
}
private function removeMenu():void {
if(menu){
if(menu.parent) removeChild(menu); //remove it from the screen
menu = null;
}
}
public function startGame(e:Event = null):void {
removeAll();
game = new MainGame();
addChild(game);
game.addEventListener(Event.COMPLETE, gameOver,false,0,true);
}
private function removeGame():void {
if(game){
if(game.parent) removeChild(game); //remove it from the screen
game = null;
}
}
public function gameOver(e:Event = null):void {
removeAll();
gameOver = new GameOver();
addChild(gameOver);
gameOver.addEventListener(Event.COMPLETE, goMenu,false,0,true);
}
private function removeGameOver():void {
if(gameOver){
if(gameOver.parent) removeChild(gameOver); //remove it from the screen
gameOver = null;
}
}
private function removeAll():void {
removeGameOver();
removeMenu();
removeGame();
}
}
}
then, your game state for example:
MainGame.as
package{
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.Timer;
public class MainGame extends MovieClip {
private var inimigoNoiteTimer:Timer;
public function MainGame() {
this.addEventListener(Event.ADDED_TO_STAGE, addedToStage, false, 0, true); //don't do anything until this object has been added to the screen
}
private function addedToStage(e:Event):void {
this.removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
//start spawning
inimigoNoiteTimer = new Timer(8000);
inimigoNoiteTimer.addEventListener("timer", criaInimigo);
inimigoNoiteTimer.start();
}
function criaInimigo(e:Event){
var inimigo = new InimigoNoite();
addChild(inimigo);
}
//when whatever happens that makes your game finished
function gameComplete():void {
dispatchEvent(new Event(addEventListener.COMPLETE));
}
}
}

expecting colon before rightparen and expecting identifier before if

Another probably dumb question.
I followed a tutorial (popping game by Richard Parnaby-King).
i got this anoying errors that i cant seems to fix.
the main.as (called test1):
package
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.utils.Timer;
[SWF(width='800',height='600',backgroundColor='#FFFFFF',frameRate='25')]
public class Test1 extends MovieClip
{
var icon:FacebookIcon = new FacebookIcon();
var background:BG = new BG();
private var timer:Timer = new Timer(5000,-1);
private var bubbles:Array = [];
private var score:int;
private var textBox:TextField = new TextField;
private var textFormat:TextFormat = new TextFormat(null, 30);
public function Test1(); void
{
if(stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
//add start button
icon.addChild(new StartButton());
icon.addEventListener(MouseEvent.CLICK, startGame);
icon.buttonMode = true;
icon.x = (stage.stageWidth / 2) - (icon.width / 2);
icon.y = (stage.stageHeight / 2) - (icon.height / 2);
addChild(icon);
textBox.defaultTextFormat = textFormat;
private function startGame(e:MouseEvent):void {
icon.removeEventListener(MouseEvent.CLICK, startGame);
removeChild(icon);
removeChild(background);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, createBubble);
timer.start();
createBubble();
score = 0;
}
I get the errors
1084: Syntax error: expecting identifier before if
and
-1084: Syntax error: expecting colon before rightparen
right where the
if(stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
What Im doing wrong? tried everything.
thanks a lot
You've got a semi-colon before the return type on your constructor. It should be a colon:
public function Test1(): void
{
if(stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}

AS3 - Error #2025: The supplied DisplayObject must be a child of the caller

After 2 days of trying and searching for an answer I still didn't found it. I keep getting Error #2025: The supplied DisplayObject must be a child of the caller. I'm making a game where if the user hits an enemy, the enemy get destroyed. The code:
My main class
package classes
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.Timer;
public class Main extends MovieClip
{
var enemyTimer:Timer;
public function Main()
{
var user:ship = new ship();
addChild(user);
user.name = "user";
user.initialize();
enemyTimer = new Timer(2000);
enemyTimer.addEventListener("timer", sendEnemy);
enemyTimer.start();
function sendEnemy(e:Event)
{
var badboy:enemy = new enemy();
addChild(badboy);
badboy.initialize();
}
}
}
}
the enemy class
package classes.enemy
{
import flash.display.MovieClip;
import flash.events.Event;
public class Enemy extends MovieClip
{
var speed:Number;
public function initialize()
{
addEventListener("enterFrame", enterFrame);
}
public function Enemy()
{
this.x = 700;
this.y = Math.random()*200 + 50;
speed = Math.random()*5 + 5;
}
function enterFrame(e:Event)
{
this.x -= speed;
if(this.hitTestObject(parent.getChildByName("user")))
{
kill();
}
}
function kill()
{
removeEventListener("enterFrame", enterFrame);
stage.removeChild(this);
}
}
}
The files are in different folders (classes > Main.as & classes.enemy.Enemy.as), don't know if that has anything to do with it.
Any help would be appreciated.
That's probably because you try to remove the Enemy MovieClip from stage, that it is not a (direct) child of.
I suggest you change this:
stage.removeChild(this);
to this:
this.parent.removeChild(this);
When you have a reference to a DisplayObject, like this in this case, you can always remove it from its parent, even if you don't know what that parent is. Or rather, you can remove it if you know it is on the display list, so you could also first check that it is, by doing:
if(this.parent) {
this.parent.removeChild(this);
}
I have got the solution: Just copy and paste the script and create few essentials symbols on stage, and in library; then, check it.
import flash.display.MovieClip;
var myArr:Array = [];
abc.startDrag(true);
var mymc:MovieClip = new MovieClip();
addChild(mymc);
init();
function init()
{
for (var i=0; i<25; i++)
{
var par:Particle = new Particle();
par.x = Math.random() * stage.stageWidth;
par.y = Math.random() * stage.stageHeight;
mymc.addChildAt(par,0);
myArr.push(par);
}
this.addEventListener(Event.ENTER_FRAME, hitTes);
}
function hitTes(e:Event):void
{
for (var j=0; j<myArr.length; j++)
{
if (abc.hitTestObject(myArr[j]))
{
if (myArr[j].parent)
{
myArr[j].parent.removeChild(myArr[j]);
}
}
}
}
I think you misplaced a method. See if this revision helps. (Also note that this does not include any cleanup of objects, which will eventually be a problem.)
package classes
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.Timer;
public class Main extends MovieClip
{
public var enemyTimer:Timer;
public var user:ship = new ship();
public var badboy:enemy = new enemy();
public function Main()
{
user = new ship();
addChild(user);
user.name = "user";
user.initialize();
enemyTimer = new Timer(2000);
enemyTimer.addEventListener("timer", sendEnemy);
enemyTimer.start();
}
// *** I moved this out of the constructor:
public function sendEnemy(e:Event):void
{
badboy = new enemy();
badboy.name = "badboy"; // you probably have to make this unique, though.
addChild(badboy);
badboy.initialize();
}
}
}