Инициализировать активы после предварительной загрузки - PullRequest
0 голосов
/ 24 декабря 2011

Всякий раз, когда я экспортирую .swf-файл моей Flash-игры, я получаю "TypeError: Error #1009: Cannot access a property or method of a null object reference." вместе с Runtime Shared Library Preloading Warning для моего прелоадера. Моя временная шкала организована так, что первый и третий кадры пусты вместе с командой stop(); в слое Actions. Второй кадр содержит один MovieClip, который содержит все мои экспортированные активы, которые будут инициализированы в третьем кадре временной шкалы. Ни один из моих активов, кроме предварительного загрузчика, не экспортируется в первом кадре. Какие изменения я должен внести в мой класс документов, чтобы инициализировать ресурсы в третьем фрейме?

Класс документа:

package com.gameEngine.documentClass
{
    import flash.events.*;
    import flash.display.*;
    import flash.geom.Point;
    import com.gameEngine.assetHolders.*;
    import com.gameEngine.assetHolders.Levels.*;

    public class Document extends MovieClip
    {
        private static var _document:Document;
        private var preloader:Preloader;
        public var mcMain:Player;
        public var restartButton:RestartButton;
        public var spawnArea:SpawnArea;
        public var level_1:Level_1;
        public var level_2:Level_2;
        public var level_3:Level_3;

        public function Document()
        {
            addEventListener(Event.ADDED_TO_STAGE, init);
            _document = this;
            preloader = new Preloader(390, this.loaderInfo);
            this.addChild(preloader);
            preloader.addEventListener("loadComplete", loadAssets);
            preloader.addEventListener("preloaderFinished", showLogo);
            mcMain = new Player(this);
            restartButton = new RestartButton(this);
            spawnArea = new SpawnArea();
            level_1 = new Level_1(this);
            level_2 = new Level_2(this);
            level_3 = new Level_3(this);
            this.addChild(restartButton);
            this.addChild(spawnArea);
            this.preloader.x = 400;
            this.preloader.y = 250;
            restartButton.x = 822.95;
            restartButton.y = 19;
            spawnArea.x = 400;
            spawnArea.y = 250;
            trace ("Document Class Initialized");
            // constructor code
        }
        public static function getInstance():Document
        {
            return _document;
        }
        private function loadAssets(event:Event):void
        {
            this.play();
        }
        private function showLogo(event:Event):void
        {
            this.removeChild(preloader);
        }
        public function init(event:Event)
        {
            if (stage.contains(spawnArea))
            {
                addChild(mcMain);
            }
            mcMain.x = spawnArea.x;
            mcMain.y = spawnArea.y;
        }
    }
}

Класс Preloader:

package com.gameEngine.assetHolders
{
    import com.gameEngine.documentClass.*;
    import flash.display.*;
    import flash.events.*;

    public class Preloader extends MovieClip
    {
        private var fullWidth:Number;
        public var loaderInfo:LoaderInfo;

        public function Preloader(fullWidth:Number = 0, loaderInfo:LoaderInfo = null)
        {
            this.fullWidth = fullWidth;
            this.loaderInfo = loaderInfo;

            addEventListener(Event.ENTER_FRAME, checkLoad);
        }

        private function checkLoad (event:Event):void
        {
            if (loaderInfo.bytesLoaded == loaderInfo.bytesTotal && loaderInfo.bytesTotal != 0)
            {
                dispatchEvent(new Event("loadComplete"));
                phaseOut();
            }

            updateLoader(loaderInfo.bytesLoaded / loaderInfo.bytesTotal);
        }

        private function updateLoader(num:Number):void
        {
            progressBar.width = num * fullWidth;
        }

        private function phaseOut():void
        {
            removeEventListener(Event.ENTER_FRAME, checkLoad);
            progressBar.gotoAndPlay(2);
            if (progressBar.currentFrame == progressBar.totalFrames)
            {
                phaseComplete();
            }
        }

        private function phaseComplete() : void
        {
            dispatchEvent(new Event("preloaderFinished"));
        }
    }
}

1 Ответ

1 голос
/ 24 декабря 2011

У вас здесь много условий для гонки. Многие из этих событий могут происходить в относительно случайное время по отношению друг к другу. , , Вы должны думать асинхронно. То есть не может быть предположения , что какой-либо объект существует. Например, в Document.init() вы проверяете, существует ли spawnArea, но почти гарантировано, что в этот момент это не так, и вы никогда не проверяете его снова.

Не внося каких-либо конкретных изменений, я могу порекомендовать общее решение. Для любого объекта (objB), который вы хотите загрузить после загрузки другого объекта (objA), создайте objB в обработчике objA ADDED_TO_STAGE. Простым примером будет:

var objA:Whatever;
var objB:WhateverElse;

[...]

objA = new Whatever();
objA.addEventListener(Event.ADDED_TO_STAGE, objAAddedHnd);

[...]

public function objAAddedHnd(event:Event)
{
    // remove the event, if no longer needed:
    objA.removeEventListener(Event.ADDED_TO_STAGE, objAAddedHnd);

    objB = new WhateverElse();
    objB.addEventListener(Event.ADDED_TO_STAGE, objBAddedHnd);
}

[...]

public function objBAddedHnd(event:Event)
{
    // remove the event, if no longer needed:
    objB.removeEventListener(Event.ADDED_TO_STAGE, objBAddedHnd);

    // and so on . . .
}

На данный момент, это показывает, что вам нужно будет планировать график создания объекта.

...