title: Компонент Camera
В Defold камера --- это компонент, который изменяет область обзора и проекцию игрового мира. Компонент Camera лишь поверхностно определяет перспективную или ортографическую камеры, которая предоставляет рендер-скрипту матрицу вида и проекции. Перспективная камера обычно используется для 3D-игр, ортографическая камера --- для 2D. Если требуются расширенные возможности, такие как преследование, зумирование, дрожание и т.д., придется реализовать их самостоятельно (см. раздел ниже сторонние решения для камер).
Чтобы создать камеру, кликните ПКМ на игровом объекте и выберите Add Component ▸ Camera. Можно также создать файл компонента в иерархии проекта и добавить этот файл к игровому объекту.
{srcset="images/camera/[email protected] 2x"}
Компонент Camera имеет следующие свойства, определяющие усеченную пирамиду видимости, или фрустум (только для перспективной камеры):
{srcset="images/camera/[email protected] 2x"}
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
Панорамирование/перемещение камеры по игровому миру осуществляется путем перемещения игрового объекта, к которому присоединен компонент камеры. Компонент Camera автоматически отправляет обновленную матрицу вида согласно текущему положению камеры по осям X и Y.
Увеличение и уменьшение масштаба при использовании перспективной камеры осуществляется путем перемещения игрового объекта, к которому прикреплена камера, вдоль оси Z. Компонент камеры автоматически отправляет обновленную матрицу вида согласно текущему положению камеры по оси Z.
Увеличивать и уменьшать масштаб при использовании ортографической камеры можно, только если тип проекции установлен в Fixed, при этом масштаб изменяется путем отправки рендер-скрипту сообщения с требуемым уровнем масштабирования:
msg.post("@render:", "use_fixed_projection", { zoom = 2, near = -1, far = 1 })
Можно заставить камеру следовать за игровым объектом. Для этого достаточно создать игровой объект с прикрепленным к нему компонентом Camera и разместить его в качестве дочернего по отношению к тому объекту, за которым необходимо следовать:
Альтернативный способ заключается в обновлении положения игрового объекта, к которому прикреплен компонент Camera, каждый кадр по мере перемещения игрового объекта, за которым нужно следить.
При панорамировании, масштабировании или изменении проекции камеры с ортографической проекцией типа Stretch по умолчанию координаты мыши, предоставленные в функции жизненного цикла on_input(), больше не будут соответствовать мировым координатам игровых объектов. Необходимо вручную учесть изменение вида или проекции. Преобразование координат мыши/экрана в мировые координаты из стандартного рендер-скрипта выполняется следующим образом:
::: sidenote Сторонние решения для камер, упомянутые в данном руководстве предоставляют функции для преобразования в экранные координаты и обратно. :::
-- 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 единиц, будет отображаться в том же размере, что и объект прямо перед камерой.
{srcset="images/camera/[email protected] 2x"}
Для использования ортографической проекции матрица проекции, передаваемая компонентом Camera, игнорируется, и вместо этого она создается самостоятельно в рендер-скрипте. Рендер-скрипт по умолчанию поддерживает три ортографические проекции: Stretch, Fixed и Fixed Fit. Чтобы выбрать, какую из них использовать, достаточно послать сообщение в рендер-скрипт:
msg.post("@render:", "use_fixed_fit_projection", { near = -1, far = 1 })
::: important Следует отметить, что ближняя и дальняя плоскости также указываются в сообщении. Ближняя и дальняя плоскости, заданные в свойствах камеры, используются только для перспективной проекции. :::
::: important При ортографической проекции представление будет расположено так, что левый нижний угол отрендеренной части экрана будет соответствовать положению игрового объекта, к которому прикреплен компонент Camera. :::
Подробнее о рендер-скрипте и о том, как изменить тип используемой ортографической проекции, можно узнать в руководстве по рендерингу.
Чтобы использовать перспективную проекцию, необходимо использовать как вид, так и проекцию, предоставляемые камерой. Рендер-скрипт должен использовать проекцию, исходящую от камеры, отправленную ему в сообщении:
msg.post("@render:", "use_camera_projection")
За подробностями о рендер-скрипте обращайтесь к руководстве по рендерингу.
Существует несколько библиотечных решений, реализующих общие функции камеры, такие как следование за игровым объектом, преобразование координат экрана в мировые и так далее. Они доступны на портале ассетов сообщества Defold: