Реализация звука в Defold проста, но мощна. Есть лишь две концепции, о которых необходимо знать:
Звуковые компоненты могут быть инстанцированы только на месте в игровом объекте. Создайте новый игровой объект, кликните на нем ПКМ и выберите Add Component ▸ Sound.
Созданный компонент имеет набор свойств, которые должны быть настроены:
При правильной настройке компонента Sound можно заставить его воспроизвести звук, вызвав sound.play()
:
sound.play("go#sound", {delay = 1, gain = 0.5, pan = -1.0, speed = 1.25})
Звук будет продолжать воспроизводиться, даже если игровой объект, к которому принадлежал компонент Sound, будет удален. Можно вызвать sound.stop()
, чтобы остановить звук (см. ниже).
Каждое сообщение, отправленное компоненту, заставляет его воспроизводить другой экземпляр звука, пока доступный звуковой буфер не будет заполнен и движок не выведет ошибки в консоль. Рекомендуется реализовать какой-либо механизм фильтрации и группировки звуков.
Если необходимо остановить воспроизведение звука, можно вызвать sound.stop()
:
sound.stop("go#sound")
Звуковая система имеет 4 уровня усиления:
sound.play()
или при изменении усиления голоса через вызов sound.set_gain()
.sound.set_group_gain()
.sound.set_group_gain(hash("master"))
.Выходное усиление является результатом перемножения этих 4 усилений. По умолчанию коэффициент усиления везде равен 1.0 (0 dB).
Любой звуковой компонент с указанным именем звуковой группы будет помещен в звуковую группу с этим именем. Если группа не указана, звук будет отнесен к группе “master”. Также можно явно задать звуковому компоненту группу “master”, что даст тот же эффект.
Имеется несколько функций для получения всех доступных групп, получения строки с именем, получения и установки усиления, среднеквадратичного (RMS, см. http://en.wikipedia.org/wiki/Root_mean_square) и пикового усиления. Также есть функция, позволяющая проверить, запущен ли музыкальный проигрыватель на целевом устройстве:
-- Если на этом iPhone/Android-устройстве воспроизводится звук, заглушить все
if sound.is_music_playing() then
for i, group_hash in ipairs(sound.get_groups()) do
sound.set_group_gain(group_hash, 0)
end
end
Группы идентифицируются с помощью хэш-значения. Строку имени можно получить с помощью sound.get_group_name()
, которую можно использовать для отображения имен групп в инструментах разработки, например, в микшере для тестирования уровней групп.
Вы не должны писать код, который полагается на строковое значение звуковой группы, поскольку они недоступны в релизных сборках.
Все значения линейны в диапазоне от 0 до 1.0 (0 dB). Для преобразования в децибелы просто используйте стандартную формул:
\[db = 20 \times \log \left( gain \right)\]for i, group_hash in ipairs(sound.get_groups()) do
-- Строка имени доступна только в отладке. В релизе возвращается "unknown_*".
local name = sound.get_group_name(group_hash)
local gain = sound.get_group_gain(group_hash)
-- Преобразовать в децибелы.
local db = 20 * math.log10(gain)
-- Получите RMS (среднеквадратичное значение коэффициента усиления). Левый и правый канал отдельно.
local left_rms, right_rms = sound.get_rms(group_hash, 2048 / 65536.0)
left_rmsdb = 20 * math.log10(left_rms)
right_rmsdb = 20 * math.log10(right_rms)
-- Получить пик усиления. Левый и правый отдельно.
left_peak, right_peak = sound.get_peak(group_hash, 2048 * 10 / 65536.0)
left_peakdb = 20 * math.log10(left_peak)
right_peakdb = 20 * math.log10(right_peak)
end
-- Группе "master" задать усиление +6 dB (math.pow(10, 6/20)).
sound.set_group_gain("master", 1.995)
Если игра воспроизводит один и тот же звук по событию, и это событие срабатывает часто, существует риск воспроизведения одного и того же звука два раза или более одновременно. Если это произойдет, звуки будут сдвинуты по фазе, что может привести к появлению очень заметных артефактов.
Самый простой способ решить эту проблему — построить шлюз, который будет фильтровать звуковые сообщения и не позволит воспроизводить один и тот же звук более одного раза в течение заданного интервала времени:
-- Не допустить воспроизведение одного и того же звука в течение интервала "gate_time".
local gate_time = 0.3
function init(self)
-- Store played sound timers in a table and count down each frame until they have been
-- in the table for "gate_time" seconds. Then remove them.
self.sounds = {}
end
function update(self, dt)
-- Count down the stored timers
for k,_ in pairs(self.sounds) do
self.sounds[k] = self.sounds[k] - dt
if self.sounds[k] < 0 then
self.sounds[k] = nil
end
end
end
function on_message(self, message_id, message, sender)
if message_id == hash("play_gated_sound") then
-- Only play sounds that are not currently in the gating table.
if self.sounds[message.soundcomponent] == nil then
-- Store sound timer in table
self.sounds[message.soundcomponent] = gate_time
-- Play the sound
sound.play(message.soundcomponent, { gain = message.gain })
else
-- An attempt to play a sound was gated
print("gated " .. message.soundcomponent)
end
end
end
Чтобы использовать шлюз, достаточно отправить ему сообщение play_gated_sound
и указать целевой звуковой компонент и усиление звука. Шлюз вызовет sound.play()
с целевым звуковым компонентом, если шлюз открыт:
msg.post("/sound_gate#script", "play_gated_sound", { soundcomponent = "/sounds#explosion1", gain = 1.0 })
Не получится заставить шлюз слушать сообщения play_sound
, поскольку это имя зарезервировано движком Defold. Вы получите неожиданное поведение, если будете использовать зарезервированные имена сообщений.
Звуками можно управлять во время выполнения с помощью ряда различных свойств (обращайтесь к документации по API). Следующими свойствами можно манипулировать с помощью go.get()
и go.set()
:
gain
number
).pan
number
). Панорамирование должно быть значением между -1 (-45 градусов влево) и 1 (45 градусов вправо).speed
number
). Значение 1.0 — нормальная скорость, 0.5 — половина скорости и 2.0 — двойная скорость.sound
hash
). Путь к ресурсу может быть использован для изменения звука с помощью resource.set_sound(path, buffer)
. Пример:local boom = sys.load_resource("/sounds/boom.wav")
local path = go.get("#sound", "sound")
resource.set_sound(path, boom)
В файле game.project имеются несколько настроек проекта, относящихся к звуковым компонентам.
Did you spot an error or do you have a suggestion? Please let us know on GitHub!
GITHUB