Why am I receiving a null error when I do a `hitTest` on a defined object?

64 views Asked by At

All I'm trying to do is remove some children from the stage but yet it gives me a null error:

TypeError: Error #2007: Parameter hitTestObject must be non-null.
at flash.display::DisplayObject/flash.display:DisplayObject::_hitTest()
at flash.display::DisplayObject/hitTestObject()
at SpaceOddessey_fla::MainTimeline/GreenMove()

I don't understand why this is happening because I defined the object in the function above the move/removal function of the 'Green Guy'. I can't move forward with this project until I get this fixed because I need to use it for the rest of my sprites as well.

Here's my code

stop();

//do this three times (for each space dude)
//GREEN
var MaxGreen:int = 1;
//Here we declare the speed of these cannon balls
var GreenVelocityX:Array = new Array();
var GreenVelocityY:Array = new Array();
//keep track of how many green guys
var GreenCount:int = 0;
var GreenSprite:Sprite;//declare a global variable for the cannonBall sprite.
var theGreen:Green_Guy;
//create the array thats holds the green guys
var myGreenGuyArray:Array = new Array(); 



//YELLOW
var MaxYellow:int = 1;
//Here we declare the speed of these cannon balls
var YellowVelocityX:Array = new Array();
var YellowVelocityY:Array = new Array();
//keep track of how many yellow guys
var YellowCount:int = 0;
var YellowSprite:Sprite;//declare a global variable for the cannonBall sprite.
var theYellow:Yellow_Guy;
//create the array thats holds the yellow guys
var myYellowGuyArray:Array = new Array();



//BABY
var MaxBabies:int = 1;
//Here we declare the speed of these cannon balls
var BabyVelocityX:Array = new Array();
var BabyVelocityY:Array = new Array();
//keep track of how many baby guys
var BabyCount:int = 0;
var BabySprite:Sprite;//declare a global variable for the cannonBall sprite.
var theBaby:Baby_Guy;
//create the array thats holds the baby guys
var myBabyGuyArray:Array = new Array();



//SPACE SHIP
var MaxShips:int = 4;
//Here we declare the speed of these cannon balls
var ShipVelocityX:Array = new Array();
var ShipVelocityY:Array = new Array();
//keep track of how many baby guys
var ShipCount:int = 0;
var ShipSprite:Sprite;//declare a global variable for the cannonBall sprite.
var theShip:space_ship;
//create the array thats holds the baby guys
var ShipArray:Array = new Array();


//ASTEROID
var MaxRocks:int = 6;
//Here we declare the speed of these cannon balls
var RockVelocityX:Array = new Array();
var RockVelocityY:Array = new Array();
//keep track of how many baby guys
var RockCount:int = 0;
var RockSprite:Sprite;//declare a global variable for the cannonBall sprite.
var theRock:rock;
//create the array thats holds the baby guys
var RockArray:Array = new Array();

yellow_btn.addEventListener(MouseEvent.CLICK, ClickHandle);
green_btn.addEventListener(MouseEvent.CLICK, ClickHandle);
baby_btn.addEventListener(MouseEvent.CLICK, ClickHandle);
function ClickHandle(targetEvent:MouseEvent):void
{
    if(targetEvent.target == yellow_btn)
    {
        MaxYellow += 1;

        stage.addEventListener(Event.ENTER_FRAME,makeYellow);
    }
    else if(targetEvent.target == green_btn)
    {
        MaxGreen += 1;
        stage.addEventListener(Event.ENTER_FRAME,makeGreen);
    }
    else if(targetEvent.target == baby_btn)
    {
        MaxBabies += 1;
        stage.addEventListener(Event.ENTER_FRAME,makeBaby);
    }
}

stage.addEventListener(Event.ENTER_FRAME,makeShips);

