0

I'm using Non-continuous Rendering in my loading screen so I can update it as I INIT different parts of my code in a secondary thread. That way I can manually increase the Animation counter that I use to draw a Sprite which shows a filling hourglass in tune with the loading of my assets.

So, I load my game screen with the help of another thread (atlases, textures, init variables,etc) :

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();

In my game screen load_all function I use Gdx.app.postRunnable to run those initializations on the next render of the main UI thread so I don't get any context errors:

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 ... 
}

The problem is that requestRendering doesn't act immediately and sometimes the postRunnables are run one after another without immediately going into the main UI render function so the user can't see the complete animation of the loading sprite; it happens with jumps. HOW can I force Rendering in the main UI thread from the secondary thread that is loading the assets and variables of behalf of the main thread?

gogonapel
  • 788
  • 6
  • 17

1 Answers1

1

If your loading happens faster than the frame time (e.g., if you're loading steps are faster than 60 steps per second) a user won't see all the animation steps. This sounds like a good thing to me!

If however, you want to make sure all the steps of the animation are shown, I think your background thread should just set a "target" animation frame, and the render thread should advance the actual frame by one until the target is hit. It could operate something like this:

  • Background thread sets target = 10 (and requests a render)
  • Render thread is at 0, sees target 10, draws 0, bumps count to 1, sets the request render flag.
  • Render thread is at 1, sees target of 10, draws 1, bumps count to 2, sets request render flag
  • Background thread sets target = 11 (and requests a render).
  • etc, etc.

This way the two can proceed at their own pace. If you want the loading to go quickly the render thread can just draw the target frame. If you want to show every frame, it can bump by 1.

One note: posting a runnable will implicitly request a render.

Secondly, it also looks like all of the work in your "background" thread is being done inside posted runnables (which is probably true, since most loading requires OpenGL context), but maybe its just because you simplified the code for posting your question. Anyway, if that is true, then it is just an awkward way of running everything on the render thread. You might be better off setting up a simple state machine, and having your render thread step through it to run your loading process directly:

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

    loadingStep++;
}

This has the side benefit of running exactly one step per render.

P.T.
  • 24,557
  • 7
  • 64
  • 95