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

时间:2015-04-18 11:06:02

标签: java android android-activity 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线程中的渲染?

1 个答案:

答案 0 :(得分:2)

如果加载速度比帧时间快(例如,如果加载步骤的速度超过每秒60步),用户将无法看到所有动画步骤。这对我来说听起来不错!

但是,如果你想确保显示动画的所有步骤,我认为你的后台线程应该只设置一个“目标”动画帧,渲染线程应该将实际帧提前一,直到目标是击中。它可以像这样运作:

  • 后台线程集target = 10(并请求呈现)
  • 渲染线程为0,看到目标10,绘制0,凸起计数为1,设置请求渲染标记。
  • 渲染线程为1,看目标为10,绘制1,颠倒计数为2,设置请求渲染标志
  • 后台线程集target = 11(并请求渲染)。
  • 等等。

这样两者可以按照自己的节奏进行。如果你想快速加载,渲染线程只能绘制目标框架。如果你想显示每一帧,它可以突然1。

一个注意事项:发布runnable将隐式请求渲染。

其次,它看起来像所有你的“后台”线程中的工作是在发布的runnables中完成的(这可能是真的,因为大多数加载需要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++;
}

这样做的好处是每个渲染只运行一步。