Read this manual in English

Компонент Camera

В Defold камера — это компонент, который изменяет область обзора и проекцию игрового мира. Компонент Camera лишь поверхностно определяет перспективную или ортографическую камеры, которая предоставляет рендер-скрипту матрицу вида и проекции. Перспективная камера обычно используется для 3D-игр, ортографическая камера — для 2D. Если требуются расширенные возможности, такие как преследование, зумирование, дрожание и т.д., придется реализовать их самостоятельно (см. раздел ниже сторонние решения для камер).

Создание камеры

Чтобы создать камеру, кликните ПКМ на игровом объекте и выберите Add Component ▸ Camera. Можно также создать файл компонента в иерархии проекта и добавить этот файл к игровому объекту.

create camera component

Компонент Camera имеет следующие свойства, определяющие усеченную пирамиду видимости, или фрустум (только для перспективной камеры):

camera settings

Id
Идентификатор компонента
Aspect Ratio
(Только для перспективной камеры) — Соотношение между шириной и высотой фрустума. 1.0 предполагает квадратичное представление. 1,33 подходит для формата 4:3, например, 1024x768. 1.78 подходит для формата 16:9. Данное свойство игнорируется, если отмечена опция Auto Aspect Ratio.
Fov
(Только для перспективной камеры) — Поле зрения камеры по вертикали, выраженное в радианах. Чем шире поле зрения, тем больше камера видит. Обратите внимание, что текущее значение по умолчанию (45) вводит в заблуждение. Для поля зрения в 45 градусов измените значение на 0.785 (π / 4).
Near Z
(Только для перспективной камеры) — Z-значение ближней плоскости отсечения.
Far Z
(Только для перспективной камеры) — Z-значение дельней плоскости отсечения.
Auto Aspect Ratio
(Только для перспективной камеры) — Если опция отмечена, камера будет вычислять соотношение сторон автоматически.

Использование камеры

Чтобы активировать камеру и передать ее матрицы вида и проекции в рендер-скрипт, нужно вызвать функцию camera.acquire_focus или отправить компоненту сообщение acquire_camera_focus:

camera.acquire_focus("#camera")

или

msg.post("#camera", "acquire_camera_focus")

В каждом кадре компонент Camera, который в данный момент имеет фокус, будет посылать сообщение "set_view_projection" в сокет “@render”, то есть оно будет поступать в рендер-скрипт:

-- builtins/render/default.render_script
--
function on_message(self, message_id, message)
    if message_id == hash("set_view_projection") then
        self.view = message.view                    -- [1]
        self.projection = message.projection
    end
end
  1. Сообщение, переданное от компонента камеры, включает матрицу вида и матрицу проекции.

Панорамирование камеры

Панорамирование/перемещение камеры по игровому миру осуществляется путем перемещения игрового объекта, к которому присоединен компонент камеры. Компонент Camera автоматически отправляет обновленную матрицу вида согласно текущему положению камеры по осям X и Y.

Зумирование камеры

Увеличение и уменьшение масштаба при использовании перспективной камеры осуществляется путем перемещения игрового объекта, к которому прикреплена камера, вдоль оси Z. Компонент камеры автоматически отправляет обновленную матрицу вида согласно текущему положению камеры по оси Z.

Увеличивать и уменьшать масштаб при использовании ортографической камеры можно, только если тип проекции установлен в Fixed, при этом масштаб изменяется путем отправки рендер-скрипту сообщения с требуемым уровнем масштабирования:

msg.post("@render:", "use_fixed_projection", { zoom = 2, near = -1, far = 1 })

Следование за игровым объектом

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

follow game object

Альтернативный способ заключается в обновлении положения игрового объекта, к которому прикреплен компонент Camera, каждый кадр по мере перемещения игрового объекта, за которым нужно следить.

Преобразование экранных координат в мировые

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

Сторонние решения для камер, упомянутые в данном руководстве предоставляют функции для преобразования в экранные координаты и обратно.

-- builtins/render/default.render_script
--
local function screen_to_world(x, y, z)
	local inv = vmath.inv(self.projection * self.view)
	x = (2 * x / render.get_width()) - 1
	y = (2 * y / render.get_height()) - 1
	z = (2 * z) - 1
	local x1 = x * inv.m00 + y * inv.m01 + z * inv.m02 + inv.m03
	local y1 = x * inv.m10 + y * inv.m11 + z * inv.m12 + inv.m13
	local z1 = x * inv.m20 + y * inv.m21 + z * inv.m22 + inv.m23
	return x1, y1, z1
end

Проекции

Компонент Camera передает рендер-скрипту перспективную проекцию. Это хорошо подходит для 3D-игр. Для 2D-игр зачастую требуется рендерить сцену с ортографической проекцией. Это означает, что вид камеры определяется не фрустумом, а фреймом. Ортографическая проекция нереалистична, поскольку она не искажает размер объектов в зависимости от расстояния до них. Объект, находящийся на расстоянии в 1000 единиц, будет отображаться в том же размере, что и объект прямо перед камерой.

projections

Ортографическая проекция (2D)

Для использования ортографической проекции матрица проекции, передаваемая компонентом Camera, игнорируется, и вместо этого она создается самостоятельно в рендер-скрипте. Рендер-скрипт по умолчанию поддерживает три ортографические проекции: Stretch, Fixed и Fixed Fit. Чтобы выбрать, какую из них использовать, достаточно послать сообщение в рендер-скрипт:

msg.post("@render:", "use_fixed_fit_projection", { near = -1, far = 1 })

Следует отметить, что ближняя и дальняя плоскости также указываются в сообщении. Ближняя и дальняя плоскости, заданные в свойствах камеры, используются только для перспективной проекции.

При ортографической проекции представление будет расположено так, что левый нижний угол отрендеренной части экрана будет соответствовать положению игрового объекта, к которому прикреплен компонент Camera.

Подробнее о рендер-скрипте и о том, как изменить тип используемой ортографической проекции, можно узнать в руководстве по рендерингу.

Перспективная проекция (3D)

Чтобы использовать перспективную проекцию, необходимо использовать как вид, так и проекцию, предоставляемые камерой. Рендер-скрипт должен использовать проекцию, исходящую от камеры, отправленную ему в сообщении:

msg.post("@render:", "use_camera_projection")

За подробностями о рендер-скрипте обращайтесь к руководстве по рендерингу.

Сторонние решения для камер

Существует несколько библиотечных решений, реализующих общие функции камеры, такие как следование за игровым объектом, преобразование координат экрана в мировые и так далее. Они доступны на портале ассетов сообщества Defold: