Я хотел написать какую-нибудь простую игру на андроиде, используя opengl, но сразу столкнулся с проблемой основной игры петля. Как я прочитал здесь: http://developer.android.com/resources/tutorials/opengl/opengl-es10.htmlприложение вызывает public void onDrawFrame(GL10 gl)
каждый раз необходимо перерисовать поверхность. Или что-то в этом роде. Моя проблема заключалась в том, как создать цикл обновления, не зависящий от вызовов отрисовки. Я имею в виду - это не может так работать, я не могу обновить игровую логику только тогда, когда устройство (приложение?) хочет перерисовать поверхность (или я ошибаюсь?).
Погуглив немного, я пришел к выводу, что мне нужно создать еще один поток для цикла обновления. Но потом у меня возникла другая проблема: когда один поток заботился о рисовании, а другой — об обновлении игровой логики, я не знал, как заставить их сотрудничать. Во-первых, это были два отдельных класса (по крайней мере, в моей реализации), поэтому они не могли использовать одни и те же игровые переменные и объекты (спрайты, таймеры, разные переменные, счетчики и т. д.) почти все, что нужно было делать этим двум классам. их работы). Теперь я думаю, что мог бы как-то упаковать их обоих в один класс. Но, во-вторых, мне нужно было как-то синхронизировать два потока.
Наконец, я пришел к этой общей идее:
открытый класс MyRenderer реализует GLSurfaceView.Renderer
с методом onSurfaceCreated()
для рисованияоткрытый класс UpdateThread реализует Runnable
с run()
и методы update()
. run()
вызывал метод update()
ровно 60 раз в секунду (мне нужен цикл с фиксированным шагом)открытый класс SpritesHolder
, используемый в качестве контейнера для всех игровые объекты/переменные/вещи (такие как спрайты, таймеры, переменные состояния и т.д....) со всеми общедоступными полями.SpritesHolder
представлял собой ящик, содержащий все необходимые переменные в одном месте, поэтому классы MyRenderer
и UpdateThread
могли получить к нему доступ и использовать его.Что касается синхронизации - я сделал что-то вроде этого:
public void update(float delta)
{
синхронизированный (spritesHolder)
{
// весь код метода...
}
}
и:
public void onDrawFrame(GL10 gl)
{
синхронизированный (spritesHolder)
{
// весь код метода...
}
}
чтобы оба потока не использовали spritesHolder одновременно. Таким образом, обновления выполнялись 60 раз в секунду, а отрисовка происходила всякий раз, когда это требовалось приложению (устройству?).
Много болтаю, извините, почти закончил писать этот пост. ;) Так или иначе - это (описанное выше) работает, и я даже написал какую-то игру, основанную на этом "шаблоне", но я думаю, что мои идеи могут быть сумасшедшими, и все это можно спроектировать намного лучше. Буду очень благодарен за все комментарии и советы.