В Defold камера — это компонент, который изменяет область обзора и проекцию игрового мира. Компонент Camera лишь поверхностно определяет перспективную или ортографическую камеры, которая предоставляет рендер-скрипту матрицу вида и проекции. Перспективная камера обычно используется для 3D-игр, ортографическая камера — для 2D. Если требуются расширенные возможности, такие как преследование, зумирование, дрожание и т.д., придется реализовать их самостоятельно (см. раздел ниже сторонние решения для камер).
Чтобы создать камеру, кликните ПКМ на игровом объекте и выберите Add Component ▸ Camera. Можно также создать файл компонента в иерархии проекта и добавить этот файл к игровому объекту.
Компонент Camera имеет следующие свойства, определяющие усеченную пирамиду видимости, или фрустум (только для перспективной камеры):
π / 4
).Чтобы активировать камеру и передать ее матрицы вида и проекции в рендер-скрипт, нужно вызвать функцию 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(), больше не будут соответствовать мировым координатам игровых объектов. Необходимо вручную учесть изменение вида или проекции. Преобразование координат мыши/экрана в мировые координаты из стандартного рендер-скрипта выполняется следующим образом:
Сторонние решения для камер, упомянутые в данном руководстве предоставляют функции для преобразования в экранные координаты и обратно.
-- 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 единиц, будет отображаться в том же размере, что и объект прямо перед камерой.
Для использования ортографической проекции матрица проекции, передаваемая компонентом Camera, игнорируется, и вместо этого она создается самостоятельно в рендер-скрипте. Рендер-скрипт по умолчанию поддерживает три ортографические проекции: Stretch
, Fixed
и Fixed Fit
. Чтобы выбрать, какую из них использовать, достаточно послать сообщение в рендер-скрипт:
msg.post("@render:", "use_fixed_fit_projection", { near = -1, far = 1 })
Следует отметить, что ближняя и дальняя плоскости также указываются в сообщении. Ближняя и дальняя плоскости, заданные в свойствах камеры, используются только для перспективной проекции.
При ортографической проекции представление будет расположено так, что левый нижний угол отрендеренной части экрана будет соответствовать положению игрового объекта, к которому прикреплен компонент Camera.
Подробнее о рендер-скрипте и о том, как изменить тип используемой ортографической проекции, можно узнать в руководстве по рендерингу.
Чтобы использовать перспективную проекцию, необходимо использовать как вид, так и проекцию, предоставляемые камерой. Рендер-скрипт должен использовать проекцию, исходящую от камеры, отправленную ему в сообщении:
msg.post("@render:", "use_camera_projection")
За подробностями о рендер-скрипте обращайтесь к руководстве по рендерингу.
Существует несколько библиотечных решений, реализующих общие функции камеры, такие как следование за игровым объектом, преобразование координат экрана в мировые и так далее. Они доступны на портале ассетов сообщества Defold:
Did you spot an error or do you have a suggestion? Please let us know on GitHub!
GITHUB