加载屏幕中的非连续渲染无法正常工作 - 多线程 LIBGDX

Non-continuous Rendering in Loading screen not working as it supposed to work - Multithreading LIBGDX

我在加载屏幕中使用非连续渲染,因此我可以在辅助线程中初始化代码的不同部分时更新它。这样我就可以手动增加我用来绘制 Sprite 的动画计数器,该 Sprite 显示与我的资产加载一致的填充沙漏。

因此,我在另一个线程(图集、纹理、初始化变量等)的帮助下加载我的游戏屏幕:

Runnable load_game_screen = new Runnable(){
    public void run(){
        new_game_screen.load_all();
    }
}};
Thread thread_load_game = new Thread(load_game_screen);
thread_load_game.start();

在我的游戏画面中 load_all 函数我使用 Gdx.app.postRunnable 到 运行 那些初始化在主 UI 线程的下一个渲染上,所以我没有收到任何上下文错误:

public void load_all(){
    Gdx.app.postRunnable(new Runnable(){
    @Override
    public void run(){
       ...load stuff
       loading_screen.loading_counter += 0.025f;
       loading_screen.loadingTimerSprite.setRegion(loading_screen.animation.getKeyFrame(loading_screen.loading_counter, true));
    }
    Gdx.graphics.requestRendering();
    Thread.sleep(25);

    Gdx.app.postRunnable(new Runnable(){
    @Override
    public void run(){
       ...load stuff part2
       loading_screen.loading_counter += 0.025f;
       loading_screen.loadingTimerSprite.setRegion(loading_screen.animation.getKeyFrame(loading_screen.loading_counter, true));
    }
    Gdx.graphics.requestRendering();
    Thread.sleep(25);

    ... etc ... 
}

问题是 requestRendering 没有立即执行,有时 postRunnables 一个接一个 运行 没有立即执行进入主 UI 渲染函数,这样用户就看不到加载精灵的完整动画;它发生在跳跃中。如何从代表主线程加载资产和变量的辅助线程强制在主 UI 线程中呈现?

如果您的加载速度快于帧时间(例如,如果您的加载步数快于每秒 60 步),用户将看不到所有动画步数。这对我来说是件好事!

但是,如果您想确保显示动画的所有步骤,我认为您的后台线程应该只设置一个 "target" 动画帧,而渲染线程应该将实际帧推进一帧直到击中目标。它可以这样操作:

  • 后台线程集 target = 10(并请求渲染)
  • 渲染线程处于 0,看到目标 10,绘制 0,碰撞计数为 1,设置请求渲染标志。
  • 渲染线程处于 1,看到目标 10,绘制 1,碰撞计数为 2,设置请求渲染标志
  • 后台线程集 target = 11(并请求渲染)。
  • 等等等等

这样两人就可以按照自己的节奏进行了。如果您希望加载快速进行,渲染线程可以只绘制目标帧。如果你想显示每一帧,它可以增加1。

请注意:发布 运行nable 将隐式请求渲染。

其次,您的 "background" 线程中的 所有 工作似乎也在已发布的 运行nables 中完成(这可能是真的,因为大多数加载都需要 OpenGL 上下文),但可能只是因为您简化了发布问题的代码。无论如何,如果那是真的,那么它只是 运行 渲染线程上所有内容的笨拙方式。您最好设置一个简单的状态机,并让您的渲染线程直接通过它进入 运行 您的加载过程:

if (! done) {
    switch(loadingStep) {
       case 0:
         // step 0 code
         break;
       case 1:
         // step 1 code 
         break;
       case 2:
         ...
       case 10:
         done = true;
         break;
    }

    loadingStep++;
}

这有一个附带的好处,即 运行每次渲染只执行一个步骤。