问题
I've just tried to implement a menu system I saw a tutorial onto a game that I'm working on and it was all smooth sailing until I've now encountered a problem with the stage being set to null and I don't know how to stop it. The line that keeps breaking it is in the AvoiderGame.as file and is the stage.addEventListener(Event.ADDED_TO_STAGE, init);
it keeps returning the following error
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at AvoiderGame()[M:\Users\Andy\Documents\Programming For Fun\Flash\Tutorial - Avoider Game\Classes\AvoiderGame.as:29]
at States/changeState()[M:\Users\Andy\Documents\Programming For Fun\Flash\Tutorial - Avoider Game\States.as:26]
at mainMenu/brnP_Button()[M:\Users\Andy\Documents\Programming For Fun\Flash\Tutorial - Avoider Game\Classes\mainMenu.as:34]
Currently the way I've programmed my game is so that it starts in States.as which contains the following code.
package
{
import flash.display.*;
import flash.system.fscommand;
public class States extends MovieClip
{
public function States()
{
changeState(null, "menu");
}
public function changeState (currentState, nextState)
{
if (currentState != null)
{
removeChild(currentState);
}
switch(nextState)
{
case "menu": var mm:mainMenu = new mainMenu(changeState);
addChild(mm);
break;
case "game": var g:AvoiderGame = new AvoiderGame(changeState);
addChild(g);
break;
case "exit": fscommand("quit");
break;
}
}
}
}
From there it will go into mainMenu.as until the user clicks play - inside mainMenu.as is the following code
package
{
import flash.display.*;
import flash.events.*;
public class mainMenu extends MovieClip
{
var theCallBackFunction:Function;
public function mainMenu(callBack)
{
var Background:gameBackground;
Background = new gameBackground();
addChild(Background);
var btnPlay:mmPlay = new mmPlay();
btnPlay.addEventListener(MouseEvent.MOUSE_DOWN, brnP_Button);
btnPlay.x = width/2;
btnPlay.y = height/2 - btnPlay.height/2;
addChild(btnPlay);
var btnExit:mmExit = new mmExit();
btnExit.addEventListener(MouseEvent.MOUSE_DOWN, brnE_Button);
btnExit.x = width/2;
btnExit.y = height/2 - btnExit.height/2;
btnExit.y += btnExit.height + 4;
addChild(btnExit);
theCallBackFunction = callBack;
}
public function brnP_Button(e:MouseEvent)
{
theCallBackFunction(this, "game");
return;
}
public function brnE_Button(e:MouseEvent)
{
theCallBackFunction(this, "exit");
return;
}
}
}
Now this is where it goes wrong - it goes into AvoiderGame.as and it then kicks me back with an error which I don't know how to fix - Could anyone advise me on how to fix it?
package
{
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.Event;
import flash.events.TimerEvent;
import com.freeactionscript.CollisionTest;
import flash.display.Stage;
public class AvoiderGame extends MovieClip
{
var theCallBackFunction:Function;
public static var enemyArray:Array;
public var enemy:Enemy
public var Background:gameBackground;
public var avatar:Avatar;
public var gameTimer:Timer;
private var _collisionTest:CollisionTest;
private var numStars:int = 80;
private var fireTimer:Timer; //causes delay between fires
private var canFire:Boolean = true; //can you fire a laser
public function AvoiderGame(callBack)
{
stage.addEventListener(Event.ADDED_TO_STAGE, init);
theCallBackFunction = callBack;
}
private function init(e:Event):void
{
Background = new gameBackground();
addChild(Background);
enemyArray = new Array();
var enemy = new Enemy(Math.round(1 + (500 - 1) * Math.random()), - 2, stage);
enemyArray.push(enemy);
addChild(enemy);
avatar = new Avatar(stage);
addChild(avatar);
avatar.x = stage.stageWidth / 2;
avatar.y = stage.stageHeight / 2;
for (var i:int = 0; i < numStars; i++)
{
stage.addChildAt(new Star(stage), 1);
}
_collisionTest = new CollisionTest();
gameTimer = new Timer(25);
gameTimer.addEventListener(TimerEvent.TIMER, onTick);
gameTimer.start();
fireTimer = new Timer(300, 1);
fireTimer.addEventListener(TimerEvent.TIMER, fireTimerHandler, false, 0, true);
fireTimer.start();
}
public function onTick(timerEvent:TimerEvent):void
{
if (Math.random() < 0.1)
{
trace('array length: ', AvoiderGame.enemyArray.length);
enemy = new Enemy(Math.round(1 + (500 - 1) * Math.random()), - 28, stage);
enemyArray.push(enemy);
addChild(enemy);
}
avatar.UpdateAvatar(canFire);
if (canFire == true)
{
canFire = false;
fireTimer.start();
}
avatar.StayOnScreen();
for each (var enemy:Enemy in enemyArray)
{
enemy.moveDown();
enemy.StayOnScreen();
if (_collisionTest.complex(enemy, avatar))
{
gameTimer.stop();
}
}
}
private function fireTimerHandler(e:TimerEvent) : void
{
//timer ran, we can fire again.
canFire = true;
}
}
}
回答1:
public function AvoiderGame(callBack)
{
stage.addEventListener(Event.ADDED_TO_STAGE, init);
theCallBackFunction = callBack;
}
Should be something like
public function AvoiderGame(callBack)
{
this.addEventListener(Event.ADDED_TO_STAGE, init);
theCallBackFunction = callBack;
}
Don't forget to remove the event listener when the init function is called.
回答2:
When a display object is not added to the stage or an other display object already in the display list, stage is null. Event.ADDED_TO_STAGE will be dispatched, when stage is set and available.
回答3:
When you create the AvoiderGame object, it wil fire the constructor. at this time, the object is not added to the stage or any object in the display list, so it will not have any reference to the stage.
You can add a listener to the ADDED_TO_STAGE event or call a custom init
method before adding it to the stage manually.
来源:https://stackoverflow.com/questions/13444408/as3-stage-null