0
\$\begingroup\$

I have a "console" window in-game where I log messages. When starting up, the game checks for updates by way of a Timer.Task. Any messages I try to log in the task are not displayed, but the file logs show that they were recorded at the proper time. I assume it's a rendering problem and the console's screen fails to render during the task execution.

I use Dagger2 for dependency-injection but the Screen is a @Singleton, plus there are logs in the constructor that are only written once, so I'm confident that the instance injected in MyGame and the one passed to StartupTask are the same.

I would like the console to continue displaying messages "in real time" while the update task is running. What am I missing?

Game class:

public class MyGame extends Game {

    private static final Logger LOGGER = LoggerFactory.getLogger(MyGame.class);

    private final Lazy<ConsoleScreen> bootScreen;
    private final Lazy<StartupTaskProvider> startupTaskProvider;

    public MyGame(Lazy<ConsoleScreen> bootScreen, Lazy<StartupTaskProvider> startupTaskProvider) {
        super();
        this.bootScreen = bootScreen;
        this.startupTaskProvider = startupTaskProvider;
    }

    @Override
    public void create() {
        LOGGER.info("Startup phase.");
        final ConsoleScreen console = bootScreen.get();
        this.setScreen(console);
        console.addLog("Initialization"); // <--- Correctly displayed

        // Update when booting.
        Timer.schedule(startupTaskProvider.get().create(), 2);
    }

    @Override
    public void render() {
        super.render();
    }
    
    @Override
    public void dispose() {
    }

Provider for MyGame: (Used as a glue between Dagger2 and the call to new Lwjgl3Application)

@Module
public class GameModule {

    @Provides
    @Singleton
    static MyGame provideGame(Lazy<ConsoleScreen> bootScreen, Lazy<StartupTaskProvider> startupTaskProvider) {
        return new MyGame(bootScreen, startupTaskProvider);
    }

}

Screen class:

@Singleton
public class ConsoleScreen implements Screen {

    private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleScreen.class);

    @Inject
    DebugUtils debugUtils;

    @Inject
    TextUtils textUtils;

    private final Stage stage;
    private final Table table;
    private final List<Label> logs;
    private final int maxSize;

    @Inject
    public ConsoleScreen(DebugUtils debugUtils, TextUtils textUtils) {
        // Creates the Stage and adds the Table to it, works fine. 
    }

    public void addLog(String text) {
        // Adds the text to the Table, works fine.
    }

    @Override
    public void show() {
        Gdx.input.setInputProcessor(stage);
    }

    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        stage.act();
        stage.draw();
    }

    @Override
    public void resize(int width, int height) {

    }

    @Override
    public void pause() {

    }

    @Override
    public void resume() {

    }

    @Override
    public void hide() {

    }

    @Override
    public void dispose() {
        stage.dispose();
    }

Startup task:

public class StartupTask extends Timer.Task {

    private final MyGame game;
    private final ConsoleScreen consoleScreen;
    private final MainScreen mainScreen;
    private final UpdateService updateService;

    public StartupTask(ConsoleScreen consoleScreen, MyGame game, MainScreen mainScreen, UpdateService service) {
        this.game = game;
        this.consoleScreen = consoleScreen;
        this.mainScreen = mainScreen;
        this.updateService = service;
    }

    @Override
    public void run() {
        consoleScreen.addLog("Starting update"); // <-- Does not display, at least not before the screen is changed.
        updateService.start().get(); // <-- Executes correctly

        // The screen is then switched and rendered correctly.
        game.setScreen(mainScreen);
        mainScreen.fadeIn();
    }

}

Provider for startup tasks:

@Module
public class StartupTaskProvider {

    @Inject
    MyGame game;

    @Inject
    ConsoleScreen consoleScreen;

    @Inject
    MainScreen mainScreen;

    @Inject
    UpdateService service;

    @Inject
    public StartupTaskProvider() {}

    @Provides
    @Singleton
    public StartupTask create() {
        return new StartupTask(consoleScreen, game, mainScreen, service);
    }

}
\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

I found it, rookie mistake. UpdateService.start() call runs asynchroneously, but by waiting on it with AsyncTask::get, I effectively tie up the main thread, hence no rendering during the update.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .