今日のlibGDX(20150630):リソースの管理 AssetManager

今日のlibGDX目次

http://snoopopo.hatenablog.com/entry/2015/04/27/220545

今日のテーマ:リソースの管理 AssetManager

qiita.com

だいぶ遅くなったけど、ついてく。今回も上の記事を参考にやっていきます。

公式のWikiだとこのへん↓

https://github.com/libgdx/libgdx/wiki/Managing-your-assets

AssetManager てなに

com.badlogic.gdx.assets.AssetManager にいます。

今いまやっているものでは Music, Sound, TextureAtlas(またはTexture) クラスを使っていて、 これらリソース郡を管理してくれるものみたい。

管理といっているのは、同じリソースを何度も読み込まないようにしたり…という意味です。

さっそく使ってみる

ゲーム起動時に実行されるcreate()でリソースをロードしている部分です。

   private void loadResource() {
        
        assetMng = new AssetManager();
        
        // imgae.
        assetMng.load(PATH_IMG_GAME, TextureAtlas.class);
        assetMng.load(PATH_IMG_MAIN, TextureAtlas.class);
        
        // sound.
        assetMng.load(PATH_SE_ENTER, Sound.class);
        assetMng.load(PATH_SE_GAMEOVER, Sound.class);
        
        //bgm.
        assetMng.load(PATH_BGM, Music.class);
    }

loadに渡す2番目の引数のクラスは、Sound, Music, Texture, TextureAtlas 以外にも AssetManagerのコンストラクタインスタンス生成してるクラスがデフォルトで使えるし、自分でAssetLoader実装して作ることもできる。Wikiにも書いてあった.

↓ロードしたものを使ってるところ

TextureAtlas gameResource = assetMng.get(PATH_IMG_GAME, TextureAtlas.class);
title = new Image(gameResource.findRegion("title"));
title.setPosition(0, 360);

getするときにクラス渡してあげないと、Objectでとれてしまってキャストする必要があったので指定しています。

捨てるところ↓

   @Override
    public void dispose () {
        assetMng.dispose();
    }

unloadで一つずつ消す場面がよくわかんなかったので、今いまはdisposeで全消ししてしまおう。

20150716 add ------

unloadでひとつづつ消すのはメモリの要領の問題のようだ。

上の例だとdisposeが呼ばれるのは、ゲームを閉じたときなので、起動から1回しか呼ばれないことになる。

その間ゲーム全体のリソースをロードしたままにしておくのは、要領の問題的に厳しい。(少なければ大丈夫とかそういう話になってしまう)

なので、不要のものはunloadするというのが、よさそう。

「非同期でロードされます」の意味

「NowLoading…」とかゲームでよくありますが、

別スレッドで読み込んでいる間にもう片方のスレッドが「NowLoading…」を描画している、のような動きをしているはずでマルチスレッドになっています。 こういう動きのことを非同期というみたい。ゲームの基本的なはなしっぽい…

そうしないと、リソースをロードしている間にほかの動作もできない(NowLoadingも出せない)。

別のスレッドが読み込んでいるということは、 そのスレッドが読み込み完了しているかどうかを使う側は意識しないといけないことになる。

というのが以下のメソッドたち。

AssetManager#finishLoading();

これはロードするまで、次の処理を実行しなくて、

assetMng.finishLoadingAsset(PATH_IMG_GAME);

これも引数で指定したものがロードされてるまで次の処理を実行しない。=よってこれが長いゲームが更新されない時間ができておかしくなる。

なので、updateメソッドで拾って、NowLoading出して、終わったタイミングで使うようにすればよい!

   if (!assetMng.update()){
        System.out.println("now loading");
    } else {          
        TextureAtlas gameResource = assetMng.get(PATH_IMG_GAME, TextureAtlas.class);
        title = new Image(gameResource.findRegion("title"));
        title.setPosition(0, 360);
        // ...
    }

ということと理解したけど、実際ゲームに組み込むといろいろ出る(最初にcreateでリソースのロードしてるけど、NowLoadingとか出すならゲームループの中でやらないと…なので、render側に持ってくとかしないといけないね)ので、E.のほうでやってみることにする。