function makeShips(Space:Event){
    //Create the Enemies if there are less then 100
    if (ShipCount < MaxShips){
        //create our sprites
        ShipSprite = new Sprite();
        stage.addChild(ShipSprite);
        theShip = new space_ship();
        ShipSprite.addChild(theShip);

        ShipSprite.x = Math.random() * 500;//width ~ 81.7
        ShipSprite.y = Math.random() * 300;

        //allows a scaler of making objects from big to small
        //BabySprite.scaleX = BabySprite.scaleY = Math.random() * 1.3;

        ShipArray[ShipCount] = ShipSprite;
        ShipCount += 1;

        stage.addEventListener(Event.ENTER_FRAME,ShipMove);
        }

        //end for loop
    }
function ShipMove(go:Event):void
{
    for(var s=0; s<ShipCount; s++)
    {
        ShipVelocityX[s] = -3;
        ShipVelocityY[s] = -1;
        /*if(my)
        {

        }*/
        ShipArray[s].x += ShipVelocityX[s];
        //myYellowGuyArray[a].y += YellowVelocityY[a];
        if (ShipArray[s].x > 550)
        {
            ShipArray[s].x = 0 - ShipArray[s].width;
        }
        else if(ShipArray[s].x + ShipArray[s].width < 0)
        {
            ShipArray[s].x = 500;
        }
        if(ShipArray[s].y > 400)
        {
            ShipArray[s].y = 0 - ShipArray[s].height;
        }
        else if(ShipArray[s].y + ShipArray[s].height < 0)
        {
            ShipArray[s].y = 400;
        }
    }
}

stage.addEventListener(Event.ENTER_FRAME,makeBaby);

function makeBaby(DudeEvent:Event){
    //Create the Enemies if there are less then 100
    if (BabyCount < MaxBabies){
        //create our sprites
        BabySprite = new Sprite();
        stage.addChild(BabySprite);
        theBaby = new Baby_Guy();
        BabySprite.addChild(theBaby);

        BabySprite.x = Math.random() * 500;//width ~ 81.7
        BabySprite.y = Math.random() * 300;

        //allows a scaler of making objects from big to small
        //BabySprite.scaleX = BabySprite.scaleY = Math.random() * 1.3;

        myBabyGuyArray[BabyCount] = BabySprite;
        BabyCount += 1;
        //trace(myEnemies.length);

        stage.addEventListener(Event.ENTER_FRAME,BabyMove);
        }

        //end for loop
    }
function BabyMove(go:Event):void
{
    for(var i=0; i<BabyCount; i++)
    {
        BabyVelocityX[i] = 5;
        BabyVelocityY[i] = 2;
        /*if(my)
        {

        }*/
        myBabyGuyArray[i].x += BabyVelocityX[i];
        myBabyGuyArray[i].y += BabyVelocityY[i];
        myBabyGuyArray[i].rotation += 2;
        if (myBabyGuyArray[i].x > 550)
        {
            myBabyGuyArray[i].x = 0 - myBabyGuyArray[i].width;
        }
        else if(myBabyGuyArray[i].x + myBabyGuyArray[i].width < 0)
        {
            myBabyGuyArray[i].x = 500;
        }
        if(myBabyGuyArray[i].y > 400)
        {
            myBabyGuyArray[i].y = 0 - myBabyGuyArray[i].height;
        }
        else if(myBabyGuyArray[i].y + myBabyGuyArray[i].height < 0)
        {
            myBabyGuyArray[i].y = 400;
        }
        for(var v:int=0; v<RockCount; v++)
        {
            if(RockArray[v].hitTestObject(myBabyGuyArray[i]))
            {
                //trace('hey')
                BabyVelocityX[i] = 100;
            }
        }
    }
}

stage.addEventListener(Event.ENTER_FRAME,makeYellow);

function makeYellow(Dude:Event){
    //Create the Enemies if there are less then 100
    if (YellowCount < MaxYellow){
        //create our sprites
        YellowSprite = new Sprite();
        stage.addChild(YellowSprite);
        theYellow = new Yellow_Guy();
        YellowSprite.addChild(theYellow);

        YellowSprite.x = Math.random() * 500;//width ~ 81.7
        YellowSprite.y = Math.random() * 300;

        //allows a scaler of making objects from big to small
        //BabySprite.scaleX = BabySprite.scaleY = Math.random() * 1.3;

        myYellowGuyArray[YellowCount] = YellowSprite;
        YellowCount += 1;

        stage.addEventListener(Event.ENTER_FRAME,YellowMove);
        }

        //end for loop
    }
