AS3 - Ссылка на этап после внедрения предварительного загрузчика
Я только что закончил основную структуру маленькой игры и сохранил простой прелоадер до последнего. Дурак я.
После многочисленных уроков я нашел этот, который работал для меня - Pre Loader в Flash Builder
Прелоадер работает и игра на сцене, но мгновенно зависает. Любая ссылка на сцену в моем коде LevelOne выдает ошибки. ошибка #1009: невозможно получить доступ к свойству или методу пустой ссылки на объект.
До реализации Preloader в качестве переключателя уровня использовался мой класс приложений (RookiesGame). Каждый уровень содержится в Спрайте. RookiesGame начинается с добавления LevelOne на сцену, затем, когда игрок завершает его, RookiesGame удаляет LevelOne и добавляет LevelTwo на сцену и т. Д.
Классы уровня ссылаются на стадию с помощью переменной _stage.
С тех пор, как я изучил эту структуру, предварительный загрузчик, ставший классом приложений, а RookiesGame - просто еще одним классом, действительно смутил меня. Разве _stage var все еще работает? Можно ли сохранить RookiesGame в качестве переключателя уровня?
В любом случае, главная проблема - ссылка на сцену из классов уровней.
Текущий код:
Preloader Class
Работает нормально, игра начинается.
package
{
import flash.display.DisplayObject;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.utils.getDefinitionByName;
[SWF(width="650", height="450", backgroundColor="#FFFFFF", frameRate="60")]
public class Preloader extends Sprite
{
// Private
private var _preloaderBackground:Shape
private var _preloaderPercent:Shape;
private var _checkForCacheFlag:Boolean = true;
// Constants
private static const MAIN_CLASS_NAME:String = "RookiesGame";
public function Preloader()
{
trace("Preloader: Initialized.")
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
public function dispose():void
{
trace("Preloader: Disposing.")
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
if (_preloaderBackground)
{
removeChild(_preloaderBackground);
_preloaderBackground = null;
}
if (_preloaderPercent)
{
removeChild(_preloaderPercent);
_preloaderPercent = null;
}
}
// Private functions
private function onAddedToStage(e:Event):void
{
trace("Preloader: Added to stage.");
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
stage.scaleMode = StageScaleMode.SHOW_ALL;
stage.align = StageAlign.TOP_LEFT;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(e:Event):void
{
if (_checkForCacheFlag == true)
{
_checkForCacheFlag = false;
if (root.loaderInfo.bytesLoaded >= root.loaderInfo.bytesTotal)
{
trace("Preloader: No need to load, all " + root.loaderInfo.bytesTotal + " bytes are cached.");
finishedLoading();
}
else
beginLoading();
}
else
{
if (root.loaderInfo.bytesLoaded >= root.loaderInfo.bytesTotal)
{
trace("Preloader: Finished loading all " + root.loaderInfo.bytesTotal + " bytes.");
finishedLoading();
}
else
{
var percent:Number = root.loaderInfo.bytesLoaded / root.loaderInfo.bytesTotal;
updateGraphic(percent);
trace("Preloader: " + (percent * 100) + " %");
}
}
}
private function beginLoading():void
{
// Might not be called if cached.
// ------------------------------
trace("Preloader: Beginning loading.")
_preloaderBackground = new Shape()
_preloaderBackground.graphics.beginFill(0x333333)
_preloaderBackground.graphics.lineStyle(2,0x000000)
_preloaderBackground.graphics.drawRect(0,0,200,20)
_preloaderBackground.graphics.endFill()
_preloaderPercent = new Shape()
_preloaderPercent.graphics.beginFill(0xFFFFFFF)
_preloaderPercent.graphics.drawRect(0,0,200,20)
_preloaderPercent.graphics.endFill()
addChild(_preloaderBackground)
addChild(_preloaderPercent)
_preloaderBackground.x = _preloaderBackground.y = 10
_preloaderPercent.x = _preloaderPercent.y = 10
_preloaderPercent.scaleX = 0
}
private function updateGraphic(percent:Number):void
{
// Might not be called if cached.
// ------------------------------
_preloaderPercent.scaleX = percent
}
private function finishedLoading():void
{
var RookiesGame:Class = getDefinitionByName(MAIN_CLASS_NAME) as Class;
if (RookiesGame == null)
throw new Error("Preloader: There is no class \"" + MAIN_CLASS_NAME + "\".");
var main:DisplayObject = new RookiesGame() as DisplayObject;
if (main == null)
throw new Error("Preloader: The class \"" + MAIN_CLASS_NAME + "\" is not a Sprite or MovieClip.");
addChild(main);
dispose();
}
}
}
RookiesGame Class (раньше был классом приложения)
Любые ссылки на stage выдали ошибку # 1009, которая прекратилась, когда я изменил stage.addChild на этот.addChild
С предварительным загрузчиком я еще не дошел до обработчика переключателя уровня, поэтому я не знаю, как будет работать stage.focus!
package
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
public class RookiesGame extends Sprite
{
private var _levelOne:LevelOne;
private var _levelTwo:LevelTwo;
public function RookiesGame()
{
_levelOne = new LevelOne(stage);
_levelTwo = new LevelTwo(stage);
this.addChild(_levelOne);
this.addEventListener("levelOneComplete",levelTwoSwitchHandler);
}
private function levelTwoSwitchHandler(event:Event):void
{
this.removeChild(_levelOne);
_levelOne = null;
this.addChild(_levelTwo);
stage.focus = stage;
}
}
}
LevelOne Class
Много ошибок # 1009. Все, что касается сцены.
Класс огромный, поэтому я выделю проблемные куски.
Ошибка # 1009 при ссылке на сцену при добавлении слушателей клавиатуры.
_stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
_stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
Также # 1009 при обращении к этапу для проверки границ этапа. Не могу просто изменить этап. к этому. больше.
private function checkStageBoundaries(gameObject:MovieClip):void
{
if (gameObject.x < 50)
{
gameObject.x = 50;
}
if (gameObject.y < 50)
{
gameObject.y = 50;
}
if (gameObject.x + gameObject.width > _stage.stageWidth - 50)
{
gameObject.x = _stage.stageWidth - gameObject.width - 50;
}
if (gameObject.y + gameObject.height > _stage.stageHeight - 50)
{
gameObject.y = _stage.stageHeight - gameObject.height - 50;
}
}
Я упоминаю _stage позже в программе, чтобы удалить слушателей событий. Это оно.
_stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
_stage.removeEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
Как я могу сослаться на сцену, без этих ошибок и сохранить RookiesGame в качестве переключателя уровня.
Структура класса LevelOne
Чтобы показать, как я использую (d) _stage.
package
{
//import classes
public class LevelOne extends Sprite
{
//Declare the variables to hold the game objects
//A variable to store the reference to the stage from the application class
private var _stage:Object;
public function LevelOne(stage:Object)
{
_stage = stage;
this.addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
private function addedToStageHandler(event:Event):void
{
startGame();
this.removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
private function startGame():void
{
//Includes _stage references that mess everything up.
}
private function levelCleared():void
{
//When Level finished, dispatch event to tell RookiesGame to switch levels.
dispatchEvent(new Event("levelOneComplete", true));
}
}
}
Извините, если это сбивает с толку, но если вы можете помочь мне сослаться на сцену с помощью классов LevelOne и RookiesGame, это было бы очень признательно.
1 ответ
Вы переходите в нуль stage
в LevelOne
от твоего RookiesGame
учебный класс. Всякий раз, когда вы создаете RookiesGame
сначала будет запущен конструктор, он еще не был добавлен в список отображения, поэтому его унаследованная ссылка на stage
является null
, Что вам нужно сделать, это добавить прослушиватель событий для ADDED_TO_STAGE
в RookiesGame
учебный класс:
package
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
public class RookiesGame extends Sprite
{
private var _levelOne:LevelOne;
private var _levelTwo:LevelTwo;
public function RookiesGame()
{
addEventListener( Event.ADDED_TO_STAGE, onAdded );
}
//added to stage event
private function onAdded( e:Event ):void {
removeEventListener( Event.ADDED_TO_STAGE, onAdded );
_levelOne = new LevelOne(stage);
_levelTwo = new LevelTwo(stage);
this.addChild(_levelOne);
this.addEventListener("levelOneComplete",levelTwoSwitchHandler);
}
...
}
Также, если вы используете addChild()
звать LevelOne
как в addChild(_levelOne)
это имеет свою собственную ссылку на stage
после того, как он был добавлен в список отображения, вам не нужно создавать _stage
переменная для этих классов, если вы добавляете их в список отображения.
Также у вас есть слушатель для ADDED_TO_STAGE
в LevelOne
, где stage
переменная больше не была бы нулевой, так что вы можете удалить переменную класса _stage
полностью.