title: Компонент Camera
Камера в Defold — это компонент, который изменяет область просмотра (viewport) и проекцию игрового мира. Компонент камеры определяет базовую перспективную или ортографическую камеру, которая предоставляет матрицы вида и проекции в рендер-скрипт.
Перспективная камера обычно используется для 3D-игр, где вид камеры и размер и перспектива объектов основаны на усечённой пирамиде (view frustum) и расстоянии и угле обзора от камеры до объектов в игре.
Для 2D-игр часто предпочтительно использовать ортографическую проекцию. Это означает, что вид камеры больше не определяется усечённой пирамидой, а ограничен параллелепипедом. Ортографическая проекция нереалистична, так как не изменяет размер объектов в зависимости от расстояния. Объект на расстоянии 1000 единиц будет отображаться того же размера, что и объект прямо перед камерой.
Чтобы создать камеру, кликните правой кнопкой мыши по игровому объекту и выберите Add Component ▸ Camera. Также можно создать файл компонента камеры в иерархии проекта и добавить его к игровому объекту.
Компонент камеры имеет следующие свойства, определяющие усечённую пирамиду камеры:
Id : Идентификатор компонента
Aspect Ratio : (Только для перспективной камеры) — соотношение ширины и высоты усечённой пирамиды. 1.0 означает квадратный вид. 1.33 подходит для соотношения 4:3, например 1024x768. 1.78 — для 16:9. Это значение игнорируется, если включён Auto Aspect Ratio.
Fov : (Только для перспективной камеры) — вертикальный угол обзора камеры в радианах. Чем шире угол обзора, тем больше камера видит.
Near Z : Z-значение ближней плоскости отсечения.
Far Z : Z-значение дальней плоскости отсечения.
Auto Aspect Ratio : (Только для перспективной камеры) — если включено, камера автоматически вычисляет соотношение сторон.
Orthographic Projection : Включите, чтобы использовать ортографическую проекцию (см. ниже).
Orthographic Zoom : (Только для ортографической камеры) — масштаб ортографической проекции (> 1 = приближение, < 1 = отдаление).
Orthographic Mode
: (Только для ортографической камеры) — управляет тем, как ортографическая камера определяет зум относительно размера окна и ваших значений дизайна (game.project
→ display.width/height
).
Fixed
(постоянный зум): используется текущее значение Orthographic Zoom
.Auto Fit
(вписать): автоматически подбирает зум так, чтобы вся дизайн-область помещалась в окно. Возможен дополнительный контент по бокам/сверху/снизу.Auto Cover
(заполнить): автоматически подбирает зум так, чтобы дизайн-область заполняла окно целиком. Возможна обрезка по бокам/сверху/снизу.
Доступно только при включённой Orthographic Projection
.Все камеры по умолчанию включены и обновляются каждый кадр, а Lua-модуль camera
доступен во всех скриптовых контекстах. Начиная с Defold 1.8.1, больше не нужно явно включать камеру через отправку сообщения acquire_camera_focus
компоненту камеры. Старые сообщения acquire и release всё ещё поддерживаются, но рекомендуется использовать сообщения enable
и disable
, как для любого другого компонента, который нужно включать или выключать:
msg.post("#camera", "disable")
msg.post("#camera", "enable")
Чтобы получить список всех доступных камер, используйте функцию camera.get_cameras()
:
-- Внимание: вызовы render доступны только в рендер-скрипте.
-- camera.get_cameras() можно использовать везде,
-- но render.set_camera — только в рендер-скрипте.
for k,v in pairs(camera.get_cameras()) do
-- таблица camera содержит URL всех камер
render.set_camera(v)
-- здесь выполняется рендеринг — всё, что использует материалы с
-- матрицами вида и проекции, будет использовать матрицы этой камеры.
end
-- чтобы отключить камеру, передайте nil (или вызовите без аргументов) в render.set_camera.
-- после этого все вызовы рендеринга будут использовать матрицы вида и проекции,
-- заданные напрямую в рендер-контексте через render.set_view и render.set_projection
render.set_camera()
Модуль camera
содержит множество функций для управления камерой. Вот несколько из них, полный список доступен в API документации:
camera.get_aspect_ratio(camera) -- получить соотношение сторон
camera.get_far_z(camera) -- получить дальнюю плоскость отсечения
camera.get_fov(camera) -- получить угол обзора
camera.get_orthographic_mode(camera) -- получить ортографический режим (одно из camera.ORTHO_MODE_*)
camera.set_aspect_ratio(camera, ratio) -- установить соотношение сторон
camera.set_far_z(camera, far_z) -- установить дальнюю плоскость отсечения
camera.set_near_z(camera, near_z) -- установить ближнюю плоскость отсечения
camera.set_orthographic_mode(camera, camera.ORTHO_MODE_AUTO_FIT) -- установить ортографический режим
... и другие
Камера идентифицируется URL, который представляет полный путь к компоненту в сцене, включая коллекцию, игровой объект и id компонента. В примере используйте URL /go#camera
для доступа к компоненту камеры из той же коллекции, и main:/go#camera
для доступа к камере из другой коллекции или рендер-скрипта.
-- Доступ к камере из скрипта в той же коллекции:
camera.get_fov("/go#camera")
-- Доступ к камере из скрипта в другой коллекции:
camera.get_fov("main:/go#camera")
-- Доступ к камере из рендер-скрипта:
render.set_camera("main:/go#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
Компонент камеры предоставляет рендер-скрипту матрицу проекции перспективной или ортографической камеры в зависимости от свойства Orthographic Projection. Матрица проекции учитывает ближнюю и дальнюю плоскости отсечения, угол обзора и соотношение сторон камеры.
Матрица вида определяет позицию и ориентацию камеры. Камера с Orthographic Projection центрирует вид на позиции игрового объекта, к которому прикреплён компонент камеры, тогда как камера с Perspective Projection располагает нижний левый угол вида на позиции игрового объекта.
Начиная с Defold 1.9.6, при использовании дефолтного рендер-скрипта Defold автоматически устанавливает последнюю включённую камеру для рендеринга. Ранее требовалось явно отправлять сообщение use_camera_projection
рендереру, чтобы уведомить его об использовании матриц камеры. Сейчас это не обязательно, но для обратной совместимости можно продолжать использовать.
Также можно явно задать конкретную камеру для рендеринга в рендер-скрипте. Это полезно, например, в многопользовательских играх для точного контроля, какая камера используется.
-- render.set_camera автоматически применит матрицы вида и проекции
-- для всего рендеринга, пока не будет вызван render.set_camera() без аргументов.
render.set_camera("main:/my_go#camera")
Чтобы проверить, включена ли камера, используйте функцию get_enabled
из Camera API:
if camera.get_enabled("main:/my_go#camera") then
-- камера включена, используем её для рендеринга
render.set_camera("main:/my_go#camera")
end
::: sidenote
Чтобы использовать set_camera
вместе с отсечением по усечённой пирамиде (frustum culling), передайте опцию:
render.set_camera("main:/my_go#camera", {use_frustum = true})
:::
Перемещайте камеру по игровому миру, перемещая игровой объект, к которому прикреплён компонент камеры. Компонент автоматически отправит обновлённую матрицу вида на основе текущих координат по осям X и Y.
Для перспективной камеры масштабирование происходит перемещением игрового объекта по оси Z. Компонент камеры автоматически обновит матрицу вида с учётом текущей позиции по Z.
Для ортографической камеры масштабирование выполняется изменением свойства Orthographic Zoom:
go.set("#camera", "orthographic_zoom", 2)
Также для ортографической камеры можно выбрать способ определения зума с помощью параметра Orthographic Mode
или из кода:
-- текущий режим (одно из: camera.ORTHO_MODE_FIXED, _AUTO_FIT, _AUTO_COVER)
local mode = camera.get_orthographic_mode("#camera")
-- включить режим "вписать" (contain), чтобы дизайн-область всегда полностью помещалась в окно
camera.set_orthographic_mode("#camera", camera.ORTHO_MODE_AUTO_FIT)
-- включить режим "заполнить" (cover), чтобы окно всегда было заполнено
-- camera.set_orthographic_mode("#camera", camera.ORTHO_MODE_AUTO_COVER)
-- вернуть "фиксированный" режим и управлять масштабом вручную через orthographic_zoom
-- camera.set_orthographic_mode("#camera", camera.ORTHO_MODE_FIXED)
Адаптивный зум — это изменение значения зума камеры при изменении разрешения экрана относительно первоначального разрешения, заданного в game.project.
Два распространённых подхода к адаптивному зуму:
Пример:
local DISPLAY_WIDTH = sys.get_config_int("display.width")
local DISPLAY_HEIGHT = sys.get_config_int("display.height")
function init(self)
local initial_zoom = go.get("#camera", "orthographic_zoom")
local display_scale = window.get_display_scale()
window.set_listener(function(self, event, data)
if event == window.WINDOW_EVENT_RESIZED then
local window_width = data.width
local window_height = data.height
local design_width = DISPLAY_WIDTH / initial_zoom
local design_height = DISPLAY_HEIGHT / initial_zoom
-- max zoom: контент изначального разрешения заполнит и выйдет за границы экрана
local zoom = math.max(window_width / design_width, window_height / design_height) / display_scale
-- min zoom: контент изначального разрешения полностью поместится в экран
--local zoom = math.min(window_width / design_width, window_height / design_height) / display_scale
go.set("#camera", "orthographic_zoom", zoom)
end
end)
end
Полный пример адаптивного зума доступен в этом примерном проекте.
Примечание: Для ортографической камеры типичное поведение «вписать/заполнить» можно получить без пользовательского кода, установив Orthographic Mode
в Auto Fit
(вписать) или Auto Cover
(заполнить). В этих режимах эффективный зум рассчитывается автоматически на основе размера окна и заданного разрешения дизайна.
Камера может следовать за игровым объектом, если сделать игровой объект с компонентом камеры дочерним по отношению к объекту, за которым нужно следить:
Альтернативный способ — обновлять позицию игрового объекта с компонентом камеры каждый кадр в соответствии с позицией объекта, за которым следят.
Когда камера смещена, масштабирована или изменена проекция с дефолтной ортографической Stretch-проекцией, координаты мыши, получаемые в функции on_input()
, больше не совпадают с мировыми координатами игровых объектов. Нужно вручную учитывать изменения вида и проекции. Код для преобразования экранных координат в мировые выглядит так:
--- Преобразует экранные координаты в мировые с учётом
-- вида и проекции конкретной камеры
-- @param camera URL камеры для преобразования
-- @param screen_x экранная координата X
-- @param screen_y экранная координата Y
-- @param z опциональный Z для преобразования, по умолчанию 0
-- @return world_x мировая координата X
-- @return world_y мировая координата Y
-- @return world_z мировая координата Z
function M.screen_to_world(camera, screen_x, screen_y, z)
local projection = go.get(camera, "projection")
local view = go.get(camera, "view")
local w, h = window.get_size()
-- https://defold.com/manuals/camera/#converting-mouse-to-world-coordinates
local inv = vmath.inv(projection * view)
local x = (2 * screen_x / w) - 1
local y = (2 * screen_y / h) - 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
return x1, y1, z or 0
end
Имейте в виду, что значения action.screen_x
и action.screen_y
из on_input()
должны использоваться как аргументы для этой функции. На странице Примеры показано использование преобразования экранных координат в мировые. Также есть примерный проект с демонстрацией этого процесса.
::: sidenote Сторонние решения для камеры предоставляют функции для преобразования координат между экраном и миром. :::
Камеры можно изменять из кода с помощью различных сообщений и свойств (подробности в API документации).
Компонент камеры имеет следующие свойства, которые можно читать и изменять через go.get()
и go.set()
:
fov
: Угол обзора камеры (number
).
near_z
: Ближняя плоскость отсечения (number
).
far_z
: Дальняя плоскость отсечения (number
).
orthographic_zoom
: Масштаб ортографической камеры (number
).
aspect_ratio
: Соотношение ширины и высоты усечённой пирамиды. Используется при вычислении проекции перспективной камеры. (number
).
view
: Вычисленная матрица вида камеры. ТОЛЬКО ДЛЯ ЧТЕНИЯ. (matrix4
).
projection
: Вычисленная матрица проекции камеры. ТОЛЬКО ДЛЯ ЧТЕНИЯ. (matrix4
).
Существуют решения сообщества, которые реализуют распространённые функции, такие как тряска экрана, следование за объектами, преобразование экранных координат в мировые и многое другое. Их можно скачать с портала Defold Asset Portal: