-1

我是 Flash 的初学者,目前我遇到了问题。我在做一个游戏,就像太空入侵者。一开始还不错 但是,当角色击中敌人时,它提示我错误。

类型错误:

错误 #1009:无法访问空对象引用的属性或方法。在 _fla::MainTimeline/frame1126() 在 flash.display::MovieClip/gotoAndStop() 在 Enemy/eFrame()

我不知道它有什么问题。谁能帮我?

这是我的时间线的来源

stop();
//these booleans will check which keys are down
var leftDown:Boolean = false;
var upDown:Boolean = false;
var rightDown:Boolean = false;
var downDown:Boolean = false;
//how fast the character will be able to go
var mainSpeed:int = 5;
//how much time before allowed to shoot again
var cTime:int = 0;
//the time it has to reach in order to be allowed to shoot (in frames)
var cLimit:int = 12;
//whether or not the user is allowed to shoot
var shootAllow:Boolean = true;
//how much time before another enemy is made
var enemyTime:int = 0;
//how much time needed to make an enemy
//it should be more than the shooting rate
//or else killing all of the enemies would
//be impossible :O
var enemyLimit:int = 16;
//the player's score
var score:int = 0;
//this movieclip will hold all of the bullets
var bulletContainer:MovieClip = new MovieClip();
addChild(bulletContainer);
//whether or not the game is over
var gameOver:Boolean = false;

//adding a listener to mcMain that will move the character
mcMain.addEventListener(Event.ENTER_FRAME, moveChar);
function moveChar(event:Event):void{
    //checking if the key booleans are true then moving
    //the character based on the keys
    if(leftDown){
        mcMain.x -= mainSpeed;
    }
    if(upDown){
        mcMain.y -= mainSpeed;
    }
    if(rightDown){
        mcMain.x += mainSpeed;
    }
    if(downDown){
        mcMain.y += mainSpeed;
    }
    //keeping the main character within bounds
    if(mcMain.x <= 0){
        mcMain.x += mainSpeed;
    }
    if(mcMain.y <= 0){
        mcMain.y += mainSpeed;
    }
    if(mcMain.x >= stage.stageWidth - mcMain.width){
        mcMain.x -= mainSpeed;
    }
    if(mcMain.y >= stage.stageHeight - mcMain.height){
        mcMain.y -= mainSpeed;
    }
    //Incrementing the cTime

    //checking if cTime has reached the limit yet
    if(cTime < cLimit){
        cTime ++;
    } else {
        //if it has, then allow the user to shoot
        shootAllow = true;
        //and reset cTime
        cTime = 0;
    }

    //adding enemies to stage
    if(enemyTime < enemyLimit){
        //if time hasn't reached the limit, then just increment
        enemyTime ++;
    } else {
        //defining a variable which will hold the new enemy
        var newEnemy = new Enemy();
        //making the enemy offstage when it is created
        newEnemy.y = -1 * newEnemy.height;
        //making the enemy's x coordinates random
        //the "int" function will act the same as Math.floor but a bit faster
        newEnemy.x = int(Math.random()*(stage.stageWidth - newEnemy.width));
        //then add the enemy to stage
        addChild(newEnemy);
        //and reset the enemyTime
        enemyTime = 0;
    }
    //updating the score text
    txtScore.text = 'Score: '+score;
}
//this listener will listen for down keystrokes
stage.addEventListener(KeyboardEvent.KEY_DOWN, checkKeysDown);
function checkKeysDown(event:KeyboardEvent):void{
    //making the booleans true based on the keycode
    //WASD Keys or arrow keys
    if(event.keyCode == 37 || event.keyCode == 65){
        leftDown = true;
    }
    if(event.keyCode == 38 || event.keyCode == 87){
        upDown = true;
    }
    if(event.keyCode == 39 || event.keyCode == 68){
        rightDown = true;
    }
    if(event.keyCode == 40 || event.keyCode == 83){
        downDown = true;
    }

    //checking if the space bar is pressed and shooting is allowed
    if(event.keyCode == 32 && shootAllow){
        //making it so the user can't shoot for a bit
        shootAllow = false;
        //declaring a variable to be a new Bullet
        var newBullet:Bullet = new Bullet();
        //changing the bullet's coordinates
        newBullet.x = mcMain.x + mcMain.width/2 - newBullet.width/2;
        newBullet.y = mcMain.y;
        //then we add the bullet to stage
        bulletContainer.addChild(newBullet);
    }
}
//this listener will listen for keys being released
stage.addEventListener(KeyboardEvent.KEY_UP, checkKeysUp);
function checkKeysUp(event:KeyboardEvent):void{
    //making the booleans false based on the keycode
    if(event.keyCode == 37 || event.keyCode == 65){
        leftDown = false;
    }
    if(event.keyCode == 38 || event.keyCode == 87){
        upDown = false;
    }
    if(event.keyCode == 39 || event.keyCode == 68){
        rightDown = false;
    }
    if(event.keyCode == 40 || event.keyCode == 83){
        downDown = false;
    }
}

