Понедельник, 30.12.2024, 17:25
Главная Регистрация RSS
Приветствую Вас, Гость
Поиск по сайту
Авторизация

Меню сайта
Game Maker
Если вы только-только начали изучать игрострой и еще даже не успели скачать сам Game Maker, предлагаем вам на выбор следующие версии программы:

Game Maker 8.1
Классика. Идеально подходит для создания простых 2D игр на PC. Требует активации.
Game Maker for Mac
Абсолютно та же программа, но только для пользователей Mac. Требует активации.
Game Maker Studio
Самая новая версия с возможностью кроссплатформенной разработки. Бесплатна.
Топ 5 игр
Агент Green 4.2 / 5.0
FeDo 4.2 / 5.0
To Mars: Sec... 4.2 / 5.0
To Mars+MapE... 3.9 / 5.0
Paintball 3.8 / 5.0

Топ игр составлен путем пользовательского голосования.

Если вы не согласны с какой-либо оценкой, примите участие и поставьте свой балл игре. Ваша оценка очень важна для нас ;)
Статистика



На сайте: 1
Гостей: 1
Пользователей: 0
Главная » Статьи » Разработка игр

3D-звук в Game Maker 8 как в игре ToMars Secrets of Phobos

Вероятнее всего некоторый программный код, представленный ниже не будет работать в Game Maker Studio 1 из-за отсутсвия поддержки некоторых функций. Вероятно, в Game Maker Studio 2 такая же ситуация. Поэтому, если вы используете GMS1 или GMS2, то Вам придётся изменить часть кода.

1. Качаем пример отсюда или отсюда, или гуглим по ключевым фразам GMFMODSimple, FMOD для Game Maker или что-то подобное.

2. Ознакамливаемся с примерами, имеющимися в архиве.

3. Замечаем, что в примерах имеются очень много скриптов.

4. Импортируем скрипты из примера в свой проект, или просто копируем. Все скрипты не понадобятся, да и на размер игры/производительность может сказаться не лучшим образом. Вот эти функции использовались в игре ToMars Secrets of Phobos:

Так что для большинства задач этого хватит. В будущем, можно будет добавить и остальные функции.

5. Копируем fmodex.dll и GMFMODSimple.dll в папку со своим проектом.

6. Складываем звуки, которые будут звучать Вашей игре через FMOD в папку со своим проектом, а лучше сделать подпапку для звуков. В ToMarsSoP использовались форматы звуков wav и ogg, но скорее всего FMOD поддерживает и другие форматы.

7. Теперь пишем код для инициализации библиотеки FMOD. Напишите код в таком месте, чтобы он выполнился один раз в начале игры:

[code] LoadFMOD(); //Объявляются все нужные переменные, которые нужны будут для работы с dll-файлами от FMOD

FMODinit(100, false); //Не помню, что означаем 100 и false

FMODSetWorldScale(0.04); //Устанавливаем коэффициент масштаба размеров мира, для перевода пикселей в метры. В ToMarsSoP стояло число 0.04, что означает, что 1 пиксель игрового мира соответствует 0.04 метра (4 см) в реальном мире. Будет использоваться для правильного расчёта эффекта Допплера

FMODSetDopplerFPS(60) //Указываем, какой FPS в Ваше игре. Также используется для расчёта эффекта Допплера

FMODMasterSetVolume(1.0); //Устанавливаем громкость. 1.0 соответствует громкости в 100% [/code]

8. Для удобной загрузки звуков в ToMarsSoP был создан скрипт LoadSoundFoFMOD. Его можно скопировать отсюда (скрипт писался во времена создания ToMarsSoP, сорри за стиль):

[code]//Скрипт создаёт глобальную переменную с названием звука, в которую вписан id звука для проигрывания через FMOD

//argument0 - относительный путь к файлу (с именем и расширением), например: "sound/weapon/marker1.wav"

//argument1 - громкость для нового звука

//argument2 - максимальное расстояние, на котором громкость максимальна

//argument3 - максимальное расстояние, на котором звук ещё слышен

//Если argument2 == 0 и argument3 == 0, то звук загружается как 2D, в противном случае в 3D

if !file_exists(argument0)

exit

i=1

name_file=''

repeat string_length(argument0) //отсекаем путь своим способом

{

if string_char_at(argument0,i)<>'/' and string_char_at(argument0,i)<>'\'

{

name_file+=string_char_at(argument0,i);

i += 1;

}

else

{

name_file = '';

i += 1;

}

}

