【问题标题】:Reloading assets on resume在简历上重新加载资产
【发布时间】:2014-05-01 13:06:34
【问题描述】:

我正在使用 libGDX 框架开发一款 Android 游戏,同时从他们的 wiki 和 Learning Libgdx Game Development 书籍中学习。本书作者定义了一个 Assets 类来使用 AssetManager 加载游戏资源。每次游戏恢复时,资产都需要重新加载,因此他使用对 Assets.intance.init(new AssetManager()) 的调用来重新加载资产并创建新对象来存储纹理引用。

当我在我的游戏中执行此操作时,在恢复之后,我所拥有的只是黑框,其中我有很好的纹理,所以我认为这里的问题是我使用的是旧的参考。我把书中的部分代码放在这里:

AssetManager#init

public void init(AssetManager assetManager) {

    /* Dispose previous asset manager */
    if (this.assetManager != null) {
        this.assetManager.dispose();
    }

    this.assetManager = assetManager;

    assetManager.setErrorListener(this);
    assetManager.load(Constants.TEXTURE_ATLAS, TextureAtlas.class);

    /* Start loading assets and wait until finished */
    assetManager.finishLoading();

    Array<String> assetNames = assetManager.getAssetNames();
    Gdx.app.debug(TAG, "Assets loaded: " + assetNames.size);
    for (String assetName : assetNames) {
        Gdx.app.debug(TAG, "Asset: " + assetName);
    }

    TextureAtlas atlas = assetManager.get(Constants.TEXTURE_ATLAS);

    /* Create game resource objects. Here I get what I need from the atlas */
    player = new AssetPlayer(atlas);
    enemy = new AssetEnemy(atlas);
}

当我创建我的游戏对象时,我使用 Assets.instance.player 和 Assets.instance.enemy 来存储对纹理的引用,就像本书的作者所做的那样,这可能是问题所在。问题是重读这本书后,我不明白他是如何解决这个问题的。

我很确定我可以解决在我的游戏对象中更改引用的问题,但是一切都变得如此混乱。我真正的问题是,我应该如何管理我的游戏中的游戏资产?我一直在寻找很多游戏示例,但其中大多数不使用 AssetManager,而是使用纹理的静态变量。

我应该在游戏对象中保留纹理的引用吗?真的有必要在简历上重新加载资产吗?当所有对象都在不知道游戏何时恢复的 worldController 中时,如何在我的游戏对象中重新加载纹理?

【问题讨论】:

    标签: android libgdx rendering assets


    【解决方案1】:

    据我所知,在这个级别上,您做得正确。您确实需要重新加载纹理,因为您的 OpenGL 上下文丢失了,并且所有指向 OpenGL 内部状态的“指针”都是陈旧的。

    正如您所指出的,因为您的 AssetManager.player 属性指向一个新对象,所以缓存旧指针的任何内容在重新启动后都是陈旧的,这可能是您的问题的根源。 (虽然很难确定。)

    如果您查看 Libgdx SuperJump 演示,他们还将所有资产指针缓存在静态字段中,但请注意,render 调用每次调用都会有效地查找纹理。见WorldRenderer.renderBob()。一种替代方法是在(重新)加载资产后对您的对象进行传递,以让他们“刷新”他们使用的资产的指针。

    【讨论】:

    • 感谢您的回答。我还有一个世界渲染器,但所有游戏对象都有一个渲染方法,所以我在它们的类中保留对它们的纹理的引用(我总是需要一个来存储当前动画)。我必须在我的 WorldController 中添加一个刷新方法来获取新的引用和另一个刷新方法,因为这个类存储了对我的游戏对象的所有引用(或者在 WorldRenderer 中,因为有对 WordController 的引用)。我不喜欢这个解决方案,但如果我想保持我的代码干净,这是必要的。我想在 Asset 类中这样做,但这是不可能的......
    【解决方案2】:

    您是否尝试过在 resume 方法上不调用 Assets.intance.init(new AssetManager())(也不在 pause 方法上调用 Assets.intance.dispose())? 请阅读此链接: https://github.com/libgdx/libgdx/wiki/Managing-your-assets

    最后(通过加载屏幕恢复)它说:

    在 Android 上,您的应用可以暂停和恢复。托管的 OpenGL 资源,例如纹理 在这种情况下需要重新加载,这可能需要一些时间。如果你想 在简历上显示加载屏幕,您可以在创建后执行以下操作 资产管理器。

    Texture.setAssetManager(manager);

    在您的 ApplicationListener.resume() 方法中,您可以切换到加载屏幕并再次调用 AssetManager.update() 直到一切恢复正常。

    如果你没有像上个 sn-p 那样设置 AssetManager,那么通常的托管纹理机制就会启动,所以你什么都不用担心。

    所以,我认为作者的方法已经没有必要了。

    你只需要在你的“游戏”类(我的意思是实现ApplicationListener的类)的dispose方法上调用Assets.intance.dispose()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-27
      • 1970-01-01
      • 2015-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多