Главная » Программирование игр под Android » Класс Camera2D – РАЗРАБОТКА ИГР ДЛЯ ОС ANDROID

0

Объединим все рассмотренные детали работы с камерой в один класс. Мы хотим, чтобы в нем хранились позиция камеры, стандартные ширина и длина области видимости и переменная масштаба. Мы также хотим иметь удобный метод для правильного назначения порта просмотра (всегда использовать весь экран) и матрицы проецирования. Еще нам нужен метод для перевода координат при касании в координаты нашего мира. Наш новый класс Camera2D показан в листинге 8.15.

Листинг 8.15. Camera2D.java: наш новенький класс камеры для рендеринга 2D

Как мы уже обсуждали, мы сохраняем позицию камеры, ширину и длину конуса отображения и переменную масштаба как члены класса. Члены позиции камеры и переменной масштаба общедоступные, поэтому мы легко можем управлять ими. Нам также нужна ссылка на GLGraphics, чтобы брать оттуда последние известные ширину и длину экрана в пикселах для перевода координат касания в координаты нашего мира.

В конструкторе мы берем экземпляр класса GLGraphics, ширину и длину конуса отображения при переменной масштаба 1 как параметры. Сохраняем их и инициализируем позицию камеры, чтобы она смотрела в центр прямоугольника, ограниченного координатами (0; 0; 1) и (frustumWidth; frustumHeight; -1), как на рис. 8.19. Исходное значение переменной масштаба равно 1.

Метод setViewport And MatricesO задает область просмотра, охватывающую весь экран, а также задает проекционную матрицу в соответствии с параметрами нашей камеры, как мы уже говорили раньше. В конце метода мы указываем OpenGL ES, что все дальнейшие матричные операции направлены на матрицу модели-вида, и загружаем единичную матрицу. Мы будем вызывать этот метод каждый кадр, чтобы можно было начинать с чистого листа. И больше никаких прямых вызовов OpenGL ES для установления области просмотра и проекционной матрицы.

Метод touchToWorld принимает член класса Vector2, содержащий координаты, которые получены при касании, и переводит вектор в пространство мира. Это то же, что мы уже обсуждали; единственная разница в том, что мы используем наш замечательный класс Vector2.

Пример

Давайте используем класс Camera2D в нашем примере с пушкой. Я скопировал файл Col1isionTest и переименовал его в Camera2DTest. Я также поменял имя класса GLGame внутри файла Camera2DTest и переименовал класс Collision-Screen в Camera2DScreen. Мы обсудим только небольшие изменения, которые надо внести, чтобы использовать наш новый класс Camera2D.

Первое, что мы делаем, – добавляем новый член в класс Camera2DScreen: Camera2D camera;

Инициализируем этот член класса в конструкторе следующим образом:

Предъявляем наш экземпляр класса GLGraphics, ширину и длину нашего мира, которые мы до этого использовали как ширину и длину конуса отображения в вызове glOrthof О. Сейчас нужно заменить наши прямые вызовы OpenGL ES в методе present , который выглядит вот так:

Мы заменяем их этим:

Нам, конечно, еще нужно очищать кадровый буфер, но все остальные прямые вызовы OpenGL ES замечательно спрятаны в методе Camera2D. setVi ewportAndMatrices. Если вы выполните этот код, вы увидите, что ничего не изменилось. Все работает, как и раньше, – все это мы делали, чтобы код был красивее и удобнее.

Мы также можем немного упростить метод теста updateO. Поскольку мы добавили в класс камеры метод Camera2D.touchToWorld, мы можем использовать и его тоже. Мы можем заменить этот фрагмент метода update:

таким:

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

Наше нововведение станет заметным, когда ядро будет лететь (когда у-координата будет больше нуля). Мы хотим, чтобы камера следила за ядром. Этого можно достичь, установив позицию камеры на позицию ядра. Это позволит всегда держать ядро в центре экрана. Также хорошо бы опробовать функционал масштабирования. Для этого будем увеличивать переменную масштаба в зависимости от у-координаты ядра. Чем дальше от нуля координата, тем больше переменная масштаба. Таким образом, камера будет отъезжать, когда у ядра будет более высокая у-координата. Вот то, что нам надо добавить в конце метода update  на экране нашего теста:

Когда у-координата ядра больше нуля, камера будет следовать за ним и отдаляться. Мы просто добавим некоторую величину к стандартной переменной масштаба, равной единице. Эта величина – отношение между положением ядра на у-оси и высотой мира. Если у-координата ядра находится в WORLD HEIGHT, переменная масштаба будет равна 2, чтобы мы видели большую часть нашего мира. Способ, которым я это сделал, на самом деле произвольный – вы можете применить любую формулу, которую хотите, для данного случая. Если позиция ядра меньше или равна нулю, показываем мир в нормальном размере, как мы делали в предыдущих примерах.

Источник: Mario Zechner / Марио Цехнер, «Программирование игр под Android», пер. Егор Сидорович, Евгений Зазноба, Издательство «Питер»

По теме:

  • Комментарии