-1

i'm new in flash and as3 programming, and this is my first project. i found error on my project like this

TypeError: Error #1009: Cannot access a property or method of a null object reference. at src.char::Enemy/Remove() at src.screen::Gameplay/Collision() at src.screen::Gameplay/Routine()

I think the error occurs because there is no function Remove () on the gameplay, but I'm not sure that's true. here's the enemy.as

import flash.display.MovieClip;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.Timer;

public class Enemy extends MovieClip {

    private var timer:Timer = new Timer(25);

    public function Enemy(xPos:Number, yPos:Number) {
        x = xPos;
        y = yPos;
        timer.addEventListener(TimerEvent.TIMER, MoveDown);
        timer.start();
    }

    private function MoveDown(e:TimerEvent):void {
        y += 3;
        if (y>400) {
            Remove();
        }
    }

    public function Remove():void {
        timer.stop();
        timer.removeEventListener(TimerEvent.TIMER, MoveDown);
        parent.removeChild(this);
    }

}

and here's the the gameplay.as

    public class Gameplay extends MovieClip {

    private var timer:Timer = new Timer(500);
    private var player:Player;

    public function Gameplay() {
        addEventListener(Event.ADDED_TO_STAGE, InitKeyboard);
        addEventListener(Event.ENTER_FRAME, Routine);
        gameplayBack.addEventListener(MouseEvent.CLICK, GoToMap);
        timer.addEventListener(TimerEvent.TIMER, OnTick);
        timer.start();
        InitPlayer();
        InitLifePoint();
    }

    private function InitLifePoint():void {
        lifePoint.gotoAndStop(1);           
    }

    private function Routine(e:Event):void {
        Collision();
    }

    private function Collision():void {
        for (var i:int = 0; i < enemies.length; i++ ) {
            if (player.hitTestObject(enemies[i])) {
                PlayerHit();
                enemies[i].Remove();
                return;
            }else {
                for (var j:int = 0; j < bullets.length; j++ ) {
                    if (bullets[j].hitTestObject(enemies[i])) {
                        layerParticle.addChild(new Blast(bullets[j].x, bullets[j].y));
                        layerParticle.addChild(new Smoke(bullets[j].x, bullets[j].y));
                        bullets[j].Remove();
                        enemies[i].Remove();
                        scorePlay.text = int(scorePlay.text) + 10 + "";
                        trace(scorePlay.text);
                        return;
                    }
                }
            }
        }
    }


    private var life:int = 1000;
    private var currentLife:int = 1000;
    private function PlayerHit():void {
        currentLife -= 100;
        if (currentLife <= 0) {
            lifePoint.gotoAndStop(100);
            GameOver();
        }else {
            lifePoint.gotoAndStop(100 - currentLife / life * 100);
        }
    }

    private var result:Result = new Result();
    private function GameOver():void {
        result.youWin.alpha = 0;
        result.ok.addEventListener(MouseEvent.CLICK, GoToMap);
        result.x = 0;
        result.y = 0;
        addChild(result);
    }

    private function InitKeyboard(e:Event):void {
        removeEventListener(Event.ADDED_TO_STAGE, InitKeyboard);
        stage.addEventListener(KeyboardEvent.KEY_DOWN, KeyDown);
    }

    private function KeyDown(e:KeyboardEvent):void {
        switch(e.keyCode) {
            case Keyboard.LEFT: MoveLeft(); break;
            case Keyboard.RIGHT: MoveRight(); break;
            case Keyboard.SPACE: Fire(); break;
        }
    }

    private var bullets:Array = new Array();
    private function Fire():void {
        var bullet:Bullet = new Bullet(player.x, player.y);
        bullet.scaleX = 0.25;
        bullet.scaleY = 0.25;
        bullet.addEventListener(Event.REMOVED_FROM_STAGE, RemoveBulletArray);
        layerParticle.addChild(bullet);
        bullets.push(bullet);
    }

    private function RemoveBulletArray(e:Event):void {
        removeEventListener(Event.REMOVED_FROM_STAGE, RemoveBulletArray);
        var index:int = bullets.indexOf(Bullet(e.currentTarget), 0);
        bullets.splice(index, 1);
    }

    private function MoveRight():void {
        if (player.x < 550) {
            player.x += 5;
        }
    }

    private function MoveLeft():void {
        if (player.x > 0) {
            player.x -= 5;
        }
    }

    private function InitPlayer():void {
        player = new Player(550 * 0.5, 350);
        layerChar.addChild(player);
    }

    private function OnTick(e:TimerEvent):void {
        RandomEnemy();
    }

    private var enemies:Array = new Array();
    private function RandomEnemy():void {
        var enemy:Enemy = new Enemy(Math.random() * 550, 0);
        enemy.addEventListener(Event.REMOVED_FROM_STAGE, RemoveFromArray);
        layerChar.addChild(enemy);
        enemies.push(enemy);
    }

    private var remaining:int = 10;
    private function RemoveFromArray(e:Event):void {
        removeEventListener(Event.REMOVED_FROM_STAGE, RemoveFromArray);
        var index:int = enemies.indexOf(Enemy(e.currentTarget), 0);
        enemies.slice(index, 1);
        remaining--;
        if (remaining == 0) GameWin();
    }

    private function GameWin():void {
        result.youLose.alpha = 0;
        result.score.text = scorePlay.text;
        result.ok.addEventListener(MouseEvent.CLICK, GoToMap);
        result.x = 0;
        result.y = 0;
        addChild(result);
    }

    private function GoToMap(e:MouseEvent):void {
        dispatchEvent(new ScreenEvent(ScreenEvent.MAP));
    }

}
Cœur
  • 37,241
  • 25
  • 195
  • 267

2 Answers2

1

Your problem is a NPE (Null Pointer Exception/Error) inside the Enemy.Remove() method:

public function Remove():void {
    timer.stop();
    timer.removeEventListener(TimerEvent.TIMER, MoveDown);
    parent.removeChild(this);
}

Either your timer property is null (which I doubt, looking at your code) or the parent property are.

In a MovieClip the parent property are filled with a DisplayObject if your MovieClip is added to it, if not, this property is null.

Your problem probably is that you are removing (from its parent) this MovieClip more than once, or is trying to remove it without adding it first.

To make sure this is the problem, add a if statement to check the parent property first, like this:

if(parent != null)
{
    parent.removeChild(this);
}

Note:
This may solve your NPE problem, but will not solve what is causing it, which may lead you into more and more inexplicable bugs.
Double check your logic to make sure you're removing a previously added MovieClip, or that you aren't removing it more than once.

NemoStein
  • 2,088
  • 2
  • 22
  • 36
  • thank you for your aswer, it's helping me. but o got another error. which say "ReferenceError: Error #1069: Property Remove not found on src.char.Enemy and there is no default value. at src.screen::Gameplay/Collition() at src.screen::Gameplay/Routine()" the collision work, but wont remove the object on array. i just confused. the code just the same as the rest. am i make mistake in parent.removeChild(this)? – Sofi Ardhan Prasetyo Feb 01 '13 at 06:23
  • Do you have more than one class named Enemy in your project? By the way, there is a typo in your methods name: `Gameplay/Collition()`. – NemoStein Feb 01 '13 at 13:38
0

Do you notice the flaw in the Collision function, if you observe like this:

for (var i:int = 0; i < enemies.length; i++) {
            if (~) {
                ...
                enemies[i].Remove();
                ...
            } else {
                for (~) {
                    if (~) {
                        ...
                        enemies[i].Remove();
                        ...
                    }
                }
            }
        }

Apparently, in the second for loop you could be easily referencing the same Enemy Object.

And the problem comes after you call Remove function, because by doing parent.removeChild(this); you remove the only reference of the object to it's parent object.

You can try to do one of these:

  • Keep a reference to the parent object in the class, manually.
  • Keep a state variable in the class to check if it is to be a part of display list or not.
  • Move the enemies[i].Remove(); code into outermost loop.
  • If possile, recycle the object. Especially, when you are just moving (x,y) the movieclip around.
loxxy
  • 12,990
  • 2
  • 25
  • 56
  • i dont get it what your point, can you make it clearer? i got another error which says "ReferenceError: Error #1069: Property Remove not found on src.char.Enemy and there is no default value. at src.screen::Gameplay/Collition() at src.screen::Gameplay/Routine()" what possible answer to remove the object on that array. even the whole code same as above. thank you for your help. – Sofi Ardhan Prasetyo Feb 01 '13 at 06:23
  • i found my self the error, it because my Remove() declaration in private, should be public. – Sofi Ardhan Prasetyo Feb 01 '13 at 07:34