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

0

 

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

Камера с видом от первого лица (Эйлерова камера)

Камера с видом от первого лица (Эйлерова камера) определяется следующими атрибутами: поле обзора в градусах; соотношение сторон области просмотра; ближняя и дальняя плоскости отсечения; позиция в 3D -пространстве; угол поворота вокруг оси у; угол поворота вокруг оси х. Он ограничен и лежит в промежутке между -90 и 90°. Подумайте о том, как далеко вы сможете наклонить вашу голову, и попробуйте выйти за эти пределы. За любые возможные травмы я ответственности не несу.

Первые три атрибута используются для определения матрицы перспективной проекции. Мы уже делали это с помощью вызова метода gl uPerspective во всех примерах с 3D.

Остальные три атрибута определяют позицию и ориентацию камеры в нашем мире.

Поместим все это в простой класс. Его код показан в листинге 11.9.

В дополнение мы хотим передвигать камеру в том направлении, в котором она направлена. Для этого нам понадобится единичный вектор, которым мы сможем добавить к вектору позиции камеры. Мы можем создать такой вектор с помощью класса Matrix, который предоставляется в Android API. Немного подумаем об этом.

В своей конфигурации по умолчанию наша камера будет смотреть вдоль отрицательной части оси z. Поэтому вектор ее направления равен (0; 0; -1). Когда мы определим углы поворота вокруг осей х или у, этот вектор будет соответственно повернут. Для определения вектора направления нам лишь нужно умножить его на матрицу, которая повернет стандартный вектор так же, как OpenGL ES повернет вершины наших моделей.

Взглянем на то, как все это работает в коде. В листинге 11.9 показан код класса EulerCamera.

Листинг 11.9. Класс EulerCamera.Java, простая камера с видом от первого лица, основанная на Эйлеровых углах вокруг осей х и у

Первые три члена хранят позицию и углы поворота камеры. Остальные четыре члена используются для расчета матрицы перспективной проекции. По умолчанию камера располагается в начале координат и смотрит вдоль отрицательной части оси z.

Конструктор принимает четыре параметра, определяющих перспективную проекцию. Мы оставляем значения по умолчанию для позиции камеры и углов ее поворота.

Эти методы просто возвращают ориентацию камеры и ее позицию.

Метод setAngles  позволяет нам напрямую устанавливать значения угла поворота камеры. Обратите внимание на то, что мы ограничиваем значение угла поворота по оси х промежутком от -90 до 90. Мы не можем повернуть собственную голову больше, чем на эти градусы, поэтому камера тоже не должна этого делать.

Метод rotateO практически идентичен методу setAnglesO. Вместо установки градусов он увеличивает их на значение параметра. Это будет полезно, когда мы в следующем примере реализуем небольшую схему управления, основанную на прикосновениях к экрану.

Метод setMatrices  просто инициализирует проекционную и модельно-видовую матрицы так, как мы говорили ранее. Проекционная матрица устанавливается с помощью метода gluPerspective, основываясь на параметрах, переданных камере в конструкторе. Модельно-видовая матрица выполняет прием Магомет – гора, применяя поворот и параллельный перенос на оси х и у. Все факторы, включенные в это действие, меняют свой знак на минус, чтобы достичь того, чтобы камера оставалась в начале координат и направлялась вдоль отрицательной части оси г. Именно поэтому мы поворачиваем и параллельно переносим объекты вокруг камеры. Других способов нет.

Наконец, мы видим таинственный метод getDirection . Он содержит несколько членов, которые используются для расчетов внутри метода. Благодаря этому мы не создаем новые массивы чисел с плавающей точкой и экземпляры класса Vector3 каждый раз, когда вызывается этот метод.

Рассматривайте эти члены класса как временные рабочие переменные. Внутри метода мы сначала устанавливаем матрицу преобразований, содержащую информацию о том, что необходимо выполнить поворот вокруг осей х и у. Нам не нужно включать туда параллельный перенос, поскольку нам необходимо создать вектор направления, а не позиции. Направление камеры не зависит от ее позиции в мире. Методы класса Matrix говорят сами за себя. Единственный странный аспект – мы вызываем эти методы в обратном порядке, не изменяя знак их аргументов. Противоположное происходит при вызове метода setMatrices, это достигается за счет того, что теперь мы применяем преобразования к точке точно так же, как и к виртуальной камере, которая не обязательно должна размещаться в начале координат и направлена в сторону отрицательной части оси z. Поворачиваемый вектор имеет координаты (0; 0; -1) и хранится в переменной inVec. Это направление камеры по умолчанию, если она не была повернута. Все производимые нами манипуляции с матрицами – это поворот вектора направления на углы pitch и roll, поэтому она указывает в том же направлении, что и камера. Последнее, что нам нужно сделать, – установить значение экземпляра класса Vector3, основываясь на результате перемножения матрицы и вектора и вернуть его вызывающей функции.

Мы можем использовать этот единичный вектор направления и в дальнейшем для того, чтобы переместить камеру в том направлении, куда она повернута.

С помощью небольшого вспомогательного класса мы напишем маленькую тестовую программу, позволяющую нам перемещаться в мире ящиков.

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

По теме:

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