//отсекаем всё, после точки

i = 1;

var_name = '';

repeat string_length(name_file)

{

if (string_char_at(name_file,i)<>'' and string_char_at(name_file,i)<>'.' and string_char_at(name_file,i)<>' ')

{

var_name+=string_char_at(name_file,i);

i += 1;

}

else

{

var_name += '_snd';

break;

}

}

is_3d = 1;

if argument2 == 0

if argument3 == 0

is_3d=0;

if is_3d=1

{

variable_global_set(var_name,FMODSoundAdd(argument0,1));

FMODSoundSetMaxVolume(variable_global_get(var_name),argument1); //настраиваем макс. громкость для нового звука

FMODSoundSetGroup(variable_global_get(var_name), 4); //настраиваем какую-то группу для нового звука

FMODSoundSet3dMinMaxDistance (variable_global_get(var_name),argument2, argument3); //настраиваем макс. расстояние, на котором ещё слышно

}

else

{

variable_global_set(var_name,FMODSoundAdd(argument0));

FMODSoundSetMaxVolume(variable_global_get(var_name), argument1); //настраиваем макс. громкость для нового звука

FMODSoundSetGroup(variable_global_get(var_name),4); //настраиваем какую-то группу для нового звука

}

[/code]

9. После кода, который мы писали выше для инициализации FMOD пишем следующее:

[code]

LoadSoundFoFMOD("sound/weapon/RPG7.wav", 1, 10, 1500); //Звук выстрела из РПГ-7

LoadSoundFoFMOD("sound/weapon/m79.wav", 1, 10, 900 ); //Звук выстрела из M-79

LoadSoundFoFMOD("sound/weapon/AK74M.wav", 1, 10, 1800); //Звук выстрела из АК-47М

LoadSoundFoFMOD("sound/weapon/distant2.ogg", 0.8, 1000, 4000); //Звук выстрела из чего-то на большим расстоянии

//и т. д. для остальных звуков

[/code]

Тут мы вызываем несколько раз написанный нами скрипт LoadSoundFoFMOD. Первым аргументом скрипта идёт путь до звукового файла, который мы хотим загрузить. Путь указывается относительно исполнительного файла Ваше игры. Вторым аргументом идёт базовая громкость звука (1 == 100% громкости). Третьим аргументом идёт расстояние в пикселях, от источника звука до "слушателя", на котором громкость будет оставаться максимальной. Четвёртым аргументом идёт расстояние в пикселях, на котором звук уже не слышен. Если Вы хотите, чтобы FMOD воспроизводил звук без эффекта 3D, то два последних аргумента можно не указывать, или указать значение 0. После каждого вызова функции при удачной загрузки звука будет создаваться глобальная переменная, которая будет содержать ID (идентификатор) загруженного звука. Эти переменные с ID звука мы будем использовать в дальнейшем. Например, для первого звука "sound/weapon/RPG7.wav" будет создана переменная global.RPG7_snd, которая будет содержать ID звука выстрела из РГП-7, для второго звука будет создана переменная global.m79_snd, которая будет содержать ID звука выстрела из M-79 (гранатомёт как у терминатора из "Терминатор 2") и т.д. Обратите внимание, регистры символов названия переменной будут соответстовать регистрам символов имени файла. Не используйте в своей игре одинаковые имена файлов звуков, даже если эти файлы будут находиться в разных папках. Иначе некоторые звуки не получится воспроизвести. В противном случае, Вам придётся переделать функцию LoadSoundFoFMOD, чтобы у Вас была поддержка звуков с одинаковым именем файлов.

10. На этом подготовительную часть мы закончили. Теперь напишите следующий код, который будет вызываться каждый шаг (тик/кадр), например, в событии End Step какого-нибудь объекта:

[code]

FMODListenerSet3dPosition (1, view_xview+view_wview / 2, view_yview + view_hview / 2, 0); //Обновляем позицию слушателя

FMODUpdate(); //Обновляем состояние библиотеки FMOD

[/code]

Первым аргументом FMODListenerSet3dPosition идёт номер слушателя, начиная с единицы. В большинстве случаев менять не нужно, хотя Вы можете поэкспериментировать. Вторым и третьим аргументов идёт координаты x и y, которые отражают позицию слушателя в игровом пространстве. Выражение "view_xview+view_wview / 2" и "view_yview + view_hview / 2" означает, что слушатель будет привязан к середине нулевого вида, но Вы можете привязать координаты слушателя, например, к главному герою Вашей игры. Третьим аргументом идёт координата z, которая в большинстве случаев в 2D-играх всегда указывается как 0.

