Как правильно создать цикл обновления/отрисовки с помощью android opengl?

Я хотел написать какую-нибудь простую игру на андроиде, используя opengl, но сразу столкнулся с проблемой основной игры петля. Как я прочитал здесь: http://developer.android.com/resources/tutorials/opengl/opengl-es10.htmlприложение вызывает public void onDrawFrame(GL10 gl)каждый раз необходимо перерисовать поверхность. Или что-то в этом роде. Моя проблема заключалась в том, как создать цикл обновления, не зависящий от вызовов отрисовки. Я имею в виду - это не может так работать, я не могу обновить игровую логику только тогда, когда устройство (приложение?) хочет перерисовать поверхность (или я ошибаюсь?).

Погуглив немного, я пришел к выводу, что мне нужно создать еще один поток для цикла обновления. Но потом у меня возникла другая проблема: когда один поток заботился о рисовании, а другой — об обновлении игровой логики, я не знал, как заставить их сотрудничать. Во-первых, это были два отдельных класса (по крайней мере, в моей реализации), поэтому они не могли использовать одни и те же игровые переменные и объекты (спрайты, таймеры, разные переменные, счетчики и т. д.) почти все, что нужно было делать этим двум классам. их работы). Теперь я думаю, что мог бы как-то упаковать их обоих в один класс. Но, во-вторых, мне нужно было как-то синхронизировать два потока.

Наконец, я пришел к этой общей идее:

  • 3 класса:
    1. открытый класс MyRenderer реализует GLSurfaceView.Rendererс методом onSurfaceCreated()для рисования
    2. открытый класс UpdateThread реализует Runnableс run()и методы update(). run()вызывал метод update()ровно 60 раз в секунду (мне нужен цикл с фиксированным шагом)
    3. открытый класс SpritesHolder, используемый в качестве контейнера для всех игровые объекты/переменные/вещи (такие как спрайты, таймеры, переменные состояния и т.д....) со всеми общедоступными полями.
  • Таким образом, класс SpritesHolderпредставлял собой ящик, содержащий все необходимые переменные в одном месте, поэтому классы MyRendererи UpdateThreadмогли получить к нему доступ и использовать его.
  • Что касается синхронизации - я сделал что-то вроде этого:

    public void update(float delta)
    {
    синхронизированный (spritesHolder)
     {
     // весь код метода...
     }
    }
    

    и:

    public void onDrawFrame(GL10 gl)
    {
    синхронизированный (spritesHolder)
     {
     // весь код метода...
     }
    }
    

    чтобы оба потока не использовали spritesHolder одновременно. Таким образом, обновления выполнялись 60 раз в секунду, а отрисовка происходила всякий раз, когда это требовалось приложению (устройству?).

Много болтаю, извините, почти закончил писать этот пост. ;) Так или иначе - это (описанное выше) работает, и я даже написал какую-то игру, основанную на этом "шаблоне", но я думаю, что мои идеи могут быть сумасшедшими, и все это можно спроектировать намного лучше. Буду очень благодарен за все комментарии и советы.

7
задан NPS 28 March 2012 в 20:14
поделиться