同步图像加载动作脚本3闪存

时间:2014-03-06 17:32:42

标签: actionscript-3 flash flashdevelop

我的flash / as3应用程序出了问题。我创造了大部分内容,目前我正努力让我的外部资源发挥作用​​。

我的应用程序由一个Controller类组成,它控制一个应用程序流。在开始时它初始化AppInitializer类,它加载/生成整个应用程序内容(这是一个简单的点'n'click游戏)。

在AppInitializer中,我创建了游戏中可用的项目数组。 Item的构造函数将path作为参数(String)传递给资源(image)。然后,在构造函数内部,我调用我的AssetsLoader类的静态方法,如下所示:

public static function loadImage(path:String):BitmapData
    {
        completed = false;
        var loader:Loader = new Loader();
        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event){completed = true;
        trace("Loading completed");
        e.target.removeEventListener(Event.COMPLETE, check);});
        if (path == "")
            loader.load(new URLRequest("images/default.png"));
        else
            loader.load(new URLRequest("images/" + path));
        //while (!completed);
        var image:Bitmap = new Bitmap((loader.content as BitmapData));
        return image.bitmapData;
    }

其中completed是AssetsLoader的静态变量。

第一个问题是:我在一行中创建了许多Item对象,所以方法loadImage不应该是静态的我猜(与完成的变量相同),因为这可能会在加载时引起问题。

第二个问题是:目前我无法返回bitmapData(或位图,这并不重要),因为return语句将始终返回null - 因为资源是异步加载的,并且未在时间申请到达退货声明。如果我取消注释wile循环,则永远不会调用complete事件。

我想请更多有经验的ActionScript开发人员指出任何需要对我的应用程序的其余部分进行微小更改的解决方案,并解决这些问题。 (我认为通过对加载器使用某种排队方法可以消除第一个问题,但到目前为止,我已经遇到了第二个问题并且没有可能的解决方案)。

我还可以考虑改变逻辑,因此我可以将所有图像资源预加载到“某处”,之后只为我的目的复制这些图像。如果这更容易做到。

2 个答案:

答案 0 :(得分:0)

超级,你用while评论疯狂的代码行;) 在这里,简单的QueueLoader(它逐个加载项目,当您将项目添加到队列时,您可以将项目的 id 存储在队列中),这将帮助您完成任务:

package {

    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;

    public class StackOverflow extends Sprite {

        public function StackOverflow() {
            addEventListener(Event.ADDED_TO_STAGE, onAdded);
        }

        private function onAdded(e:Event):void {
            removeEventListener(Event.ADDED_TO_STAGE, onAdded);

            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;

            setup();
        }

        private function setup():void {
            //Store somewhere reference on QueueLoader to reuse it, and use queue
            var loader:QueueLoader = new QueueLoader();
            loader.addEventListener(QueueLoaderEvent.COMPLETE, onCompleteItem);
            //Add as many images to load as you want, and store Id's of items that
            //will be loaded in future, if you want...
            loader.addItem("someUrl1");
            loader.addItem("someUrl2");
            var importantId:int = loader.addItem("someUrl3");
            loader.addItem("someUrl4");
            loader.addItem("someUrl6");
        }

        private function onCompleteItem(e:QueueLoaderEvent):void {
            trace("Item loaded");
        }
    }
}

import flash.display.Loader;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.net.URLRequest;

internal class QueueLoader extends EventDispatcher {
    private var _list:Array;
    private var _cursor:int;
    private var _loading:Boolean;

    public function QueueLoader(target:IEventDispatcher = null) {
        super(target);
        _list = [];
    }

    public function addItem(url:String):int {
        var item:Object = {url: url, id: ++_cursor};
        _list.push(item);
        loadNext();
        return item.id;
    }

    override public function dispatchEvent(evt:Event):Boolean {
        if (hasEventListener(evt.type) || evt.bubbles) {
            return super.dispatchEvent(evt);
        }
        return true;
    }

    protected function loadNext():void {
        if (_list.length > 0 && !_loading) {
            var loader:Loader = new Loader();
            var data:Object = _list[0];
            var request:URLRequest = new URLRequest(data.url);
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete, false, 0, true);
            loader.load(request);
            _loading = true;
        }
    }

    private function onComplete(e:Event):void {
        var data:Object = _list.shift();
        data.content = e.currentTarget.content;
        dispatchEvent(new QueueLoaderEvent(QueueLoaderEvent.COMPLETE, data.id, data));
        _loading = false;
        loadNext();
    }
}

internal class QueueLoaderEvent extends Event {

    public static const COMPLETE:String = "queueLoaderEventComplete";

    private var _id:int;
    private var _data:Object;

    public function QueueLoaderEvent(type:String, $id:int, $data:Object, bubbles:Boolean = false, cancelable:Boolean = false) {
        _id = $id;
        _data = $data;
        super(type, bubbles, cancelable);
    }

    override public function clone():Event {
        return new QueueLoaderEvent(type, id, data, bubbles, cancelable);
    }

    public function get id():int {
        return _id;
    }

    public function get data():Object {
        return _data;
    }
} 

你的 loadImage mehtod会看到结尾:

public static function loadImage(path:String):int
{
    return queueLoader.addItem(path);
}

答案 1 :(得分:0)

正如我在评论中所建议的那样,最小的更改解决方案可能只是将一个函数作为loadImage()参数的一部分进行调用。这称为回调函数,它看起来像这样:

首先创建回调函数:

public function addImage( bitmapData:BitmapData ):void {
    //do something with the bitmapData returned
}

下一步调整您的loadImage()本地函数,以便在事件完成时使用位图数据进行回调:

public static function loadImage(path:String, callback:Function):BitmapData {
    completed = false;
    var loader:Loader = new Loader();
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event){completed = true;
    trace("Loading completed");
    var image:Bitmap = new Bitmap((loader.content as BitmapData));
    callback( image ); //call the callback with the bitmap
    e.target.removeEventListener(Event.COMPLETE, check);});
    if (path == "")
        loader.load(new URLRequest("images/default.png"));
    else
        loader.load(new URLRequest("images/" + path));
}

然后只需拨打loadImage()这样的电话:

loadImage( myPathToImage, addImage );

这是一个简单的解决方案,完全符合你的需要。