0
votes

I came upon an error I can't fix. I'm making a game and it should say "you lose" after losing your 3 lives, but in my case everything freezes and I get an error.

TypeError: Error #2007: Parameter hitTestObject must be non-null. at flash.display::DisplayObject/_hitTest() at flash.display::DisplayObject/hitTestObject() at Fatality/enterFrameEvents()[C:\Documents and Settings\labo\Bureaublad\GIP 12 mei\Fatality.as:26]

Have a look at my code. This is the code I've written in the class

Basicly this class is a "game over" power in my breakout game. When this touches the paddle, it's game over. The problem is that it freezes after it touches the paddle instead of showing "you lose".

package 
{
    import flash.display.*;
    import flash.events.*;

    public class Fatality extends MovieClip
    {
        private var yspeed:Number = 1;
        private var _root:MovieClip;

        public function Fatality()
        {
            // constructor code
            addEventListener(Event.ADDED, beginClass);
            addEventListener(Event.ENTER_FRAME, enterFrameEvents);
        }
        private function beginClass(event:Event):void
        {
            //defining _root as the document root
            ////je definieërt _root als het document root
            _root = MovieClip(root);
        }
        private function enterFrameEvents(event:Event):void
        {
            this.y = this.y + yspeed;
            if (this.hitTestObject(_root.mcPaddle))
            {
                this.removeEventListener(Event.ENTER_FRAME, enterFrameEvents);
                this.parent.removeChild(this);

                if (_root.lives == 3)
                {
                    _root.removeChild(_root.hartje3);
                    _root.removeChild(_root.hartje2);
                    _root.removeChild(_root.hartje1);
                }
                else if (_root.lives == 2)
                {
                    _root.removeChild(_root.hartje2);
                    _root.removeChild(_root.hartje1);
                }
                else if (_root.lives == 1)
                {
                    _root.removeChild(_root.hartje1);
                }
                _root.gameOver = true;
                //De listeners weg doen
                _root.mcBall.removeEventListener(Event.ENTER_FRAME, _root.moveBall);
                _root.mcPaddle.removeEventListener(Event.ENTER_FRAME, _root.movePaddle);
                removeEventListener(Event.ENTER_FRAME, _root.checkLevel);
                removeEventListener(Event.ENTER_FRAME, _root.updateTextFields);
                //Ga naar een lose frame
                _root.gotoAndStop('lose');

            }
        }
    }

}

That last part refers to the lose frame, here is the code of the lose frame

    //De lose frame

//reset het spel als je op je muis klikt
stage.addEventListener(MouseEvent.CLICK, resetGame);

function resetGame(event:MouseEvent):void{
    //deze listener weg doen
    stage.removeEventListener(MouseEvent.CLICK, resetGame);
    //het spel resetten
    gotoAndPlay(1);
}

//de eindscore laten zien
txtScore.text = "Final Score: "+score;

I would really appreciate if somebody helped me with this error because it's been annoying me quite alot, thanks.

EDIT

MAIN CODE:

import flash.events.MouseEvent;
import flash.events.Event;

stop();
//Variabelen
//Nodige variabelen voor de beweging van de bal
var ballXSpeed:Number = 8;//X Snelheid van de bal
var ballYSpeed:Number = 8;//Y Snelheid van de bal
//Hoeveel bricks er over zijn op het stage (podium)
var brickAmt:int = 0;
//Hoeveel levens je hebt
var lives:int = 3;
//Als het game over is
var gameOver:Boolean = false;
//De score van het spel
var score:int = 0;
//Eerst heb ik een een functie gemaakt waar
//al de code in zit die nodig is om het spel te starten
//dit bevat listeners, variabelen en andere dingen
function beginCode(event:MouseEvent):void
{
    //doet de listener weg wanneer je klikt
    stage.removeEventListener(MouseEvent.CLICK, beginCode);
    //Voegt een listener toe aan de paddle
    //die een functie runt elke keer als een frame voorbij is
    mcPaddle.addEventListener(Event.ENTER_FRAME, movePaddle);
    //Voegt een listener toe aan de ball;
    //die een functie runt elke keer als een frame voorbij is
    mcBall.addEventListener(Event.ENTER_FRAME, moveBall);

    //Voegt een listener toe om te checken of het level voorbij is;
    addEventListener(Event.ENTER_FRAME, checkLevel);
    //verwijdert het "click to start" tekst
    txtStart.text = '';
}

