LibGDX在繁重处理期间加载屏幕

时间:2017-10-12 18:13:08

标签: java multithreading libgdx heavy-computation

长篇故事: 我试图在LibGDX中创建一个加载屏幕,不仅需要加载纹理和音频等资源,我还需要创建世界对象(超过1000万个对象) - 我可能想要查看减少的对象数量未来,但我的问题仍然适用于它是一个对象还是数万亿。

在对象初始化期间,由于我假设的延迟,GDX render()方法停止。它将落后于整个应用程序进入的多少#34;没有响应"几秒钟。

我几个月来一直在研究,没什么好发现的。我找到的90%的主题或我问过的人,总是说同样的话;使用AssetManager。我试过这个,但它似乎只支持资产,而不是繁重的处理世界对象。有人告诉我它可以支持自定义类,但是由于缺少文档,我从来没有这样做。

与我最相似的最佳主题是one,它给了我一个在Gdx.app.postRunnable()中使用Gdx.app.postRunnable()的想法。结果如下:

Gdx.app.postRunnable(new Runnable() {
    @Override
    public void run() {

        // do some heavy processing
        // set loading screen percent to x%

        Gdx.app.postRunnable(new Runnable() {
            @Override
            public void run() {

                // do some more heavy processing
                // set loading screen percent to y%

            }
        });

    }
});

解决方案效果很好。它进行了大量处理,设置了加载屏幕的百分比然后绘制它。因此,为了显示缘故,这个解决方案解决了我从未绘制百分比的问题。但是,这个解决方案仍然会将应用程序变为"没有响应"重工之间;这冻结了最终的音乐播放。

通过在postRunnables中添加足够的postRunnables,不会有任何延迟,因为繁重的进程不再存在 - 而是建立在重度进程分成迷你进程的基础上,解决了#34;没有响应"州。虽然这很多postRunnables对于干净的代码并不是很实用,因为它需要超过30个postRunnables,而上面的代码只是2.代码很容易变丑,因此我寻求替代方案。

This帖子也非常有趣,解释了我遇到的完全相同的问题,但结果并没有成功。

我通过两个线程在Java Swing中实现了这一点;一个main和一个loadScreen线程(LCThread)。当进入loadingScreen时,LCThread开始绘制loadingScreen,而主线程进行重处理。完成后,主线程使用它先前处理的对象。遗憾的是,我无法将其转换为LibGDX,因为两个线程无法单独绘制。

短篇小说:我需要编写一个加载屏幕来加载大量的后台处理(初始化很多对象),同时绘制进度(在render()方法中处理)并播放音乐显示加载屏幕,所有这些都不会使应用程序滞后进入"没有响应"。

你有什么建议吗?

1 个答案:

答案 0 :(得分:1)

你可以分解你的GameObject,以便释放处理器。希望这会加载块并保持渲染循环自由播放音乐。基本上所有加载和创建资产都通过AssetManager并在渲染循环中检查以查看游戏的状态并采取相应的行动。 自定义GameObject加载器。 GameObject只是一个泛型类,将其应用于您的项目specifecs。

在AssetManger update(int millis)方法中,它将CPU产生指定的毫秒数。如果你打破了所有的处理并将它放在他们自己的AssetLoaders中,那么AssetManager会更新那段时间并且不会阻止cpu。

public class GameObjectLoader extends SynchronousAssetLoader<GameObject, GameObjectLoader.GameObjectParameters> {

    public GameObjectLoader( FileHandleResolver resolver ) {

        super( resolver );
    }

    @Override
    public GameObject load( AssetManager assetManager, String fileName, FileHandle file, GameObjectParameters parameter ) {

        TextureAtlas atlas = assetManager.get( parameter.src, TextureAtlas.class );
        ShaderProgram shaderProgram = assetManager.get( parameter.shaderSrc, ShaderProgram.class );
        JsonValue json = assetManager.get( parameter.jsonSrc, JsonValue.class );
        Calculation calculation = assetManager.get( parameter.id, Calculation.class );

        GameObject gameObject = new GameObject(
            atlas.findRegion( parameter.name ),
            shaderProgram,
            json,
            calculation
        );

        assetManager.unload( parameter.id ); // unload it otherwise it stays in memory

        return gameObject;
    }

    @Override
    public Array<AssetDescriptor> getDependencies( String fileName, FileHandle file, GameObjectParameters parameter ) {

        Array<AssetDescriptor> dependencies = new Array<AssetDescriptor>();

        dependencies.add( new AssetDescriptor<TextureAtlas>( parameter.src, TextureAtlas.class ) );
        dependencies.add( new AssetDescriptor<ShaderProgram>( parameter.shaderSrc, ShaderProgram.class, parameter.shaderParameter ) );
        dependencies.add( new AssetDescriptor<JsonValue>( parameter.jsonSrc, JsonValue.class ) );
        dependencies.add( new AssetDescriptor<Calculation>( parameter.id, Calculation.class ) );

        return dependencies;
    }


    public static class GameObjectParameters extends AssetLoaderParameters<GameObject> {

        // maybe you have a lot of game logic and dont need to load everything from disk make a custom loader for that too
        public String id = "";
        public String src = "";
        public String name = "";
        public String jsonSrc = "";
        public String shaderSrc = "";
        public ShaderProgramLoader.ShaderProgramParameter shaderParameter = null;
    }
}

AssetLoaders不需要有文件可以使用它仍然无法使用。

class CalculationLoader extends SynchronousAssetLoader<Calculation, AssetLoaderParameters<Calculation>> {

    public CalculationLoader( FileHandleResolver resolver ) {

        super( resolver );
    }

    @Override
    public Calculation load( AssetManager assetManager, String fileName, FileHandle file, AssetLoaderParameters<Calculation> parameter ) {

        // this is the heavy processing
        // the AssetManager dictates how many of these per cycle will be calculated
        return new Calculation();
    }

    @Override
    public Array<AssetDescriptor> getDependencies( String fileName, FileHandle file, AssetLoaderParameters<Calculation> parameter ) {

        return null;
    }

    public static class CalculationParameters extends AssetLoaderParameters<Calculation> {


    }
}