function YellowMove(go:Event):void
{
    for(var a=0; a<YellowCount; a++)
    {
        YellowVelocityX[a] = -3;
        YellowVelocityY[a] = -1;
        /*if(my)
        {

        }*/
        myYellowGuyArray[a].x += YellowVelocityX[a];
        myYellowGuyArray[a].y += YellowVelocityY[a];
        myYellowGuyArray[a].rotation += 1;
        if (myYellowGuyArray[a].x > 550)
        {
            myYellowGuyArray[a].x = 0 - myYellowGuyArray[a].width;
        }
        else if(myYellowGuyArray[a].x + myYellowGuyArray[a].width < 0)
        {
            myYellowGuyArray[a].x = 500;
        }
        if(myYellowGuyArray[a].y > 400)
        {
            myYellowGuyArray[a].y = 0 - myYellowGuyArray[a].height;
        }
        else if(myYellowGuyArray[a].y + myYellowGuyArray[a].height < 0)
        {
            myYellowGuyArray[a].y = 400;
        }
        for(var u:int=0; u<RockCount; u++)
        {
            if(RockArray[u].hitTestObject(myYellowGuyArray[a]))
            {
                YellowVelocityX[a] *= -1;
            }
        }
    }
}

stage.addEventListener(Event.ENTER_FRAME,makeGreen);

function makeGreen(Evnt:Event){
    //Create the Enemies if there are less then 100
    if (GreenCount < MaxGreen){
        //create our sprites
        GreenSprite = new Sprite();
        stage.addChild(GreenSprite);
        theGreen = new Green_Guy();
        GreenSprite.addChild(theGreen);

        GreenSprite.x = Math.random() * 500;//width ~ 81.7
        GreenSprite.y = Math.random() * 300;

        //allows a scaler of making objects from big to small
        //BabySprite.scaleX = BabySprite.scaleY = Math.random() * 1.3;

        myGreenGuyArray[GreenCount] = GreenSprite;
        GreenCount += 1;

        stage.addEventListener(Event.ENTER_FRAME,GreenMove);
        }
        //end for loop
    }
function GreenMove(go:Event):void
{
    for(var b:int=0; b<GreenCount; b++)
    {
        GreenVelocityX[b] = 7;
        GreenVelocityY[b] = -4;

        myGreenGuyArray[b].x += GreenVelocityX[b];
        myGreenGuyArray[b].y += GreenVelocityY[b];
        myGreenGuyArray[b].rotation -= 1;
        if (myGreenGuyArray[b].x > 550)
        {
            myGreenGuyArray[b].x = 0 - myGreenGuyArray[b].width;
        }
        else if(myGreenGuyArray[b].x + myGreenGuyArray[b].width < 0)
        {
            myGreenGuyArray[b].x = 500;
        }
        if(myGreenGuyArray[b].y > 400)
        {
            myGreenGuyArray[b].y = 0 - myGreenGuyArray[b].height;
        }
        else if(myGreenGuyArray[b].y + myGreenGuyArray[b].height < 0)
        {
            myGreenGuyArray[b].y = 400;
        }
        for(var z:int=0; z<ShipCount; z++)
        {
            //if(myGreenGuyArray[b] == null)
            {
                if(ShipArray[z].hitTestObject(myGreenGuyArray[b]))
                {
                    //if(GreenCount > 1)
                    //{
                        myGreenGuyArray[b].y = -50;
                        stage.removeChild(myGreenGuyArray[b]);
                        myGreenGuyArray.splice(b,1);
                        GreenCount--;
                        //b--;
                    //}
                }
            }
        }
        for(var g:int=0; g<RockCount; g++)
        {
            if(RockArray[g].hitTestObject(myGreenGuyArray[b]))
            {
                GreenVelocityX[b] *= -1;
            }
        }
    }
}

