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