function movePaddle(event:Event):void
{
    //De paddle volgt de muis
    mcPaddle.x = mouseX - mcPaddle.width / 2;
    //Houdt de paddle op het stage

    //Als de muis te ver naar links gaat
    if (mouseX < mcPaddle.width / 2)
    {
        //Houdt de paddle op het stage
        mcPaddle.x = 0;
    }
    //Als de muis te ver naar rechts gaat
    if (mouseX > stage.stageWidth - mcPaddle.width / 2)
    {
        //Houdt de paddle on stage
        mcPaddle.x = stage.stageWidth - mcPaddle.width;
    }
}
function ContinueGame(event:Event):void
{
    mcBall.addEventListener(Event.ENTER_FRAME, moveBall);
}
function moveBall(event:Event):void
{
    //Dit is de code voor de beweging van de bal
    mcBall.x +=  ballXSpeed;//Beweegt de bal horizontaal
    mcBall.y +=  ballYSpeed;//Beweegt de bal verticaal
    //Stuitert de bal weg van de muren
    if (mcBall.x >= stage.stageWidth - mcBall.width)
    {
        //Als de bal de rechterkant raakt
        //van het scherm, en weg stuitert 
        ballXSpeed *=  -1;
    }
    if (mcBall.x <= 0)
    {
        //Als de bal de linkerkant raakt
        //van het scherm, en weg stuitert 
        ballXSpeed *=  -1;
    }
    if (mcBall.y >= stage.stageHeight - mcBall.height)
    {
        //Als de bal de grond raakt
        //stuitert het omhoog en verlies je 1 leven
        //ballYSpeed *= -1;
        lives--;
        if (lives == 2)
        {
            removeChild(this.hartje3);
        }
        else if (lives == 1)
        {
            removeChild(this.hartje2);
        }
        else if (lives == 0)
        {
            removeChild(this.hartje1);
        }
        ballXSpeed = 8;
        ballYSpeed = 8;
        mcBall.x = 151.9;
        mcBall.y = 264.9;
        mcBall.removeEventListener(Event.ENTER_FRAME, moveBall);
        stage.addEventListener(MouseEvent.CLICK, ContinueGame);

        //Wanneer er geen levens meer over zijn
        if (lives <= 0)
        {
            //het is nu game over
            gameOver = true;
            //De listeners weg doen
            mcBall.removeEventListener(Event.ENTER_FRAME, moveBall);
            mcPaddle.removeEventListener(Event.ENTER_FRAME, movePaddle);
            removeEventListener(Event.ENTER_FRAME, checkLevel);
            removeEventListener(Event.ENTER_FRAME, updateTextFields);
            //Ga naar een lose frame
            gotoAndStop('lose');
        }
    }
    else
    {
        if (mcBall.y <= 0)
        {
            //Als de bal de bovenkant raakt van het scherm
            //en stuitert terug naar beneden
            ballYSpeed *=  -1;
        }
        //Je raakt de paddle
        if (mcBall.hitTestObject(mcPaddle))
        {
            calcBallAngle();
        }
    }
}

function calcBallAngle():void
{
    //ballPosition is de positie van het balletje op de paddle
    var ballPosition:Number = mcBall.x - mcPaddle.x;
    //hitPercent converts ballPosition in een percentage
    //Helemaal naar links is -0.5
    //Helemaal naar rechts is 0.5
    //Het midden is 0
    var hitPercent:Number = (ballPosition / (mcPaddle.width - mcBall.width)) - .5;
    //Neemt het hitPercent en maakt het een groter nummer zodat de bal
    //werkelijk stuitert
    ballXSpeed = hitPercent * 10;
    //Zorgt dat het balletje terug omhoog stuitert
    ballYSpeed *=  -1;
}

