PDA

Просмотр полной версии : Звуки с ожиданием



Эрендир
18.07.2014, 18:45
Периодически мне задают вопросы по звукам в скриптах, хотя где-то я уже выкладывал на форуме соответствующую инструкцию. Сегодня хочу рассказать, как всё же сделать звуковую библиотеку и скриптом проигрывать из неё файлы с ожиданием окончания проигрывания.

Как известно, для проигрывания звуков в Trainz есть функция у абстрактного класса World

PlaySound(Asset asset, string filename, float volume, float minDistance, float maxDistance, GameObject target, string attachmentPoint, bool looping);
До Trainz 2012 это функция возвращала float значение соответствующее длине проигрываемого звукового файла. Достаточно было это значение только подставить в Sleep, и всё прекрасно работало.
Однако, с введением в Trainz 2012 эффекта Доплера длина звукового файла фактически перестала быть константой. В связи с этим, N3V Games отказались от привычной работы функции PlaySound, которая перестала возвращать значение соответствующее длине проигрываемого звукового файла. Значит, привычный способ реализации звуков, особенно зацикленных, больше не подходит. Как быть? Выходит, что знать длину звукового файла нам надо заранее. Есть разные способы реализации этого подхода, однако здесь я хочу поделиться тем способом, который я сделал для себя. Этот способ, на мой взгляд, наиболее универсален.

Первое что необходимо сделать, так это написать обёртку для функции PlaySound. Выглядеть она будет вот так:

public final void PlaySoundAndSleep(Asset srcAsset, string soundFile, float volume, float minDistance, float maxDistance, GameObject srcObject, string att, float subtime)
{
World.PlaySound(srcAsset, soundFile, volume, minDistance, maxDistance, srcObject, att);
Soup wavdb = srcAsset.GetConfigSoup().GetNamedSoup("extensions").GetNamedSoup("sound-length-base");
me.Sleep(wavdb.GetNamedTagAsFloat(soundFile, 10.0) - subtime);
}

Набор параметров здесь такой же, как и у оригинальной функции, кроме параметра subtime:

srcAsset - ссылка на актив, который содержит звуковые файлы. Одним словом, это наша библиотека звуков.
soundFile - Путь к звуковому файлу. Напоминаю, что это относительный путь от корня актива (где лежит config.txt)
volume - громкость проигрываемого звука. Значения от 0.0 - 1.0. Хочу обратить внимание, что 1.0 - это оригинальная громкость звукового файла. Значения выше 1.0 ставить нет смысла, ибо громкость выше не станет.
minDistance - расстояние в метрах от точки проигрывания звука, на котором затухание звука будет отсутствовать (громкость будет равна заданной в volume)
maxDistance - расстояние, на котором звук затухнет полностью. Это значение должно быть больше, чем minDistance
srcObject - это непосредственно объект, в котором находится точка привязки к звуку. (если скрипт у нас в этом объекте, то me)
att - имя точки привязки, от которой будет исходить звук. (имеет формат a.name)
subtime - дополнительный параметр позволяющий сокращать или удлинять длину звука для более плавного перехода одного звука к другому или в зацикленных звуках. Задаётся в секундах. Положительно значение уменьшает ожидание, отрицательное увеличивает.


Это функцию нужно просто скопировать в тот скрипт, откуда будет производиться проигрывание звука.

И так, модифицированная функция есть, теперь нужно создать звуковую библиотеку. По сути, это может быть абсолютно любой актив, содержащий звуки. Их можно положить в локомотив, тогда его актив будет звуковой библиотекой. Для кабины можно положить звуки в актив кабины, и тогда она будет звуковой библиотекой. А можно все звуки вынести в отдельный актив, откуда их и использовать и в кабине, и в локомотиве, и где бы то ни было ещё.
После создания актива со звуками, необходимо указать длины этих звуков, которые будет использовать модифицированная функция для создания паузы. Для получения длин звуков я рекомендую воспользоваться программой от agmike. Предлагаю немного модифицированный вариант.

