Error #2025: The supplied DisplayObject must be a child of the caller - Game Looping when after gotoAndStop - actionscript-3

So ok Im somewhat new to flash im more of a java man myself but anyway I keep getting this error and all the solutions ive been find either don't work or they break the games collision
Here's the Code
stop();
import flash.utils.Timer;
import flash.utils.getDefinitionByName;
import flash.events.Event;
import flash.events.TimerEvent;
var playerobj:player;
var nextObject:Timer;
var objects:Array = new Array();
var score:int = 0;
const speed:Number = 9.0;
playerobj = new player();
playerobj.y = 650;
addChild(playerobj);
setNextObject();
addEventListener(Event.ENTER_FRAME, moveObjects);
function setNextObject()
{
nextObject = new Timer(1000+Math.random()*1000,1);
nextObject.addEventListener(TimerEvent.TIMER_COMPLETE,newObject);
nextObject.start();
}
function newObject(e:Event)
{
var newObject:AI;
newObject = new AI();
newObject.x = Math.random() * 480;
addChild(newObject);
objects.push(newObject);
setNextObject();
}
function moveObjects(e:Event)
{
for (var i:int=objects.length-1; i>=0; i--)
{
objects[i].y += speed;
if (objects[i].y > 800)
{
removeChild(objects[i]);
score = score + 10000;
objects.splice(i,1);
}
if (objects[i].hitTestObject(playerobj))
{
cleanUp();
}
}
playerobj.x = mouseX;
}
function cleanUp():void
{
while (this.numChildren > 0)
{
removeChildAt(0);
}
nextObject.stop();
gotoAndStop(4);
stop();
}
It must be somehow related to this problem but whenever gotoAndStop is called the game seems to loop around back into the frame not really sure why, Thanks for your help

In the cleanup function, right after declaring it, you should remove the ENTER_FRAME event listener. Also, I would stop the timer before removing childs and I would just remove the objects you added to stage dynamically. And the stop() in the cleanup function is redundant.
function cleanUp():void {
removeEventListener(Event.ENTER_FRAME, moveObjects);
nextObject.stop();
for(var i:uint = 0; i < objects.length; i++){
removeChild(objects[i]);
}
removeChild(playerObj)
gotoAndStop(4);
}
Also, it's better to keep minimal code in the timeline and move as much as you can in classes.

the error is in the cleanUp()
function moveObjects(e:Event)
{
for (var i:int=objects.length-1; i>=0; i--)
{
objects[i].y += speed;
if (objects[i].y > 800)
{
removeChild(objects[i]);
score = score + 10000;
objects.splice(i,1);
}
if (objects[i].hitTestObject(playerobj))
{
cleanUp();
}
}
//playerobj no more exists if cleanUp() is called, move this line above cleanUp();
//playerobj.x = mouseX;
//or inside cleanUp() put that line
//removeEventListener(Event.ENTER_FRAME, moveObjects);
}

Related

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