function makeLvl():void
{//Zet de bricks op level 1
    //checkt of er nog levels over zijn
    if (currentLvl > lvlArray.length)
    {
        //het is nu game over
        gameOver = true;
        //de listeners weg doen
        mcPaddle.removeEventListener(Event.ENTER_FRAME, movePaddle);
        mcBall.removeEventListener(Event.ENTER_FRAME, moveBall);
        removeEventListener(Event.ENTER_FRAME, checkLevel);
        removeEventListener(Event.ENTER_FRAME, updateTextFields);
        //ga naar een lose frame
        gotoAndStop("win");
    }
    //vindt de array lengte van de level code
    //De index moet currentLvl-1 zijn want:
    //array indexes beginnen vanaf 0 en onze level start op 1
    //onze level zal altijd 1 hoger zijn dan de index van de array
    var arrayLength:int = lvlArray[currentLvl - 1].length;
    //de huidige rij van bricks die we aan het maken zijn
    var brickRow:int = 0;
    //Een lus die dr bricks op het stage zet
    for (var i:int = 0; i<arrayLength; i++)
    {
        //Checkt of het een brick moet zetten daar
        if (lvlArray[currentLvl - 1][i] == 1)
        {
            //maakt een variabele aan van de brick
            var brick:Brick = new Brick();
            //regelt de coordinaten van de brick via de i variabele en brickRow
            brick.x = 15 + (i - brickRow * 7) * 75;
            brick.y = 10 + brickRow * 20;
            //checkt of de huidige brick een nieuwe rij nodig heeft
            for (var c:int = 1; c<=10; c++)
            {
                if (i == c*7-1)
                {
                    brickRow++;
                }
            }
            //nu zet dit de brick op het stage
            addChild(brick);
        }
    }
}

function checkLevel(event:Event):void
{
    //checkt of de bricks allemaal weg zijn
    if (brickAmt == 0)
    {
        //reset het level door het level te verhogen
        currentLvl++;
        //makeLvl wordt opnieuw gerunt
        //reset de tekst "click to begin"
        txtStart.text = "Click To Begin";
        makeLvl();
        //reset de positie van het balletje en de paddle
        mcBall.x = 150;
        mcBall.y = 265;
        mcBall.width = 10;
        mcBall.height = 10;
        mcPaddle.x = 230;
        //al de listeners weg doen
        mcPaddle.removeEventListener(Event.ENTER_FRAME, movePaddle);
        mcBall.removeEventListener(Event.ENTER_FRAME, moveBall);
        removeEventListener(Event.ENTER_FRAME, checkLevel);
        //je "listent" voor een click van de muis om het spel terug te starten
        stage.addEventListener(MouseEvent.CLICK, beginCode);
    }
}

function updateTextFields(event:Event):void
{
}
//als je clickt met je muis, begint het spel
stage.addEventListener(MouseEvent.CLICK, beginCode);
//de tekst die tevoorschijn komt;
txtStart.text = "Click To Begin";
//een functie maken om de text fields te updaten
addEventListener(Event.ENTER_FRAME, updateTextFields);
//het level maken
makeLvl();

pauseButton.addEventListener(MouseEvent.CLICK, pauseGame);
function pauseGame(e:MouseEvent):void
{
    stage.frameRate = 0;
}

playButton.addEventListener(MouseEvent.CLICK, resumeGame);
function resumeGame(e:MouseEvent):void
{
    stage.frameRate = 24;
}

CODE FOR THE BRICK CLASS:

