actionscript-3 - 运行时加载外部资源并在 ActionScript 3 中重用预加载的资源?

标签 actionscript-3 flex3 asset-management

我正在创建一个 2d Flash 游戏(用 flex/actionscript 3 编码),在需要时下载资源。目前我的设置如下:

AssetLoader.as

package
{
    import flash.display.Loader;
    import flash.net.URLRequest;

    public class AssetLoader extends Loader
    {
        //set vars
        private var url:String = "http://test.com/client/assets/";

        public function AssetLoader(url:String)
        {
            Logger.log("AssetLoader request: " + this.url + url);
            var request:URLRequest = new URLRequest(this.url + url);
            this.load(request);
        }
    }
}

然后,在我想要加载资源的地方执行以下操作:

var asset:AssetLoader = new AssetLoader("ships/" + graphicId + ".gif");
asset.contentLoaderInfo.addEventListener(Event.COMPLETE, onShipAssetComplete, false, 0, true);

private function onShipAssetComplete(event:Event):void
{
    var loader:Loader = Loader(event.target.loader);
        shipImage = Bitmap(loader.content);
        shipImage.smoothing = true;
        addChild(shipImage);
}

问题是,此方法不会检查已下载的资源,因此它会在第二次请求相同资源时重新下载它们(我认为)。

因此,我需要一个存储所有下载资源的数组,并根据请求检查该资源的名称是否存在于数组中。因此,如果已经下载了该资源,则必须返回内存中的该资源,而不是重新下载。

我可以将 assetloader 设为静态类,但我必须等待图像下载完成后触发事件 - 所以我不能简单地让静态函数返回相应的图像。知道我应该怎么做吗?

编辑评论后的尝试:

package
{
    import flash.display.Loader;
    import flash.events.Event;
    import flash.net.URLRequest;

    public final class AssetManager
    {
        private static var assets:Object = {};
        private static var preUrl:String = Settings.ASSETS_PRE_URL;

        public static function load(postUrl:String):*
        {
            if (assets[postUrl])
            { //when the asset already exists
                //continue
            }
            else
            { //the asset still has to be downloaded
                var request:URLRequest = new URLRequest(preUrl + postUrl);
                var loader:Loader = new Loader();
                loader.load(request);
                loader.contentLoaderInfo.addEventListener(Event.COMPLETE, 
                function(event:Event):void
                {
                    var loader:Loader = Loader(event.target.loader);
                    assets[postUrl] = loader.content;
                }, false, 0, true); 
            }
        }
    }
}

EDIT2:另一次尝试

package
{
    import flash.display.Loader;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.net.URLRequest;

    public final class AssetManager
    {
        private static var assets:Object = {};
        private static var preUrl:String = Settings.ASSETS_PRE_URL;

        public static function load(postUrl:String):*
        {
            if (assets[postUrl])
            { //the asset already exists
                var dispatcher:EventDispatcher = new EventDispatcher();
                dispatcher.dispatchEvent(new CustomEvent(CustomEvent.LOAD_COMPLETE, assets[postUrl]));
            }
            else
            { //the asset still has to be downloaded
                var request:URLRequest = new URLRequest(preUrl + postUrl);
                var loader:Loader = new Loader();
                loader.load(request);
                loader.contentLoaderInfo.addEventListener(Event.COMPLETE, 
                function(event:Event):void
                {
                    var loader:Loader = Loader(event.target.loader);
                    assets[postUrl] = loader.content;
                    var dispatcher:EventDispatcher = new EventDispatcher();
                    dispatcher.dispatchEvent(new CustomEvent(CustomEvent.LOAD_COMPLETE, assets[postUrl]));
                }, false, 0, true); 
            }
        }
    }
}

然后,我尝试以下操作:

var asset:AssetManager = AssetManager.load("ships/" + graphicId + ".gif");
            asset.addEventListener(CustomEvent.LOAD_COMPLETE, onShipAssetComplete, false, 0, true);

但是出现错误,“通过静态 AssetManager 类型的引用未定义方法 addEventListener”(粗略翻译)。

最佳答案

您可以在 AssetLoader 类中添加一个静态对象(用作字典,其中 Assets 的 url 作为键, Assets 的内容作为值),同时继续以正确的方式使用该类现在。

private static var assets:Object = {};

不同之处在于,如果先前已请求过内容的 URL,则您的类需要检查该静态对象。如果有,请立即分派(dispatch)完整事件。如果没有,请按照正常例程操作,并且不要忘记使用新加载的资源填充静态对象。



更新:

这是一个简单的例子来说明我的意思。我还没有时间测试这个,但它应该可以工作。

注意: 您必须调用您创建的 AssetLoader 实例的 loadAsset() 方法才能实际加载资源。这与我们扩展的 Loader 类的工作方式一致。

您应该始终在调用 loadAsset() 方法之前添加所有事件监听器。在您的问题中,您从构造函数中调用 load() 方法,然后才添加 Event.COMPLETE 的事件监听器。这可能会产生奇怪的结果。

代码如下:

package
{
  import flash.display.Loader;
  import flash.events.Event;
  import flash.net.URLRequest;


  public class AssetLoader extends Loader
  {
    private static const BASE_URL:String = 'http://test.com/client/assets/';

    public static var storedAssets:Object = {};

    private var assetURL:String;
    private var urlRequest:URLRequest;
    private var cached:Boolean = false;


    public function AssetLoader(url:String):void
    {
      trace('Loading: ' + url);
      assetURL = url;

      if (storedAssets[assetURL] != null)
      {
        cached = true;
        trace('Cached');
      }
      else
      {
        trace('Loading uncached asset');
        urlRequest = new URLRequest(BASE_URL + assetURL);
        contentLoaderInfo.addEventListener(Event.COMPLETE, OnAssetLoadComplete);
      }
    }

    public function loadAsset():void
    {
      if (cached)
        loadBytes(storedAssets[assetURL]);
      else
        load(urlRequest);
    }

    private function OnAssetLoadComplete(event:Event):void
    {
      storedAssets[assetURL] = contentLoaderInfo.bytes;
      trace('Loaded ' + contentLoaderInfo.bytesLoaded + ' bytes');
    }

  }

}


更新2:

以下是如何使用上面的类:

var assetLdr:AssetLoader = new AssetLoader("ships/" + graphicId + ".gif");
assetLdr.contentLoaderInfo.addEventListener(Event.COMPLETE, onShipAssetComplete);
assetLdr.loadAsset();

private function onShipAssetComplete(event:Event):void
{
    var shipImage:Bitmap = Bitmap(event.target.loader.content);
    // Do stuff with shipImage
}

关于actionscript-3 - 运行时加载外部资源并在 ActionScript 3 中重用预加载的资源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1263177/

相关文章:

java - 搜索索引函数不返回值

apache-flex - Adobe AIR - 读取 AIR 包外同一文件夹中的文件

database - flex 独立应用程序使用哪个数据库?

apache-flex - 使用Flex使本地SQLite数据库与实时服务器数据库保持同步

version-control - 如何在 DVCS 中适当管理大型艺术 Assets ?

javascript - HtmlWebpackPlugin - 在正文中的特定位置注入(inject) js

php - #2101 : The String passed to URLVariables. decode() 必须是包含名称/值对的 URL 编码查询字符串

actionscript-3 - 柔性 : how to control Spark datagrid header-text alignment?

apache-flex - Flex 拖放 : Detecting when all data has been moved from source to destination