I am making a minions game. My minion's instance name is sideMinion. The bananas are falling and everything works fine, but my removeChild() doesn't work properly. The error I'm getting is
Error #2025: The supplied DisplayObject must be a child of the caller.
The removeChild() or the hitTestObject doesn't work properly.
This is what I have in my banana as. class:
package {
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.events.Event;
public class banana extends MovieClip {
var velX: Number = 0;
var velY: Number = 0;
var falling: Boolean = false;
var gravity: Number = 0;
public function banana() {
var timing: Timer = new Timer(25, 0);
timing.addEventListener(TimerEvent.TIMER, moveMe);
timing.start();
}
private function moveMe(event: TimerEvent)
{
x += velX;
y += velY;
if (falling) velY += gravity;
/* trace("[BANANA] position:", x, y, "speed:", velX, velY);*/
}
public function setSpeed(dx,dy) {
velX = dx;
velY = dy;
}
public function setSpot(atX,atY){
this.x=atX;
this.y=atY;
}
public function makeItFall (){
falling=true;
}
}
}
And in my main program:
import flash.display.MovieClip;
import flash.events.KeyboardEvent;
import flash.events.Event;
var leftKey:Boolean;
var rightKey:Boolean;
var upKey:Boolean;
var downKey:Boolean;
var jump:Boolean = false;
var xvelocity:int = 9;
var yvelocity:int = 3;
var gravity:Number = 7;
stage.addEventListener(Event.ENTER_FRAME, changeVelocity);
stage.addEventListener(KeyboardEvent.KEY_UP, checkKeyUp);
stage.addEventListener(KeyboardEvent.KEY_DOWN, checkKeyDown);
function changeVelocity(evt:Event){
moveMinion();
yvelocity += gravity;
}
function moveMinion(){
if (leftKey == true){
sideMinion.x -= xvelocity;
sideMinion.left();
}
if (rightKey == true){
sideMinion.x += xvelocity;
sideMinion.right();
}
}
function checkKeyDown(e:KeyboardEvent){
if (e.keyCode == Keyboard.LEFT){
leftKey = true;
}
else if (e.keyCode == Keyboard.RIGHT){
rightKey = true;
}
}
function checkKeyUp(e:KeyboardEvent){
if (e.keyCode == Keyboard.LEFT){
leftKey = false;
}
else if (e.keyCode == Keyboard.RIGHT){
rightKey = false;
}
}
btnStart.addEventListener(MouseEvent.CLICK, makeItFall);
function makeItFall(e:MouseEvent){
var numBananas = 6;
var theBananas: Array = new Array();
theBananas = [];
for (var i = 0; i < numBananas; i++) {
var aBanana: banana = new banana();
theBananas.push(aBanana);
btnStart.visible=false;
aBanana.y=30;
theBananas[i].setSpot(Math.random()*450+50,Math.random()*200+20);
theBananas[i].setSpeed((Math.random()), 1);
stage.addChild(aBanana);
}
var health: uint= 1;
addEventListener(Event.ENTER_FRAME, pickUpBananas);
function pickUpBananas(event:Event){
for( var i= 0; i<theBananas.length; ++i){
if (sideMinion.hitTestObject(theBananas[i])){
removeChild(theBananas[i]);
health=health+1;
trace(health);
}
}
}
}
stop();
Edit : format code
As you are adding child to stage, you'll have to remove it also from stage:
stage.removeChild(theBananas[i]);
For future, in some situations you can also use parent property if you don't know the actual parent:
theBananas[i].parent.removeChild(theBananas[i]);
In your game, I assume you want also to remove the bananas from theBananas-array when you remove bananas from stage, so that your array wont end up having already deleted bananas. So, here's couple modifications:
for(var i:int = theBananas.length-1; i>-1; i--){ //inverted loop
if (sideMinion.hitTestObject(theBananas[i])){
stage.removeChild(theBananas[i]);
theBananas.splice(i,1); //removing it from the array
health=health+1;
trace(health);
}
}
Inverted loop obviously loops from last element all the way to the first one, becouse if you'd remove the first element from the array, then second element would 'jump' into its place and loop would skip it.
I hope we all will soon get to see your game! :)

Adobe Animate CC dynamic text null error

I have got this error
"TypeError: Error #1009: Cannot access a property or method of a null object reference.
at sole_fla::MainTimeline/game()"
I just can't seems to display my score on the dynamic text box that I created that I named as "scoretext"
this is my code
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.display.MovieClip;
addEventListener(Event.ENTER_FRAME, game);
addEventListener(MouseEvent.CLICK, onClick);
var score:int = 0;
var high:int = 0;
const gravity:Number = 2;
const force: Number = 30;
const lyfe: Number = 100;
var yspeed: Number = 249;
var life: Number = 0;
function onClick(event:MouseEvent):void
{
//just testing if mouse input is detected
trace("The event handler works!");
}
//game main loop
function game(event: Event) {
score = 0;
life = lyfe;
yspeed = yspeed + gravity;
player.y = yspeed;
if(player.y - player.height/2 < 0)
player.y = player.height/2;
for (var i = 0; i < numChildren; i++) {
//test if mons hit player
if (mons.hitTestObject(player)){
life = life - 10;
trace("hit");
}
//test if starz hit player
if (starz.hitTestObject(player)){
//I believe this is the part where it gets the error
//this is my scoretext dynamic text box to display the score
scoretext.text = score.toString();
++score;
}
}
}
stage.addEventListener(KeyboardEvent.KEY_DOWN, fl_KeyboardDownHandler_2);
function fl_KeyboardDownHandler_2(event:KeyboardEvent):void
{
if(event.keyCode == 32){
yspeed = yspeed - force;
trace("Key Code Pressed: " + event.keyCode);
player.gotoAndPlay(41);
}
}
Changing frames does not go together well with persistent event listeners.
The listener is executed, but references to objects are null if the object is not present on the current frame.
When switching states in your application, terminate previous states properly by removing event listeners.

"TypeError: Error #1009: Cannot access a property or method of a null object reference" while using gotoAndplay function

