LibGDX_7.3: 资源管理器(AssetManager)

本文链接: http://blog.csdn.net/xietansheng/article/details/50188131

LibGDX 基础教程(总目录)

本篇部分参考自官方wiki: https://github.com/libgdx/libgdx/wiki/Managing-your-assets

1. 资源管理器(AssetManager)概述

资源管理器(AssetManager)主要负责统一加载和管理 纹理(Texture)、纹理图集(TextureAtlas)、位图字体(BitmapFont)、音乐(Music)、音效(Sound) 等 assets 文件夹中的资源。

2. 为什么要使用 AssetManager

如果你的游戏非常简单,加载资源不需要很多时间,那么你可以选择不使用 AssetManager,在其他任何情况下都建议使用它。使用 AssetManager 的好处如下所示:

  • 所有资源的加载采用异步加载方式,不阻塞渲染线程,因此在加载资源时可以显示一个正在加载数据的场景(在场景中可使用进度条实时显示加载进度)。
  • AssetManager 对资源使用引用计数。如果 资源A 和 资源B 同时依赖于 资源C,那么 资源C 只有在 资源A 和 资源B 都被释放时才释放。这也就意味着如果同一个资源被加载多次,实际上在内存中只会存在一份实例被共享使用。
  • 在同一个地方存储所有的资源。
  • 可以透明地实现像缓存一样的事物。

3. 创建一个 AssetManager

创建 AssetManager 实例非常简单,直接 new 创建即可:

AssetManager manager = new AssetManager();

这里创建了一个标准的资源管理器,并同时存储所有类型的资源加载器。

注意: AssetManager 和 其他所有的资源(例如 Texture 等)的实例 不能被静态变量引用 ,除非你能够很好的管理它们。比如下面的代码将可能会引起问题:

public static AssetManager assets = new AssetManager();

这在 Android 平台将会导致问题,因为静态变量的生命周期和 LibGDX 应用的生命周期不能保证一定相同。因此你的一个 LibGDX 应用实例提供的 AssetManager 实例有可能会被下一个 LibGDX 应用实例使用,而加载过的资源却不再有效。这通常会导致黑块/缺失的纹理或错误的资源。

在 Android 平台中,甚至会导致同一时间在你的 Activity 中有多个 LibGDX 应用实例被激活,所以即使你妥善处理了生命周期方法也不要认为你是安全的!(See this StackOverflow question for details.)

4. 加载 assets 资源

加载资源时,资源管理器需要知道如何去加载一个明确类型的资源,这个功能通过 AssetLoader(资源加载器)来实现。AssetLoader 是一个抽象类,它有两个实现,分别是 SynchronousAssetLoader(同步资源加载器) 和 AsynchronousAssetLoader(异步资源加载器),前者在渲染线程直接加载,后者在另外的一个线程中加载。

具体资源类型的加载器定义在 com.badlogic.gdx.assets.loaders 包中,下面列出 AssetManager 默认支持加载的部分资源:

  • Texture
  • BitmapFont
  • TextureAtlas
  • Music
  • Sound
  • Pixmap
  • ParticleEffect
  • Skin
  • I18NBundle
  • ……

加载一个指定类型的资源非常简单:

manager.load("data/mytexture.png", Texture.class);
manager.load("data/myfont.fnt", BitmapFont.class);
manager.load("data/mymusic.ogg", Music.class);

调用 load 方法会将资源的加载加入到一个待加载的队列中,然后按照 load 的顺序依次加载。

把所有需要加载的资源都添加到队列后,可以调用下面的方法实时获取加载进度:

// 返回加载进度的百分比
float percent = manager.getProgress();

5. 获取已加载的资源

根据文件名称和指定的类型获取加载后的资源实例:

Texture tex = manager.get("data/mytexture.png", Texture.class);
BitmapFont font = manager.get("data/myfont.fnt", BitmapFont.class);

资源实例必须要加载完毕之后才能获取,可以使用下面方法判读是否加载完毕:

boolean texIsLoaded = manager.isLoaded("data/mytexture.png");
boolean fontIsLoaded = manager.isLoaded("data/myfont.fnt");

也可以在资源全部 load 到队列后,调用下面的等待加载完毕的方法,方法执行完再获取资源:

// 调用这个方法将阻塞线程, 直到待加载队列中的所有资源都加载完毕
manager.finishLoading();

6. 释放资源

通过 AssetManager 加载的资源,不再需要使用到某个资源,要对资源进行释放时,通常不调用资源对象本身的 dispose() 方法进行释放,而是统一由 AssetManager 中的方法进行释放。

释放单个资源:

manager.unload("data/myfont.fnt");

释放所有资源(包括已加载完毕的和已在待加载队列中的):

manager.clear();

释放所有资源(包括已加载完毕的和已在待加载队列中的),并销毁资源管理器(不再需要用到资源管理器时也必须手动销毁):

manager.dispose();

7. 恢复加载场景

在 Android 平台,应用可以被暂停(paused)和恢复(resumed),在这种情况下,管理的像纹理这样的 OpenGL 资源会重新加载,恢复时可能需要一些时间。如果你想在恢复时显示一个正在加载的场景,当创建好一个 AssetManager 后可以做下面这样的设置:

Texture.setAssetManager(manager);

然后在 ApplicationListener.resume() 生命周期方法中切换到正在加载的场景,并且再一次调用 AssetManager.update() 方法直到一切恢复正常。

如果你没有做 Texture.setAssetManager(manager) 的操作,通常纹理的管理机制会发挥作用自动处理,所以你不需要担心任何事情。

8. 代码示例: AssetManager 在代码中的使用

为了方便演示不再引入资源,这里只演示前面章节中常用的两张图片(badlogic.jpglogo.png,直接放到 assets 文件夹下)的加载。

package com.libgdx.test;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

/** * 游戏主程序的启动入口类 */
public class MainGame extends ApplicationAdapter {

    // 资源在 assets 文件夹中的相对路径
    private static final String BADLOGIC = "badlogic.jpg";
    private static final String LOGO = "logo.png";

    private SpriteBatch batch;

    private AssetManager manager;

    private Texture badlogicTexture;
    private Texture logoTexture;

    @Override
    public void create() {
        batch = new SpriteBatch();

        // 创建资源管理器
        manager = new AssetManager();

        // 加载资源
        manager.load(BADLOGIC, Texture.class);
        manager.load(LOGO, Texture.class);

        // 阻塞线程, 等待资源加载完毕
        manager.finishLoading();

        // 加载完毕后获取资源实例
        badlogicTexture = manager.get(BADLOGIC, Texture.class);
        logoTexture = manager.get(LOGO, Texture.class);
    }

    @Override
    public void render() {
        // 白色清屏
        Gdx.gl.glClearColor(1, 1, 1, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        batch.begin();

        batch.draw(badlogicTexture, 0, 0);
        batch.draw(logoTexture, 10, 300);

        batch.end();
    }

    @Override
    public void dispose() {
        // 当应用退出时释放资源
        if (manager != null) {
            /* * 释放所有资源, 并销毁 AssetManager。 * * 注意: 本例中的 Texture 通过 AssetManager 进行管理, * 因此这里不需要再调用 Texture 的 dispose() 方法。 */
            manager.dispose();
        }
    }

}

你可能感兴趣的:(跨平台,游戏开发,libgdx)