:click-me: (https://yadi.sk/d/edOkIs8EWrsUh)

В архиве папка с 3-мя файлами. Надо эту папку распаковать,звуковые файлы кинуть в неё же. Затем запустить run.cmd. После того, как программа завершиться, необходимо открыть блокнотом файл len.txt. В нём будут все длины файлов уже в том виде, в котором их необходимо будет вставить в config.txt файл звуковой библиотеки

Перейдём к config.txt файлу. В нём необходимо создать стандартный блок расширений extensions. Выглядит это вот так

extensions
{

}
Затем, внутри этого блока необходимо создать блок, который и будет содержать длины звуковых файлов. Это будет выглядеть так

extensions
{
sound-length-base
{


}
}
И уже в блок sound-length-base необходимо вставить то, что получилось в файле len.txt. Конечный вариант файла конфигурации будет выглядеть так

extensions
{
sound-length-base
{
compressor_run.wav "1.435"
compressor_start.wav "0.992"
compressor_stop.wav "0.627"
fuelpump.wav "8.852"
oil_pump_run.wav "2.005"
oil_pump_start.wav "0.747"
oil_pump_stop.wav "1.569"
engine_start.wav "13.550"
engine_stop.wav "6.339"
}
}

Останется только получить актив библиотеки в скрипте, который и будет передан в качестве первого параметра для модифицированной функции.
Если звуки у нас в том же активе в котором скрипт, то это можно сделать вызвав функция GetAsset (http://online.ts2009.com/mediaWiki/index.php/Class_TrainzGameObject). Она вернёт ссылку на актив, в котором выполняется скрипт.
Если же звуки лежат в отдельном активе, то его необходимо прописать в kuid-table config.txt того актива, в котором выполняется скрипт, и с помощью функции FindAsset (http://online.ts2009.com/mediaWiki/index.php/Class_Asset#FindAsset) вытащить на него ссылку.
Подробнее об этих функциях можно узнать на wiki разработчиков
:click: (http://online.ts2009.com/mediaWiki/index.php/TrainzScript_Library_Reference)

Надеюсь, что эта статья поможет начинающим скриптерам .... и не только

leha ya !
23.07.2015, 08:04
подскажите пожалуйста как можно прикрутить звуки дизеля от скриптового локомотива к локомотиву с простым запуском и расходом !?

ArtyemLavrov
02.09.2016, 15:18
Для более похожей замены World.PlaySound, может кому поможет:


float World_PlaySound(Asset srcAsset, string soundFile, float volume, float minDistance, float maxDistance, GameObject srcObject, string att) {
World.PlaySound(srcAsset, soundFile, volume, minDistance, maxDistance, srcObject, att);
Soup wavdb = srcAsset.GetConfigSoup().GetNamedSoup("extensions" ).GetNamedSoup("sound-length-base");
return wavdb.GetNamedTagAsFloat(soundFile, 10.0));
}

TRam_
02.09.2016, 15:21
Soup wavdb = srcAsset.GetConfigSoup().GetNamedSoup("extensions" ).GetNamedSoup("sound-length-base");
лучше её получить заранее 1 раз, и потом везде использовать.

ArtyemLavrov
15.12.2016, 18:11
Сообщение от ArtyemLavrov
Soup wavdb = srcAsset.GetConfigSoup().GetNamedSoup("extensions" ).GetNamedSoup("sound-length-base");
лучше её получить заранее 1 раз, и потом везде использовать.
А вдруг разные библиотеки звуков?

TRam_
15.12.2016, 18:47
ArtyemLavrov, конфиги в trainz "на лету" в процессе игры не редактируются. А то что ты предполагаешь (что у разных локов объект скрипта подгружается один) - в корне не верно, каждая секция локомотива подгружает и инициализирует свой собственный экземпляр класса со своим собственным рефференсом на свою звуковую бибилотеку и её конфиг.

ArtyemLavrov
15.12.2016, 19:15
Ты меня не понял. Ладно, проехали.

kemal
15.12.2016, 20:02
Тогда подгрузить суп для каждой.



New