I was trying to add a gameover screen with a restart button for my game.I had placed the restart button at frame 22.When my player dies it goes to frame 22 and i'm able to restart the game on clicking the button,but this message gets looped in the output area.Please help me how i can correct this issue.
Issue is not there when i remove the line
gotoAndPlay(22);
at Frame 17,but without that i will not get the desired functionality.
Please find my code below
At Frame 17 - Game code
stop();
import flash.events.Event;
import flash.events.MouseEvent;
var mouseIsDown = false;
var speed = 0;
var score = 0;
addEventListener(Event.ENTER_FRAME,mainLoop);
stage.addEventListener(MouseEvent.MOUSE_DOWN,clicked);
stage.addEventListener(MouseEvent.MOUSE_UP,unclicked);
function clicked(m:MouseEvent)
{
mouseIsDown = true;
}
function unclicked(m:MouseEvent)
{
mouseIsDown = false;
}
function mainLoop(e:Event)
{
score = score + 10;
output.text = "Score: "+score;
if(mouseIsDown)
{
speed -= 2;
}
else
{
speed+=2;
}
if(speed > 10) speed = 10;
if(speed < -10) speed = -10;
player.y += speed;
for(var i = 0; i < numChildren; i++)
{
if (getChildAt(i) is Cloud || getChildAt(i) is Boundary)
{
var b = getChildAt(i) as MovieClip;
if(b.hitTestObject(player))
{
for(var counter = 0; counter < 12; counter++)
{
var boom = new Boom();
boom.x = player.x;
boom.y = player.y;
boom.rotation = Math.random() * 360;
boom.scaleX = boom.scaleY = 0.5 + Math.random();
addChild(boom);
}
player.visible = false;
removeEventListener(Event.ENTER_FRAME,mainLoop);
gotoAndPlay(22);
}
}
}
}
At frame 22 - Restart screen
stop();
import flash.events.MouseEvent;
foutput.text = "Score: "+ fscore;
btn_playagain.addEventListener(MouseEvent.CLICK, playagain);
function playagain(m:MouseEvent)
{
gotoAndPlay(17);
}
btnback3.addEventListener(MouseEvent.CLICK, backMain3);
function backMain3(m:MouseEvent)
{
gotoAndPlay(1);
}
At frame 1 - Main Menu screen
stop();
import flash.events.MouseEvent;
import flash.system.fscommand;
btnnewgame.addEventListener(MouseEvent.CLICK, newGame);
function newGame(m:MouseEvent)
{
gotoAndPlay(17);
}
btnins.addEventListener(MouseEvent.CLICK, instruct);
function instruct(m:MouseEvent)
{
gotoAndPlay(6);
}
btncredits.addEventListener(MouseEvent.CLICK, credits);
function credits(m:MouseEvent)
{
gotoAndPlay(11);
}
btnexit.addEventListener(MouseEvent.CLICK, exitfunc);
function exitfunc(m:MouseEvent)
{
fscommand("quit");
}
At Frame 6 - Instructions Screen
stop();
btnback1.addEventListener(MouseEvent.CLICK, backMain1);
function backMain1(m:MouseEvent)
{
gotoAndPlay(1);
}
At Frame 11 - Credits Screen
stop();
btnback2.addEventListener(MouseEvent.CLICK, backMain2);
function backMain2(m:MouseEvent)
{
gotoAndPlay(1);
}
That error means that you are trying to call a method on a null object, meaning one of the objects you are using on frame 22 doesn't actually exist at that moment.
The likely candidates for the offending variable are foutput, btn_playagain, and btnback3. Check to make sure that they are on the stage at frame 22, and are spelt correctly.
You use output.text on frame 17, are you sure that it should be foutput.text on frame 22?

hitTestObject issue // remove stage Error #2025

