【问题标题】:Non-continuous Rendering in Loading screen not working as it supposed to work - Multithreading LIBGDX加载屏幕中的非连续渲染无法正常工作 - 多线程 LIBGDX
【发布时间】:2015-04-18 11:06:01
【问题描述】:

我在加载屏幕中使用了非连续渲染,因此当我在辅助线程中初始化代码的不同部分时,我可以对其进行更新。这样我就可以手动增加我用来绘制 Sprite 的 Animation 计数器,该 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 线程中进行渲染?

【问题讨论】:

    标签: java android android-activity libgdx


    【解决方案1】:

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

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

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

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

    请注意:发布可运行文件将隐式请求渲染。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-26
      • 1970-01-01
      • 1970-01-01
      • 2013-07-12
      • 2021-05-04
      • 2018-07-30
      • 1970-01-01
      相关资源
      最近更新 更多