-1

私はフラッシュの初心者で、現在問題があります。スペースインベーダーのようなゲームを作っています。はじめのうちはよかった。ただし、キャラクターが敵に命中すると、エラーが発生します。

タイプ エラー:

エラー #1009: null オブジェクト参照のプロパティまたはメソッドにアクセスできません。_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

スクリプトにはいくつかの設計エラーがあります。

  • ルートのフィールドを作成しないでください。冗長であるだけでなく、設計の失敗につながるからです。また、クリップが削除されたときにクリーンアップしません (これは削除とは異なります)。
  • 間違っていなければ、DisplayObject が DisplayObjectContainer に追加されたときに Event.ADDED もディスパッチされるため、_root は null である可能性があります。
  • Enemy ごとに Event.ENTER_FRAME ハンドラが登録されます。これにより、パフォーマンスの問題やスパゲッティ コードが発生する可能性があります。コンテナーにその子を処理させます (特定のコンテキストでゲーム ループを検索します)。

子供が自分自身を削除したい場合は、安全な削除メソッドを実装することをお勧めします。

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

そして、eFrame でスローされたエラーについて。nullとは何かを言うのは本当に難しいです:

  • ステージ: Event.ADDED_TO_STAGE の後にのみ利用可能
  • _root.bulletContainer: Object に _root と入力しただけで、それ以上の情報はありません
  • _root.mcMain: オブジェクトに _root と入力しただけで、それ以上の情報はありません

強力な型付けを含むコーディングへのよりクリーンなアプローチのみをお勧めします

于 2012-12-26T18:10:59.343 に答える