Мобильная версия сайта | |||||||||
[Главная] | [Новости] | [Статьи] |
[Проекты] |
[Ссылки] |
[Автор] |
||||
[Архив новостей] | |||||||||
[Форум] | на форуме можно задать вопрос, посмотреть ответы на часто задаваемые вопросы | ||||||||
Здравствуйте! Вы попали на информационно-образовательный сайт посвященный информатике, информационным технологиям и компьютерным играм. Подробнее о целях и задачах сайта в разделе Главная. [English version of this page here...] | |||||||||
[Базовые уроки по DirectX] [Основы DirectMusic на Delphi] [Основы DirectInput8 на Delphi] [Основы DirectSound8 на Delphi] | |||||||||
[Разработка компьютерной игры] [Пример игры Donuts3D] | |||||||||
12/06/2008 Воспроизведение файлов в форматах *.it, *.xm, *.s3m, *.mod продолжение... |
|||||||||
[назад] | |||||||||
Теперь рассмотрим код, который должен осуществляться при уничтожении приложения - во время закрытия окна формы в данном примере - procedure TfrmMain.FormClose |
|||||||||
FMUSIC_StopAllSongs();
//останавливаем
все играющие звуковые файлы for Index := 0 to MAX_SONGS - 1 do begin if FSongs[Index].Module <> nil then begin FMUSIC_FreeSong(FSongs[Index].Module); //освобождаем ресурсы памяти от трекерских файлов и end else if FSongs[Index].Stream <> nil then begin FSOUND_Stream_Stop(FSongs[Index].Stream); //файлов-потоков (таких как wav, mp2, mp3, ogg и подобных) FSOUND_Stream_Close(FSongs[Index].Stream); end; end; FSpectrum.Free; //удаляем объект спектрального анализатора FMOD_Unload; //и выгружаем библиотеку fmod.dll из памяти |
|||||||||
Мы выяснили что должно происходить во время старта и уничтожения приложения. Рассмотрим как осуществить загрузку, выгрузку, проигрывание, останов, регулировку позиции текущего паттерна, громкости, организацию одновременного воспроизведения нескольких файлов и прочие особенности. |
|||||||||
загрузка - procedure TfrmMain.btnLoadClick Проверяем сколько файлов уже есть в списке и выводим предупреждение об ошибке если их больше допустимого SongCount := lbxFiles.Items.Count;
if SongCount = MAX_SONGS then |
|||||||||
Для очередного элемента открытых файлов - Пробуем открыть файл как трек, а затем как поток Stream
:= nil; Если никак не удалось - снова предупреждение
if (Module = nil) and (Stream = nil) then |
|||||||||
Если трек загрузился, то установить громкость для данного трека на максимум, а шаг панорамы на 15% if
Module <> nil then |
|||||||||
Присваиваем полученные обработчики трека и потока данному элементу массива воспроизводимых файлов, индикатор проигрывания сброшен FSongs[SongCount].Module
:= Module; lbxFiles.Items.Add(ExtractFileName(dlgOpen.Files[Index]));
//эта особенность актуальна лишь
для примера testbed.dpr |
|||||||||
После этого вызывается псевдо-щелчок по файлу. Это приводит к считыванию текущих параметров из модуля (потока) данного файла, но это уже более актуально для примера testbed.dpr, хотя что-то может пригодиться и в игровом приложении {...} lbxFilesClick(nil); |
|||||||||
выгрузка мелодии из памяти - procedure TfrmMain.btnDeleteClick определяем текущий элемент списка и останавливаем, Index
:= lbxFiles.ItemIndex; btnStopClick(nil); |
|||||||||
а затем удаляем его - lbxFiles.Items.Delete(Index); |
|||||||||
Воспроизведение мелодии - procedure TfrmMain.btnPlayClick Выбранная мелодия останавливается, если она уже играла Index := lbxFiles.ItemIndex;
if Index < 0 then
if FSongs[Index].Playing then Включаем воспроизведение текущей мелодии списка if
FSongs[Index].Module <> nil then |
|||||||||
или потока, если это поток else
if FSongs[Index].Stream <> nil then |
|||||||||
если звуковой поток уже играет, то включить воспроизведение стерео, громкость на максимум else |
|||||||||
Остановка воспроизведения - procedure TfrmMain.btnStopClick Определяем текущую мелодию Index := lbxFiles.ItemIndex;
if Index < 0 then Если это трекерский модуль - применяем команду остановки для него
if FSongs[Index].Module <> nil then если
это потоковое аудио - применяем другую команду остановки Текущий
канал потока - неопределен, индикатор проигрывания сброшен |
|||||||||
Регулировка громкости текущей мелодии - Если не установка регулятора глобальной громкости if
not FSettingMasterVolume then Определяем
текущую композицию для
модуля применяем свою команду //регулятором для
потока - свою //регулятором |
|||||||||
Регулировка текущего воспроизводимого паттерна в трекерском модуле - переход к предыдущему паттерну порядка воспроизведения - procedure
TfrmMain.btnPrevOrderClick(Sender: TObject); считываем
текущий модуль если
это трекерский модуль - считываем текущий индекс элемента порядка воспроизведения
и уменьшаем его на 1 |
|||||||||
для переключения на следующий паттерн всё аналогично кроме строк - т.е. приращаем индекс на +1 if
Order < FMUSIC_GetNumOrders(FSongs[Index].Module) then |
|||||||||
внутри метода периодической работы таймера представлены ряд интересных команд - procedure
TfrmMain.tmrMainTimer(Sender: TObject); для
игрового проекта это по большому счету не особо нужная информация, но
все-таки полезна //это
полезно, т.к. для музыки не существует такого понятия как FPS, зато вышеуказанные
параметры могут служить в какой-то мере для целей оценки быстродействия
работающего проекта |
|||||||||
Конфигурирование - выбор драйвера и параметров фильтрации - Настройки конфигурирования происходят в модуле формы TfrmConfig - С точки зрения наших задач заслуживает внимания метод модуля config.pas - Считываются параметры установленные в окне формы конфигуратора и применяются к объекту FSOUND. procedure
TfrmConfig.btnOkClick(Sender: TObject); |
|||||||||
Оставшиеся нерассмотренными здесь методы, я думаю, Вы разберете самостоятельно. | |||||||||
Теперь переходим к практическим упражнениям - реализации использования FMOD 3.75 для воспроизведения музыки и звуков в трекерских и потоковых форматах. | |||||||||
Файл fmod.dll размещаем в папке проекта, в настройках проекта указываем ссылку на интерфейсы в delphi-исходниках - fmod375; В секции interface uses добавляем ссылку на fmodtypes В секции implementation uses добавляем ссылки на fmod, fmoderrors
Внутри класса приложения объявляем 2 метода - //music
functions |
|||||||||
Пишем реализацию данных методов - procedure
TD3DGameApp.InitMusicLib;
{ Check version numbers }
{ Initialize FSOUND }
if not FSOUND_Init(22050, 128, 0) then
{ Initialize song list to empty }
FTrackNumber := 0; LoadPlaylist(DefaultThemes); //данный метод будет реализован далее (см. ниже) end; |
|||||||||
procedure
TD3DGameApp.FreeMusicLib; FreePlayList; //данный метод будет реализован далее (см. ниже) FMOD_Unload; |
|||||||||
Как видим нам почти ничего даже переделывать не пришлось, только опустили кое-какой код и изменили вызовы MessageBox. | |||||||||
Я организую вызов данных методов внутри TD3DGameApp.CreateSoundObjects и TD3DGameApp.DestroySoundObjects. Где будете делать это Вы - решать Вам. Можете поступить аналогично. Следует иметь в виду, что метод InitMusicLib должен вызываться только после того, как окно приложения будет создано и обработчик окна - m_hWnd в нашем случае обретет своё действительное значение - в противном случае будут только ошибки... ошибки... и ошибки...
|
|||||||||
Теперь реализуем загрузку нужных мелодий в список. Для удобства и наименьших изменений кода можно сделать это организовав загрузку требуемого списка мелодий из обычного текстового файла, где бы каждая строка соответствовала полному имени файла внутри дистрибутива игры. Таким способом и Вы и Ваши пользователи будут вольны не только слушать в игре то что было предопределено ее дистрибутивом, но и любые другие файлы мелодий поддерживаемых форматов. | |||||||||
Единственным ограничением списка воспроизведения является количество файлов в нем - не более 512, но это ограничение легко обойти использовав столько плей-листов сколько нужно. Конечно же в каждый момент времени работа будет осуществляться только с выбранным списком. | |||||||||
Загрузка списка мелодий из текстового файла const DefaultThemes = 'Media\Music\muzon_themes.txt'; - Код уже должен быть Вам знаком по предыдущему повествованию, особо нового ничего нет procedure
TD3DGameApp.LoadPlaylist(PlayList: string); создаем
список строк будущего плей-листа и загружаем SongCount := FTMSPlayList.Count; предупредить, если мелодий в списке больше допустимого!
if SongCount = MAX_SONGS then загружаем файлы списка в массив FSongs
for Index := 0 to SongCount - 1 do begin
if (Module = nil) and (Stream = nil) then
if Module <> nil then
FSongs[Index].Module := Module; |
|||||||||
Метод FreePlaylist выглядит совсем просто - procedure
TD3DGameApp.FreePlaylist; |
|||||||||
Воспроизводим и останавливаем нужный трэк или поток по его номеру в массиве FSongs - procedure
TD3DGameApp.PlayItem(Index: Integer);
if FSongs[Index].Module <> nil then procedure
TD3DGameApp.StopItem(Index: Integer);
if FSongs[Index].Module <> nil then |
|||||||||
Для того, чтобы не выгружать весь плей-лист ради одной лишь песни реализуем методы удаления и добавления отдельных композиций списка. Сначала реализуем удаление - |
|||||||||
procedure
TD3DGameApp.DeleteSong(Index: Integer); var Index2: Integer; begin if (Index < 0) or (Index > FTMSPlayList.Count-1) then Exit; StopItem(Index); |
|||||||||
Теперь добавление - function
TD3DGameApp.AddSong(Filename: string): Integer;
if SongCount = MAX_SONGS then
if (Module = nil) and (Stream = nil) then
if Module <> nil then result := FTMSPlayList.Add(Filename);
FSongs[result].Module := Module; end; |
|||||||||
Регулируем громкость - значения громкости 0 - тишина, 255 - максимум procedure
TD3DGameApp.Volume(SongIndex: Integer; Value: Byte);
if FSongs[SongIndex].Module <> nil then end; |
|||||||||
Регулировка позиции воспроизведения модуля по паттернам - переход к следующему/предыдущему паттерну - function
TD3DGameApp.Go2NextPattern(SongIndex: Integer): Integer;
if (SongIndex < 0) or (SongIndex > FTMSPlayList.Count-1) then
if FSongs[SongIndex].Module = nil then function
TD3DGameApp.Go2PrevPattern(SongIndex: Integer): Integer;
if (SongIndex < 0) or (SongIndex > FTMSPlayList.Count-1) then
if FSongs[SongIndex].Module = nil then |
|||||||||
Для целей отладки будет полезно получать параметры производительности системы FMOD - var
if CurrentSongIndex > -1 then данный метод должен вызываться периодически (аналогично FrameMove). Здесь также проверяется режим плей-листа. Если он установлен, то будет проигрываться следующий файл списка, в противном случае будет бесконечно воспроизводиться композиция с индексом CurrentSongIndex. |
|||||||||
Если Ваш игровой проект будет поддерживать в опции настроек установку каких-либо аудио-параметров - выбор драйвера, параметры фильтрации и т.п., то можете реализовать их установку по аналогии с тем, как это выполнено в рассмотренном нами выше примере. | |||||||||
На этом пожалуй и закруглимся. Заметим лишь, что созданные методы теперь могут вызываться в различных частях Вашего приложения, чтобы например, для одной сцены играла одна музыка, для другой - другая. Одновременного воспроизведения нескольких файлов можно добиться простым вызовом метода PlayItem с нужными индексами. Сделать чтобы несколько файлов играли одновременно и бесконечно - это Вы, я думаю сможете самостоятельно, но на первых порах это вряд ли Вам понадобится. |
|||||||||
|
|||||||||
[Назад] [Все уроки] | |||||||||
Обновления
и новости о развитии Delphi DirectX проекта http://www.megainformaticsite.pochta.ru http://www.megainformatic.boom.ru http://www.megainformatic.narod.ru
|
|||||||||
Cвои пожелания, вопросы или заметки отправляйте на: |
|||||||||
Обмен ссылками | |||||||||
|
|||||||||
(с) МЕГА ИНФОРМАТИК 2006-2009 | |||||||||