hey :S I`m trying to make 2 things so far but neither work :(
The 1st is to make an Row of 5 Ships that position them selves from the top to left.Then add an Event to make them move down.
But every time i try to make a new Row of 5 new ships ... they position themselves after the last ship from the previous Row.I did think of a way to fix that by waiting the 1st Row of ships to go beyond the stage and then remove them from the stage and splice from the Array but ... when I increase the speed of spawning (when i have 2 rows with 5 ships on the stage or more)that does't work.
And the second error I think is from that fact .... that I have 2 rows at the same time on the stage.
ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
at flash.display::DisplayObjectContainer/removeChild()
at MainClass/doShips()
at MainClass/everyFrame()
I dont know what exactly to paste from the code so i had to push everything in the MainClass of the FLA.fail :D but i did it neatly! so if anyone helped me he would track the code easily
so its a simple FLA.fail with 4 MC and in those 4 MC there is no code
a Bullet
a Ship with colour Yellow
a Ship2 with colour Green so i can see the randomising
and a Player with the class Turret
so the MainClass of the FLA is :
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class MainClass extends MovieClip {
protected var mouseSpeed:Number = 20;
protected var _thePlayer:Turret = new Turret();
protected var shipCount:Number;
protected var shipCount2:Number;
protected var shipArray:Array = new Array();
protected var counter:int = 0;
//variables for bullets
private var shootCooldown:Number = 0; //speed of the fire
private var firing:Boolean = false;//bullets triger
private var numToShoot:int = 1; //bullets
const MAX_COOLDOWN = 10; //bullets timer
protected var _bulletsArray:Array = new Array();
public function MainClass() {
_thePlayer.x = stage.stageWidth/2
_thePlayer.y = stage.stageHeight - _thePlayer.height/2
addChild(_thePlayer)
addEventListener(Event.ENTER_FRAME, everyFrame)
stage.addEventListener(MouseEvent.MOUSE_DOWN, startFire);
stage.addEventListener(MouseEvent.MOUSE_UP, stopFire);
}
private function startFire(ev:MouseEvent) {
firing = true;
}
private function stopFire(ev:MouseEvent) {
firing = false;
}
//every frame do this
protected function everyFrame(ev:Event):void{
//Moving The Turret
moveTheTurret();
//increase the counter every frame
counter++;
if(counter % 70 == 0){
//position the ships on the stage
positionShips();
}
//handle the ships when they are added on the stage
doShips();
//when to fire
updateFire();
//handle the bullets
doBullets();
}
//Moving The Turret
protected function moveTheTurret() {
if (mouseX > _thePlayer.x +15) {
_thePlayer.x += mouseSpeed;
} else if (mouseX < _thePlayer.x - 15) {
_thePlayer.x -= mouseSpeed;
} else {
_thePlayer.x = mouseX;
}
}
//createShips and position them
protected function positionShips() {
shipCount = 3;
shipCount2 = 2;
var gap = 10;
for (var i:int = 0; i < shipCount; i++) {
var s = new Ship();
shipArray.push(s);
}
for (var j:int = 0; j < shipCount2; j++) {
s = new Ship2();
shipArray.push(s);
}
var array:Array=new Array();
while (shipArray.length>0) {
var index:uint = Math.floor(Math.random() * shipArray.length);
array.push(shipArray[index]);
shipArray.splice(index,1);
}
shipArray = array;
//shipsArray has been randomized
for (var k:int = shipArray.length - 1; k >= 0; k--) {
addChild(shipArray[k]);
shipArray[k].x = shipArray[k].width/2 + (shipArray[k].width * k) + (gap*k);
}
}
//move the ships
protected function doShips() {
for (var i:int = shipArray.length - 1; i >= 0; i--) {
shipArray[i].y +=3 //make the Ships fall down
for (var bcount= _bulletsArray.length-1; bcount >= 0; bcount--) {
//if the bullet is touching the ship
if (shipArray[i].hitTestObject(_bulletsArray[bcount])) {
//if we get here it means there`s is a collision
removeChild(_bulletsArray[bcount]);
_bulletsArray.splice(bcount,1);
removeChild(shipArray[i]);
_bulletsArray.splice(i,1);
}
}
//if it gets over 380 remove from stage and splice from the array
if(shipArray[i].y > 380){ // stage.stageHeight)
removeChild(shipArray[i]);
shipArray.splice(i,1);
}
}
}
//when to fire
public function updateFire() {
//if we are currently holding the mouse down
if(firing == true){
fire();
}
//reduce the cooldown by 1 every frame
shootCooldown--;
}
//Shoot bullets
private function fire() {
if (shootCooldown <= 0) {
//reset the cooldown
shootCooldown = MAX_COOLDOWN
for (var i=0; i<numToShoot; i++){
//spown a bullet
var b = new Bullet();
//set the rotation of the bullet
b.rotation = -90
b.x = _thePlayer.x;
b.y = _thePlayer.y;
//add the bullet to the list/Array of _bulletsArray
_bulletsArray.push(b);
//add the bullet to the perent object;
addChild(b);
}
}
}
//handling the bullets
protected function doBullets(){
//make a for loop to iterate all the _bulletsArray on the screen
for (var bcount:int = _bulletsArray.length-1; bcount>=0; bcount--) {
//make the bullets move Up
_bulletsArray[bcount].y -=20;
//if the bullet is beyond the screen remove from the stage and the Array
if(_bulletsArray[bcount].y < 0){
removeChild(_bulletsArray[bcount])
_bulletsArray.splice(bcount,1);
}
}
}
}
}
I dont know how to fix neither of the 2 problems.Would be very thankful for any help!!!
Thanks in advance.

How to remove all of one class of children from screen in Flash CS4 AS3?

