2

アセットが必要なときにダウンロードされる2Dフラッシュゲーム(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);
}

つまり、このメソッドはすでにダウンロードされたアセットをチェックしないため、同じアセットが2回目に要求されたときにそれらを再ダウンロードします(私は思います)。

したがって、必要なのは、ダウンロードされたすべてのアセットが格納されている配列です。要求に応じて、このアセットの名前が配列に存在するかどうかがチェックされます。したがって、すでにダウンロードされている場合は、メモリからそのアセットを再ダウンロードするのではなく、返す必要があります。

アセットローダーを静的クラスにすることもできますが、画像のダウンロードが完了したらイベントが発生するのを待つ必要があります。そのため、静的関数に対応する画像を返すようにすることはできません。私がこれをどのように行うべきか考えていますか?

コメント後の試みのために編集:

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」というエラーが発生します(大まかに翻訳されています)。

4

3 に答える 3

1

AssetLoaderクラスに静的オブジェクト(アセットのURLをキーとして、アセットのコンテンツを値として持つディクショナリとして使用)を追加すると同時に、現在使用している方法でクラスを使用し続けることができます。

private static var assets:Object = {};

違いは、コンテンツのURLがすでに要求されている場合、クラスはその静的オブジェクトをチェックする必要があるということです。ある場合は、イベント全体をすぐにディスパッチします。そうでない場合は、通常のルーチンに従い、静的オブジェクトに新しくロードされたアセットを設定することを忘れないでください。



アップデート:

これは私が意味したことの簡単な例です。これをテストする時間がありませんでしたが、動作するはずです。

注: アセットを実際にロードするには、作成した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
}
于 2009-08-11T22:11:19.387 に答える
1

おそらく、バルクローダーを確認する必要があります。それはあなたがやろうとしているようなことをします。本当にカスタムソリューションを使用したい場合、それは優れた参考資料になりますが、なぜ車輪の再発明を行うのでしょうか。

タイラー。

于 2009-08-11T22:11:24.473 に答える
1

これは、resourceIdをキャプチャするためのloadコマンドの変更です。

public function load(postUrl:String):*
{
    var index:int;
    if ((index = assetExists(postUrl)) != -1)
    {
        dispatchEvent(new CustomEvent(CustomEvent.LOAD_COMPLETE, asset[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)
        {
            // NOTE: not sure on scoping here ...
            // pretty sure you're this will be the Loader
            // if not just read it off the event like you were before
            assets[postUrl] = content;
            dispatchEvent(new CustomEvent(CustomEvent.LOAD_COMPLETE, asset[postUrl]));
        }, false, 0, true);
    }
}

/* In a new file */
public class CustomEvent extends Event
{
    public static const LOAD_COMPLETE:String = "CustomEvent_LoadComplete";

    // If you know the type you should use it (e.g. Sprite/DisplayObject)
    public var content:*;

    public function CustomEvent(type:String, _content:*)
    {
        content = _content;
        super(type);
    }
}

注:イベントの子孫を作成するときは、メソッドtoStringcloneメソッドもオーバーライドする必要があります。また、weakReferencesなどを通過したい場合があるため、コンストラクターをだましました。

于 2009-08-12T13:48:21.163 に答える