//klassen moeten altijd in een packed zitten
package 
{
    //display elements importeren die we kunnen gebruiken in deze klasse
    import flash.display.*;
    import flash.events.*;

    //de naam van de klasse definiëren en zeggen dat
    //het de MovieClip klasse "extends",
    //dat wil zeggen dat het dezelfde properties heeft als die van een movieclip
    public class Brick extends MovieClip
    {
        //de main timeline
        private var _root:MovieClip;
        //alle klassen moeten een functie hebben die elke keer
        //runt wanneer een instance van die klasse op het stage wordt gezet
        public function Brick()
        {
            //deze code runt wanneer de brick op het stage wordt gezet
            addEventListener(Event.ADDED, beginClass);
            //enter frame code
            addEventListener(Event.ENTER_FRAME, enterFrameEvents);
        }
        //private functions zijn functies die je niet kan gebruiken
        //vanuit de main timeline, maar enkel vanuit de klasse zelf
        private function beginClass(event:Event):void
        {
            //je definieërt _root als het document root
            _root = MovieClip(root);
            //verhoogt het aantal bricks op het stage
            _root.brickAmt++;
        }
        private function enterFrameEvents(event:Event):void
        {
            //controleren of de player heeft verloren
            if (_root.gameOver)
            {
                //deze brick kapot maken
                this.parent.removeChild(this);
                //stoppen met deze code te runnen;
                removeEventListener(Event.ENTER_FRAME, enterFrameEvents);
            }
            //hit testing met het balletje
            if (this.hitTestObject(_root.mcBall))
            {
                //hierdoor stuitert het balletje verticaal
                _root.ballYSpeed *=  -1;
                //Creeër een Power UP (Werk met een Random
                //om een powerup te maken en werk met een
                //tweede random om te bepalen welke power)
                MakePowerUp();
                //deze brick kapot maken
                this.parent.removeChild(this);
                //stoppen met deze code te runnen;
                removeEventListener(Event.ENTER_FRAME, enterFrameEvents);
                //verlaagt het aantal bricks op het stage
                _root.brickAmt--;
                //de score verhogen
                _root.score +=  10;
            }
        }
        function MakePowerUp():void
        {
            //random plaatsen om te beslissen of er een power aangemaakt wordt
            //en zo ja, welke
            var getal = randomRange(1,40);
            if (getal < 3)
            {
                var power:Power = new Power();
                power.x = this.x + 35;
                power.y = this.y + 5;
                _root.addChild(power);
            }
            else if (getal < 6)
            {
                var power2:Power2 = new Power2();
                power2.x = this.x + 35;
                power2.y = this.y + 5;
                _root.addChild(power2);
            }
            else if (getal < 9)
            {
                var mario:Enlarger = new Enlarger();
                mario.x = this.x + 35;
                mario.y = this.y + 5;
                _root.addChild(mario);
            }
            else if (getal < 14)
            {
                var power3:Power3 = new Power3();
                power3.x = this.x + 35;
                power3.y = this.y + 5;
                _root.addChild(power3);
            }
            else if (getal < 16)
            {
                var fat:Fatality = new Fatality();
                fat.x = this.x + 35;
                fat.y = this.y + 5;
                _root.addChild(fat);
            }
            else if (getal < 20)
            {
                var lifesteal:Lifestealer = new Lifestealer();
                lifesteal.x = this.x + 35;
                lifesteal.y = this.y + 5;
                _root.addChild(lifesteal);
            }
        }
        function randomRange(minNum: Number, maxNum:Number):Number
        {
            return (Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum);
        }

    }
}
2

2 Answers

0
votes

The error is referring to line 26:

if (this.hitTestObject(_root.mcPaddle))

The error is telling you that _root.mcPaddle is null at that point in the program.

0
votes

You have an enterframe listener attached to all the bricks. They continue to fire after a gameover event. You have to remove all of them at the point you initiate a gameover condition. The trouble is, you apparently do not keep track of how many bricks are there, and what are they. I'd advise making an Array of Bricks, place them as usual, but use one single enter frame listener that will check if the ball collides with any of the bricks in turn, instead of testing against this aka a brick. This way you will have a single stationary point that will contain all the enterframe code, ease your debugging, allow yourself to expand the game functional easier, and consolidate all the code concerning game flow. For this, you will have to use a manager class, most likely Level, which you add to a frame instead of a set of bricks, and which will create the necessary amount of bricks from a data table that corresponds to a level.

If you want to do both creating a level by hand, aka placing bricks on stage, and have such a functionality, you make a container sprite, that overlaps the entirety of a level, that contains all the bricks, and that is either of Level type or extends Level, and make a Level class which will trace all its children for being of type Brick, enumerate them and add to an internal array. A sample enumerator code:

public class Level extends Sprite {
    private var bricks:Array=new Array();
    private var numBricks:int=0;
    public function Level() {
        for (var i:int=0;i<numChildren;i++) {
            if (getChildAt(i) is Brick) {
                numBricks++;
                bricks.push(getChildAt(i));
            }
        }
        // do the rest of initialization
        addEventListener(Event.ENTER_FRAME,processLevel);
    }
    private function processLevel(e:Event):void {
        moveBall();
        movePaddle();
        movePowerups();
        for (var i:int=numBricks-1;i>=0;i--) {
            if (bricks[i].hitTestObject(ball)) {
                // process hit brick
                bricks.splice(i,1); // drop a now nonexistent brick off array
                numBricks--;
                if (numBricks==0) { } // level won, add code to advance
                // and don't forget cleanup, and return statement!
            }
        }
        // about the same for powerups, including an array, number of powerups, 
        // powerups effect, etc.
    }