Ok, so I've been stuck on this for about three hours now and I finally feel like asking for help.
Basically, I am trying to remove all instances of an enemy object from the screen when my player ship makes contact with one of them, as he then loses a life and is put back into a safe position on the screen.
EDIT: This is all the code from my Enemy Dude .as file, a bit overboard maybe but nonetheless.
package
{
import flash.display.MovieClip;
import flash.events.*;
import flash.media.Sound;
import flash.media.SoundChannel;
public class Enemydude extends MovieClip
{
private var _root:Object;
private var speed:int = 6;
private var shipps = this
public function Enemydude()
{
addEventListener(Event.ADDED, beginclass);
addEventListener(Event.ENTER_FRAME, entFrame);
}
private function beginclass(event:Event):void
{
_root = MovieClip(root);
}
private function entFrame(event:Event):void
{
x -= speed;
if(this.x < -64)
{
removeEventListener(Event.ENTER_FRAME, entFrame);
_root.removeChild(this)
}
if(_root.gameover)
{
x = -700
removeEventListener(Event.ENTER_FRAME, entFrame);
removeEventListener(Event.ADDED, beginclass);
}
for (var i:int = 0; i<_root.playerBulletContainer.numChildren; i++)
{
var bulletTarget:MovieClip = _root.playerBulletContainer.getChildAt(i)
if (hitTestObject(bulletTarget))
{
removeEventListener(Event.ENTER_FRAME, entFrame);
_root.removeChild(this);
_root.playerBulletContainer.removeChild(bulletTarget);
bulletTarget.removeListeners();
_root.Score += 10
makeExplosion();
}
}
if(hitTestObject(_root.mcship))
{
makeExplosion();
shipPos();
removethis();
}
}
private function makeExplosion()
{
var sndExplode:snd_explosion1;
var sndExplodeChannel:SoundChannel;
sndExplode=new snd_explosion1();
sndExplodeChannel=sndExplode.play();
var newExplosion01:explosionEffect=new explosionEffect ;
newExplosion01.x=this.x;
newExplosion01.y=this.y;
_root.explosionContainer.addChild(newExplosion01);
}
private function shipPos()
{
_root.lives -= 1;
_root.mcship.x = 80;
_root.mcship.y = 225;
for each(var i:Enemydude in _root.enemies)
{
removethis();
}
_root.enemies.length = 0;
}
public function removethis():void
{
if(parent) parent.removeChild(this)
removeEventListener(Event.ENTER_FRAME, entFrame);
}
}
}
EDIT: And this is the code I now have that relates to the Enemydude in my main timeline, quite sorry about all this.
var enemies:Array = [];
var Shipheight:Number = 300;
var Enemytime:int = 0;
var Enemylimit:int = 16;
if (Enemytime<Enemylimit)
{
Enemytime ++;
}
else
{
var newEnemy01 = new Enemydude();
newEnemy01.y = Shipheight;
newEnemy01.x = stage.stageWidth + 64;
addChild(newEnemy01);
enemies.push(newEnemy01);
Enemytime = 0
function shipY(event:Event):void
{
Shipheight = Math.ceil(Math.random()* 250) + 80;
}
Thank you for your help in advance, any advice is appreciated.
I suggest storing your enemies in an Array.
For example, create the array enemies:
var enemies:Array = [];
And then amend your code to:
else
{
var newEnemy01 = new Enemydude();
newEnemy01.y = Shipheight;
newEnemy01.x = stage.stageWidth + 64;
addChild(newEnemy01);
enemies.push(newEnemy01);
Enemytime = 0;
}
That way you can remove all of the enemies using this new array:
for each(var i:Enemydude in enemies)
{
i.remove(); // Or whatever function Enemydude has to remove itself.
}
// Empty the enemies Array.
enemies.length = 0;
Here's the .remove() method you could make for Enemydude:
public function remove():void
{
if(parent) parent.removeChild(this);
// Remove any event listeners etc from this object.
}
A common and easy way of doing this is to create a subcontainer to hold the objects and destroy this object instead. It makes easy for some collision checks too, since you can use the holder object to make one check against the player.
If you don't want to create this, you can use an array or a vector to store references to this objects, what makes easy to traverse the list.
I persoally recommend the vector aprouch:
var enemyList:Vector.<Enemy> = new Vector.<Enemy>();
Then you can loop almost like an array (as Marty Wallace showed on his answer):
for each(var e:Enemy in enemyList) {
container.removeChild(e);
}
enemyList.length = 0; // empty vector
Vectors are a bit slower than normal arrays, but are type safe. The difference in performance is almost negligible in most cases.