libgdx & kryonet: темы

Я пытаюсь разработать игру для платформы Android, используя библиотеку Libgdx. Для сети я использую библиотеку Kryonet.

Я хочу изменить экран, когда я уверен, что мое приложение подключено к моему серверу.
Кажется, сетевая часть работает, но у меня есть проблема с потоками: это поток Kryonet, который выполняет OpenGL, а не поток Libgdx:

public class MyGdxGame extends Game {
    public static int UDP_PORT = 55555, TCP_PORT = 55556;
    private Client client;

    @Override
    public void create() {
        /*
         * client connection
         * etc ...
         */
        client.addListener(new Listener() {
            private int nb = 0;

            @Override
            public void received(Connection connection, Object data) {
                super.received(connection, data);
                nb++;
                if (nb == 5) {
                    MyGdxGame.this.setSecondScreen();
                }
            }
        });
        setScreen(new First(this, client));
    }

    protected void setSecondScreen() {
        setScreen(new Second(this, client)); //This part should be executed by Libgdx thread ?!     
    }

Обратите внимание, что First и Second являются классами Screen, которые просто рисуют изображение.

У меня есть это исключение, когда я пытаюсь запустить Второй экран: Исключение в потоке "Клиент" java.lang.RuntimeException: Контекст OpenGL не найден в текущем потоке.

Могу ли я заставить поток LibGDX выполнять инструкции? Возможен ли другой подход?

Слава Джонатану

1 ответ

Решение

В Libgdx только один поток (поток, который выполняет обратные вызовы жизненного цикла приложения) имеет действительный контекст OpenGL и может вызывать вызовы OpenGL. Вы можете опубликовать Runnable в поток GDX из других ваших потоков, чтобы заставить его выполнять вещи от имени других потоков. Опубликованные runnables будут выполнены до запуска следующего обратного вызова. Смотрите Gdx.app.postRunnable()

В вашем случае вы можете сделать что-то вроде этого:

@Override
public void received(Connection connection, Object data) {
   super.received(connection, data);
   nb++;
   if (nb == 5) {
      final MyGdxGame g = MyGdxGame.this;
      Gdx.app.postRunnable(new Runnable() {
         public void run() {
            g.setSecondScreen();
         });
   }
}

В зависимости от того, как часто это происходит, вы можете избежать выделения нового Runnable на каждом обратном вызове, так что если вы сделаете MyGdxGameRunnable или сделать заказ Listener который реализует Runnable Вы должны быть в состоянии избежать распределения.

Другие вопросы по тегам