11. Теперь, чтобы воспроизвести какой-либо 3D-звук, достаточно вызвать функцию FMODSoundPlay3d:

[code]

FMODSoundPlay3d(global.RPG7_snd, x, y, 0, false);

[/code]

Первым аргументом указывается ID звука, который мы хотим воспроизвести. В нашем случае, первым аргументом указана переменная global.RPG7_snd, которая содержит в себе ID звука выстрела из РПГ-7. Второй и третий аргумент - x и y координаты источника звука. Четвёртый аргумент - z-координата источника звука, в 2D-играх обычно ставят 0. Пятый аргумент - поставить ли этот звук на паузу, обычно тут ставится false. Даже не могу привести пример, в каких случаях может понадобиться поставить тут true.


Примечание 1: Если звук был загружен с помощью LoadSoundFoFMOD без указанных двух последних параметров или с указанными параметрами со значениями 0, то воспроизводить такие звуки можно только с помощью функции FMODSoundPlay, в противном случае могу быть ошибки. Первым параметром FMODSoundPlay принимает ID звука, вторым - поставить ли этот звук на паузу


Примечание 2: FMODSoundPlay3d возвращает 0 в случае ошибки или ID экземпляра воспроизведённого звука, в случае успеха (ID звука и ID экземпляра звука не одно и то же!). ID экземпляра звука можно будет использовать в дальнейшем, для управления экземпляром звука, например, для изменения скорости воспроизведения, питча прямо во время воспроизведения или чтобы поставить экземпляр звука на паузу. Работа с экземплярами звука очень мощная функция, однако это тема для отдельной статьи. К тому же, когда создавался ToMarsSoP не использовались возможности для работы с экземплярами звука, поэтому данную темя предлагаю для самостоятельного изучения. Аналогично, FMODSoundPlay возвращает 0 в случае ошибки или ID экземпляра воспроизведённого звука, в случае успеха.


Примечание 3: В ToMarsSoP при каждом выстреле из огнестрельного оружия без глушителя воспроизводится сразу два звука. Например, при выстреле из AK74M воспроизводится звук global.AK74M_snd и global.distant2_snd. Таким образом, вблизи слышится звук выстрела global.AK74M_snd, а при отдалении отчётливее слышится звук global.distant2_snd, который больше соответствует звуку выстрела на большом расстоянии. Это достигается благодаря тому, что при загрузке "sound/weapon/distant2.ogg" указывалось максимальное расстояние, на котором слышится этот звук в несколько раз больше, чем максимальное расстояние, на котором слышится звук "sound/weapon/AK74M.wav". То есть 1800 пикселей у "sound/weapon/AK74M.wav" и 4000 пикселей у "sound/weapon/distant2.ogg".


Примечание 4: В ToMarsSoP не использовалось панорамирование. То есть неважно, где находится источник звука, справа или слева от слушателя, он всегда будет воспроизводится с одинаковой громкостью в правом и левом канале. Данная тема предлагается для самостоятельного изучения.

12. Ну, а теперь, чтобы при выходе из игры не возникало никакой ошибки, вставьте код в событие Game End какого-нибудь объекта, который будет существовать до тех пор, пока не выйдите из игры:

[code]

FMODAllStop(); //Останавливаем все звуки
FMODfree(); //Отключаем библиотеку FMOD и высвобождаем оперативную память, занятую звуками и нуждами самой FMOD

[/code]

UPD: в архив добавил простой пример StereoSimpleDemo.gmk реализациий трёхмерного стереозвучания для игры с видом сверху
Категория: Разработка игр | Добавил: sasha (25.08.2020) | Автор: sasha
Просмотров: 1155 | Комментарии: 8 | Теги: FMOD, GMFMOD, 3дзвук, 3dзвук | Рейтинг: 5.0/1
Всего комментариев: 8
8 sasha   (14.02.2021 02:22) [Материал]
sasha UPD: в архив добавил простой пример StereoSimpleDemo.gmk реализациий трёхмерного стереозвучания для игры с видом сверху

0
4 BRESS   (27.08.2020 16:32) [Материал]
BRESS То, что в GMS не работает, наверное, не критично особо. Там FMOD и не нужен, т.к. есть встроенный звуковой движок со всеми необходимыми плюшками.

Но для олдов на GM8 это мастхев (хотя на мой взгляд 3д звук в 2д играх - лишее)

P.S. Эх надо стайл листингов поправить... но все лень.

0
1 UNIT02GS   (26.08.2020 16:39) [Материал]
UNIT02GS Интересная вещь. Получилось сделать звук костра в 3D пространстве. Звучит гораздо лучше чем со стандартными функциями GM. А как быть например во время паузы игры?

Стандартные функции GM очень ограничены, практически не юзабельны. Я например делал так:
- Писал sound_global_volume(0) 
- Потом sound_stop(фоновая музыка)

А потом, когда игра возобновлялась:
- sound_global_volume(1)
- sound_loop(фоновая музыка)

С FMOD можно сделать не полную остановку звука, а именно паузу? Что бы потом при возобновлении все звуки воспроизвелись с того же места?

2 sasha   (26.08.2020 18:55) [Материал]
sasha Да, такое возможно. Если посмотреть в пример к GMFMOD в папке со скриптами GMFMODSimple/SoundInstances есть скрипты, которые позволяют взаимодействовать с проигрывающимся звуками в данный момент. Для того, чтобы поставить на паузу или снять с паузы проигрывающийся в данный момент звук (экземпляр звука) есть скрипт FMODInstanceSetPaused, который первым аргументом принимает ID экземпляра звука (не ID звука), вторым аргументом true или false,  в зависимости от того, нужно ли ставить на паузу или снять с паузы. ID экземпляра звука возвращают скрипты, которые лежат в папке GMFMODSimple/PlayingSounds Правда, сам я этим не пользовался, сказать на сколько всё хорошо работает не могу. Кстати, в примере в папке со скриптами

0
3 UNIT02GS   (27.08.2020 11:03) [Материал]
UNIT02GS Что-то вроде этого? Мне кажется я что-то делаю не так. Потому что это не срабатывает. 

FMODInstanceSetPaused(global.sou_bonefire_snd, true);

5 sasha   (27.08.2020 21:28) [Материал]
sasha Не) Что-то вроде этого:
Допустим, я воспроизвёл звук выстрела из РПГ-7 через FMODSoundPlay3d:

Код
some_sound_instance = FMODSoundPlay3d(global.RPG7_snd, x, y, 0, false);
Таким образом, в переменную some_sound_instance будет записан ID экземпляра. Теперь, чтобы поставить на паузу этот экземпляр звука, можно вызвать такой код:

Код
FMODInstanceSetPaused(some_sound_instance, true);
Соответственно, чтобы снять с паузы экземпляр some_sound_instance:

Код
FMODInstanceSetPaused(some_sound_instance, false);

Для лучшего понимания, зачем тут нужны ID экземпляров звука:

При каждом воспроизведении звука через FMODSoundPlay3d или через FMODSoundPlay создаётся новый ID экземпляра. То есть, такой код заставит вопроизвестись звук global.RPG7_snd дважды в одно и то же время:

Код
some_sound_instance1 = FMODSoundPlay3d(global.RPG7_snd, x, y, 0, false);
some_sound_instance2 = FMODSoundPlay3d(global.RPG7_snd, x, y, 0, false);
А такой код поставит на паузу только первый экзмепляр звука:

Код
FMODInstanceSetPaused(some_sound_instance1, true);
А экземпляр звука some_sound_instance2 продолжить звучать.

Ещё есть такой вариант:

В примере в папке со скриптами я находил папку Groupings, в которой, судя по всему, находятся скрипты для управления целыми группами звуков. Например, с помощью FMODGroupSetPaused можно ставить на паузу сразу целую группу звуков. Скорее всего, как-то можно помещать разные звуки через FMODSoundSetGroup. Сам я уже этого не помню, если честно). Я думаю, что для удобства можно поместить звуки, которые могут быть поставлены на паузу во время паузы в игре в отдельную группу, чтобы не нужно было ставить на паузу отдельные звуки. Об этом я раньше не знал, поэтому не юзал.

0
6 UNIT02GS   (28.08.2020 04:58) [Материал]
UNIT02GS Есть первые успехи. Я обратил внимание, что в твоем скрипте LoadSoundFoFMOD в конце уже есть строчки со скриптом FMODSoundSetGroup. Вместо стандартного значения я выставил туда argument4. Получается теперь можно сразу указать нужную группу. А после уже спокойно вызывать FMODGroupSetPaused. Осталось только по новому адаптировать звуковую систему игры. Будем разбираться дальше.

7 sasha   (28.08.2020 10:55) [Материал]
sasha Да, действительно. Как-то я не обратил внимание на FMODSoundSetGroup)

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]