stage.addEventListener(Event.ENTER_FRAME,makeRocks);

function makeRocks(RockHard:Event){
    //Create the Enemies if there are less then 100
    if (RockCount < MaxRocks){
        //create our sprites
        RockSprite = new Sprite();
        stage.addChild(RockSprite);
        theRock = new rock();
        RockSprite.addChild(theRock);

        RockSprite.x = Math.random() * 500;//width ~ 81.7
        RockSprite.y = Math.random() * 300;

        //allows a scaler of making objects from big to small
        //BabySprite.scaleX = BabySprite.scaleY = Math.random() * 1.3;

        RockArray[RockCount] = RockSprite;
        RockCount += 1;

        stage.addEventListener(Event.ENTER_FRAME,RockMove);
        }

        //end for loop
    }
function RockMove(go:Event):void
{
    for(var r=0; r<RockCount; r++)
    {
        RockVelocityX[r] = 7;
        RockVelocityY[r] = 3;
        /*if(my)
        {

        }*/
        RockArray[r].x += RockVelocityX[r];
        //RockArray[r].y += RockVelocityY[r];
        if (RockArray[r].x > 550)
        {
            RockArray[r].x = 0 - RockArray[r].width;
        }
        else if(RockArray[r].x + RockArray[r].width < 0)
        {
            RockArray[r].x = 500;
        }
        if(RockArray[r].y > 400)
        {
            RockArray[r].y = 0 - RockArray[r].height;
        }
        else if(RockArray[r].y + RockArray[r].height < 0)
        {
            RockArray[r].y = 400;
        }
    }
}
2

There are 2 answers

0
Jawad Khan On

You have to restructure and simplify your code. You have to eliminate nested enter_frame events at all costs. ideally you can do all the happenings with one ENTER_FRAME event.

Do as following which is closest to your code and yet bit cleaner

  1. create functions for make and move
  2. call the make functions through for loop (not by enter_frame)
  3. once all the make functions are called then create an enter_frame event and call the move functions within that.

However, you can further make it more cleaner but atleast doing above will give you head start towards your goals.

0
null On

I don't understand why this is happening

This sounds trivial, but this is happening because of the reason given in the error description:

Parameter hitTestObject must be non-null.

And this is the truth that one has to accept. There is no way around it. There's no such thing as "but I'm sure this should not be happening". It's not like a discussion that can be won by raising the better argument. In a sense, the compiler is always right. You cannot disprove it.

I defined the object in the function above the move/removal function of the 'Green Guy'

No. The error says you didn't, so you didn't. The parameter is null. There's no point in denying the truth.

The real question is not "Why does it say it is null even though it isn't?", but "Why is the value null?"

The error states that it occurs in hitTestObject() function. the stack trace explains that it occurs in GreenMove() function. There are two lines that could be causing this.

if(ShipArray[z].hitTestObject(myGreenGuyArray[b]))

and

if(RockArray[g].hitTestObject(myGreenGuyArray[b]))

You should place a breakpoint at each line, run your code with the debugger again and try to reproduce the error. This is way you debug code. You do not look at it for five hours hoping that the reason will jump at you and get frustrated because you cannot find it.

When the error occurs, hitTestObject will think that myGreenGuyArray[b] is null. From this, you know for what value of b this happens. Run it again. Make it fail again. See if it always happens at the same value of b.

This line looks suspicious, because it alters the array.

myGreenGuyArray.splice(b,1);

Your problem is caused by the messy use of arrays. Think about it: what if there's only one element that gets removed? What happens if you access that (removed, nonexistent) element of the array again?

trace([1,2,3][37] == null); // does the result of accessing an element that doesn't exist equal null?

To solve this

  1. get rid of the unnecessary count variables. An array has a length property for exactly that purpose.
  2. Iterate backwards over the array. This will prevent skipping an element if one is removed and requires no strange subtractions of counts to account for that, it just works.
  3. As soon as an element is removed, stop the loop and go to the next iteration with continue and/or break, possibly in combination with a label, to jump out of nested loops.