这是来自 ENEMY 的源代码。

//This is the basic skeleton that all classes must have
package{
    //we have to import certain display objects and events
    import flash.display.MovieClip;
    import flash.events.*;
    //this just means that Enemy will act like a MovieClip
    public class Enemy extends MovieClip{
        //VARIABLES
        //this will act as the root of the document
        //so we can easily reference it within the class
        private var _root:Object;
        //how quickly the enemy will move
        private var speed:int = 5;
        //this function will run every time the Bullet is added
        //to the stage
        public function Enemy(){
            //adding events to this class
            //functions that will run only when the MC is added
            addEventListener(Event.ADDED, beginClass);
            //functions that will run on enter frame
            addEventListener(Event.ENTER_FRAME, eFrame);
        }
        private function beginClass(event:Event):void{
            _root = MovieClip(root);
        }









        private function eFrame(event:Event):void{
            //moving the bullet up screen
            y += speed;
            //making the bullet be removed if it goes off stage
            if(this.y > stage.stageHeight){
                removeEventListener(Event.ENTER_FRAME, eFrame);
                _root.removeChild(this);
            }

            //checking if it is touching any bullets
            //we will have to run a for loop because there will be multiple bullets
            for(var i:int = 0;i<_root.bulletContainer.numChildren;i++){
                //numChildren is just the amount of movieclips within 
                //the bulletContainer.

                //we define a variable that will be the bullet that we are currently
                //hit testing.
                var bulletTarget:MovieClip = _root.bulletContainer.getChildAt(i);


                //now we hit test
                if(hitTestObject(bulletTarget)){
                    //remove this from the stage if it touches a bullet
                    removeEventListener(Event.ENTER_FRAME, eFrame);
                    _root.removeChild(this);
                    //also remove the bullet and its listeners
                    _root.bulletContainer.removeChild(bulletTarget);
                    bulletTarget.removeListeners();
                    //up the score
                    _root.score += 5;
                }
            }

            //hit testing with the user
            if(hitTestObject(_root.mcMain)){
                //losing the game
                _root.gameOver = true;
                _root.gotoAndStop('lose');
            }

            if(_root.gameOver){
                removeEventListener(Event.ENTER_FRAME, eFrame);
                this.parent.removeChild(this);
            }
        }
        public function removeListeners():void{
            this.removeEventListener(Event.ENTER_FRAME, eFrame);
        }
    }
}
4

1 回答 1

0

您的脚本中有几个设计错误:

  • 不要为 root 创建一个字段,因为它不仅是多余的,而且会导致糟糕的设计。此外,删除剪辑时您不会清理(这与删除的内容不同)。
  • _root 可以为空,因为如果我没记错的话,在将 DisplayObject 添加到 DisplayObjectContainer 时也会调度 Event.ADDED。
  • 为每个 Enemy 注册一个 Event.ENTER_FRAME 处理程序。这可能会导致性能问题和 spagetti 代码 - 让容器处理其子级(在您的特定上下文中搜索游戏循环)。

当孩子想要移除自己时,我建议实施一种安全的移除方法。

function remove():void {
  if (parent) parent.removeChild(this); // otherwise an run time error might be thrown
}

以及关于 eFrame 中引发的错误。真的很难说,什么是空:

  • 阶段:仅在 Event.ADDED_TO_STAGE 之后可用
  • _root.bulletContainer:您只是将 _root 输入到 Object,没有提供更多信息
  • _root.mcMain:您只是将 _root 输入到 Object,没有提供更多信息

我只能推荐一种更简洁的编码方法,其中包括强类型

于 2012-12-26T18:10:59.343 回答