DXUTsound.cpp + DXUTsound.h — классы оболчки для работы с DirectSound
play_sounds.cpp + play_sounds.h — определение проигрываемых звуков, общие функции управления звуками и функции уже прогрывания некоторых конкретных звуков. Последние, естественно, менять на свои. Или Удалить. Для проигрывания любого звука используется функция
Первый параметр — номер звука из массива структур. Для прямого доступа лучше использовать именованные константы, определяемые в play_sounds.h в enum ids_sounds
Второй — флаг проигрывания по кругу
Третий — позиция с которой будет проигрываться звук, по умолчанию — 0
Уровень для каждого звука и путь получения его значения описывается в массиве структур.
естественно enum нужно привести в соответствие с массивом структур звуков.
В массиве структур — sounds описываются все звуки:
-Первое поле — обязательно NULL
-Второе — 0
-Третье — имя wav вайла. После к нему будет прибавлен путь до папки со звуками
-Четвертое — имя параметра в конфиге, для регулирования уровня данного звука. Можно иметь один параметр, но обязательно строку с его именем тогда задать для всех звуков.
-В последнем поле задается уровень от 0 до 100% по умолчанию.
там где … обязательно задать имена папок и файлов.
Вообще хранить файлы звуков в gauges не очень хорошо. Но так исторически сложилось в тех проектах, где я работаю.
Хранить все свое стоит в папке с моделью, т.е. где-то в ..Aircraft{папка самолета}{например, в папке cfg_and_res}
Но тут, тогда нужно будет обязательно считать имя самолета из Aircraft и папку с самолетом называть именно так.
Другой вариант — хранить в определенной подпапке самолета и gau и уже получив, через функции API, полный путь к gau файлу, отсчитывать от него путь к конфигам и звукам.
Функция initialization_play_sounds() — должна обязательно вызываться в инициализации gau, т.е. в module_init
Функция deinitialization_play_sounds() — в module_deinit
Последние функции становятся доступными, если раскрыть макрос — GAUGE_TABLE_BEGIN()
В архиве есть папка libs
В ней заголовочный файл и lib из DirectX SDK 2007 для работы с DirectSound. (dxguid.lib — кажется не нужна)
После DirectX SDK 2007 уже DirectSound нет. Там уже другой, более крутой механизм проигрывания звуков.
Для сима вполне достаточно возможностей, которые предоставляет DirectSound из DirectX SDK 2007.
PlaySoynd проигрывает файл, если я правильно понял. Мне нужно чтобы при загрузке самолета все используемые файлы писались в буферы, и там хранились до выхода из сима(самолета). Моё мнение это должно повысить производительность. Может я не прав, поправте меня, я ведь только учусь.
serg_p591
04.07.2012 в 20:52
В приведенном мной примере, как раз эти буферы и создаются в инициализации. В инициализации в них заливаются звуки из wav файлов и задается уровень громкости. Далее проигрывание производится уже загруженного звука. В деинициализации все удаляется.
seycovip3008
04.07.2012 в 20:54
Вот выдрал из одного своего проекта.
Спасибо большое, очень выручили, я как раз и не хотел .dll загружать WAVE файлами. Я даже понять не смог в моем вареанте WAVE файл компилируется или просто считывается каждый раз при запуске самолета из директории. Теперь буду спокойно разбираться.
Edited by seyco
seycovip3008
04.07.2012 в 20:57
В приведенном мной примере, как раз эти буферы и создаются в инициализации. В инициализации в них заливаются звуки из wav файлов и задается уровень громкости. Далее проигрывание производится уже загруженного звука. В деинициализации все удаляется.
Я уже понял, спабибо еще раз
gosha-z32
05.07.2012 в 06:56
Мысли вслух:
1. А SetCooperativeLevel(NULL,) реально работает?
2. Не вижу ничего плохого в хранении звука как ресурса. Придется только написать собственную разборку RIFFа для получения WAVEFORMATEX и остального. Некоторые мысли по этому поводу есть в DX SDK
3. У меня в June 2010 DX SDK (Latest вроде как) DSound вполне наличествует
4. Если пишем звук под FSX — GUIDы надо брать из fsx.cfg
5. Опять же, если пишем под FSX — неплохо бы отработать кнопочку Mute
serg_p591
05.07.2012 в 07:24
… 1. А SetCooperativeLevel(NULL,) реально работает? …
2. Не вижу ничего плохого в хранении звука как ресурса. Придется только написать собственную разборку RIFFа для получения WAVEFORMATEX и остального. Некоторые мысли по этому поводу есть в DX SDK …
Если нужно заменить звук (на другой, ну мало ли, доработали вдруг), то что, будем компилить заново gau (dll)? Случай с reshack не рассматриваем, ибо если размер нового звука больше, воспользоваться reshack-ом нельзя. Да и думаю вообще, хранить данные и ресурсы в теле модуля — зло.
… 3. У меня в June 2010 DX SDK (Latest вроде как) DSound вполне наличествует …
Точно помню, когда хотел найти dsound.h — не нашел его в June 2010 DX SDK. А в доке было написано, что XAudio2 заменил Direct Sound с , точно не помню, кажется с версии DX SDK 2008. Сейчас некогда ставить June 2010 DX SDK, но вот, например, сейчас наткнулся на статью:
Как заявляет сама Microsoft (смотреть тут), она больше не поддерживает DirectSound, и новые проекты, в зависимости от типа, должны использовать новое программное обеспечение. Для игр это XAudio2 и X3DAudio, для всего остального — Windows Core Audio.
Если нужно заменить звук (на другой, ну мало ли, доработали вдруг), то что, будем компилить заново gau (dll)? Случай с reshack не рассматриваем, ибо если размер нового звука больше, воспользоваться reshack-ом нельзя. Да и думаю вообще, хранить данные и ресурсы в теле модуля — зло.
Насчет замены — согласен, насчет зла — нет
Точно помню, когда хотел найти dsound.h — не нашел его в June 2010 DX SDK.
Вот сейчас посмотрел в свой DXSDK/Include — вот он, dsound.h, размером 113801 байт…
serg_p591
05.07.2012 в 08:16
Ну значит я ошибся.
Хотя, MS точно не рекомендовала использовать его. Этот текст на англицком я точно видел. Сейчас некогда искать.
BoL4oNoK1
11.10.2012 в 18:29
Спасибо, Сергей, за ответ, но может кто из знающих все же подскажет=)
serg_p591
11.10.2012 в 19:59
Определение статической переменной:
ID id_agr72_sprite_y = -1;
В инициализации (лучше всего в module_init()):
// проверяем есть ли L:переменная, если нет - создаем
if((id_agr72_sprite_y = check_named_variable("agr72_sprite_y")) == -1)
id_agr72_sprite_y = register_named_variable("agr72_sprite_y");
// id_agr72_sprite_y — числовой идентификатор данной переменной
// agr72_sprite_y_cbvar — некая переменная C.
В деинициализации (лучше в module_deinit()):
unregister_all_named_vars ();
Лучше всего все ID и нэймы L:переменных запихнуть в массив структур (который инициализировать сразу же при определении, так удобней) и уже оперировать с ним (тут уже многие операции можно будет производить в циклах).
Можно сделать связанный список структур или класс, например, LVars, содержащий связанный список экземпляров классов, например, LVar.
Edited by serg_p
seycovip3029
11.10.2012 в 20:15
Спасибо Сергей! Приятно, когда есть отзывчивые люди.
Определены классы для работы с L:переменными, класс-родитель всех систем, пример топливной системы, пример системы управления центровкой.
Все файлы cpp — отдельно-компилируемые модули (далее по тексту просто модули).
Модуль sim (sim.h и sim.cpp) — все дела связанные с симконнектом. Там подробные комментарии (в файлах sim.h и sim.cpp). SimConnect.dll загружается явным образом из предопределенного места. Соответственно все вызовы функций SimConnect-а — через указатели, которые получаются через вызов функции API — GetProcAddress(). Прибегнуть к такому варианту зугрузки SimConnrect-а заставили постоянные траблы у пользователей с симконнектом.
SimConnect.dll от FSX+SP1 лежит в fsx_gaufor_simpanelSimConnectSP1
Уровень логики полностью отвязан от приборов визуализации. Но для того, что бы произошла инициализация — необходимо прописать в Panel.cfg хотя бы один прибор из dll. В примере это невидимый прибор — LogicLevel. Определен в главном модуле (main.cpp).
В main.rc определны свойсва dll.
Там все «NO NAME» и «No copyright».
Я специально все убрал.
Проект сделан в VC++ 2008.
Все из SDK для FSX + SP1
В проекте используется только одна конфигурация — Release. Debug я удалил. Но я изменил параметры компиляции так, что при компиляции и сборке генерится отладочная информация. Вся она записывается в файл fsx_gau.pdb. В fsx_gau.dll прописан только путь к fsx_gau.pdb. Такой вариант, по моему мнению, более удобен по сравнению с работой в двух конфигурациях проекта. Всегда есть релизная dll и всегда есть возможность ее отладить. Для отладки нужен только pdb файл. Естественно пользователям его не даем. Даем только dll. Но здесь есть минус. Пришлось отключиь оптимизацию. Помню читал статейку про то, что оптимизация — зло. Для меня было достаточно убедительно. Правда ссылку потерял. Это конечно все спорно, но я выбрал этот вариант работы и все gau делаю именно так, с генерацией отладочной информации и отключенной оптимизацией.
Edited by serg_p
icebear604
18.10.2012 в 03:50
Уровень логики полностью отвязан от приборов визуализации. Но для того, что бы произошла инициализация — необходимо прописать в Panel.cfg хотя бы один прибор из dll. В примере это невидимый прибор — LogicLevel. Определен в главном модуле (main.cpp).
Серёга, до сих пор? Можно же сделать как в кишках девятки с инициализацие в модуле и вклиниванием в общую цепь обновления гауг. Вроде даже обсуждали это уже. Я точно помню, что Денис говорил, что в десятке симконектом это можно сделать штатно.
serg_p591
18.10.2012 в 10:54
Свой модуль, в FSX, ты должен класть инсталлером в определенное место и еще обязательно прописать его в xml файле, где прописываются внешние, по отношению к симу, модули. Т.е. твой инсталлер должен будет корректно модифицировать этот xml файл. Ну шо бы сим знал, что ету dll надо загружать при старте. Плюс твой модуль будет висеть всегда в памяти, нужен он, ненужен, он будет там пока не умрет сим.
Для меня все это зло!
Мне легче dll положить в папку Panel (ну или в предопределенную папку внутри папки модели) и прописать одну строчку с фейковым прибором в Panel.cfg (если в dll нет ни одного видимого прибора) и все, уровень логики заработал.
Тут принцип простой. Если в dll есть хотя бы один прибор, пусть даже невидимый, причем не важно, где в Panel.cfg он прописан, то этого достаточно, что бы сим загрузил эту dll и выполни ее инициализацию. После загрузки срабатывает module_init(), инициализируется SimConnect, происходит подписка на системное событие Frame — все, моя логика заработала и заработала совершенно независимо от уровня представления.
Т.е. достаточно просто добавить одну строку в Panel.cfg, не важно куда, и моя dll будет работать, как надо и загружаться только с моей моделью. Более того, повторюсь, если в dll есть хотя бы один видимый прибор, то фейковый, невидимый прибор уже не нужен.
Так, кстати, у меня сейчас работает и тушка в FS9. 5 gau (это сложилось исторически). Фейковые приборы тут даже и не нужны, я их все поубивал, ибо в каждой из gau куча видимых приборов. Т.е. загрузка и инициализация моих dll (gau) обязательно произойдет, а при их инициализации и запуск моего уровня логики (вклинивание в цепочку). Естественно все это ща в тушке работает не через симконнект, а сам знаешь чрез что. Более того, если я захочу все причесать и свести весь уровень логики в одну dll уровня логики, то и в этом случае я не буду ее делать как модуль. Мне не трудно прописать одну строку в Panel.cfg и при этом получить независимый уровень логики загружающийся вместе с моей моделью.
Ну и скажи, накой мне городить в тушке модуль?
Если конечно у меня не возникнет необходимость «ожить» до загрузки моей модели. Тут да — без модуля не обойтись!
Правда в связи с FSX смущает немного одно обсоятельство. Если у тебя, например, 3 dll, то в этом случае будут открыты три сессисии SimConnect-а. Но я думаю (я точно не проверял), что это совсем не накладно. Так шо особо-то причиной городить модуль,это обстоятельство тоже не может быть.
Ну а вообще, лучше все пробовать самому, а не говорить, что вот Денис говорил, а ты до сих пор. Т.е. попробуй сам и тогда ты точно будешь знать ценость любого совета для себя и соответственно для конкретного контекста.
Edited by serg_p
icebear604
18.10.2012 в 13:47
Ну а вообще, лучше все пробовать самому, а не говорить, что вот Денис говорил, а ты до сих пор. Т.е. попробуй сам и тогда ты точно будешь знать ценость любого совета для себя и соответственно для конкретного контекста.
Нуууу, не ругайся. Про части, называемые модуль в понятии сима, ты прав. Но я так обычную гаугу обозвал и попробовал на девятке такой «модуль». Грузится на ура только с тем самолётом, где используется, выгражуется тоже вместе с самолётом и иницилизации не надо через невидимый прибор. А как твой способ при загрузке полёта сразу ВК? Пойми мне правильно, я противник подходов «загрузи самолёт, вылези из него, залезь в цессну». Я не думаю, что эйсы в десятке сделали другое что-то, просто сделали доступ к этой цепочке документированым и всё. Но опять же, могу быть не прав, десятку в книжках видел.
serg_p591
18.10.2012 в 15:36
Если уровень логики крутится не CalBack-ом прибора, а обработчиком события (что в FS9, что в FSX) — логика систем работает вне зависимости от того работают ли приборы или нет. Т.е. это означает, что вне зависимости от того, где ты загрузился в 2D или в ВК, твоя топливная система, гидросистема, курсовая система и т.д. — будут работать, тока надо потыкать тумблера. Т.е. здесь не получится так, что загрузившись в ВК, тебе обязательно надо показать главную панель, что бы все закрутилось.
Так у меня в примере.
Так сейчас у меня в тушке.
За исключение прибора ККП и озвучки экипажа. Думаю, даст Бог — доделаю. Сейчас делаю сохранение/восстановление состояния систем. Данные сначала запихиваю в map (контейнер map из STL, а затем сбрасываю в файл. При загрузке — из файла в map. Переменная в map-е ищется по ключу, по своему найму (поиск очень быстрый, в одноразовом событии загрузки полета — вполне все к месту). Далее извлекается Value и присваивается соответствующему полю, переменной.
STL — обалденная вещь. Жалею, что поздно ее для себя открыл.
Edited by serg_p
seycovip3029
18.10.2012 в 18:25
Ах вот почему у меня логика да и вообще все начинает работать только после переключения в 2D.
Вовремя прочитал, теперь надо думать как пользоваться обработчиком событий…
Edited by seyco
seycovip3029
18.10.2012 в 22:43
Если уровень логики крутится не CalBack-ом прибора, а обработчиком события (что в FS9, что в FSX) — логика систем работает вне зависимости от того работают ли приборы или нет. Т.е. это означает, что вне зависимости от того, где ты загрузился в 2D или в ВК, твоя топливная система, гидросистема, курсовая система и т.д. — будут работать, тока надо потыкать тумблера. Т.е. здесь не получится так, что загрузившись в ВК, тебе обязательно надо показать главную панель, что бы все закрутилось.
А у меня так и получилось, пока все 2D панели с тумблерами не откроешь (тумблеры уже включены из памяти cfg-а), приборы не хотят работать, даже после того, как всю логику работы перенес из одного прибора в логику симконнекта.
…
Проблему решил просто — открыл, закрыл все панели (кроме 1-й) в инициализации.
Edited by seyco
serg_p591
19.10.2012 в 04:56
Это не решение.
Собственно это решение первое, что приходит в голову. Но это — не решение.
Единственно правильное решение «вклится в цепочу».
Как?
Для FSX все показано и рассказано.
Здесь.
Для FS9 решение есть, но это через личку.
Причем, за неимением времени — передача библиотеки и небольшой пример.
icebear604
19.10.2012 в 08:01
Если уровень логики крутится не CalBack-ом прибора, а обработчиком события (что в FS9, что в FSX) — логика систем работает вне зависимости от того работают ли приборы или нет. Т.е. это означает, что вне зависимости от того, где ты загрузился в 2D или в ВК, твоя топливная система, гидросистема, курсовая система и т.д. — будут работать, тока надо потыкать тумблера. Т.е. здесь не получится так, что загрузившись в ВК, тебе обязательно надо показать главную панель, что бы все закрутилось.
Я вернусь к этой теме, когда перелезу на десятку. Как в девятке знаю, давно уже всё отвязали, всё крутится вне зависимости от способа загрузки самолёта и т.п.
STL — обалденная вещь. Жалею, что поздно ее для себя открыл.
STL — удобная вещь, не более. А скажи-ка мне, в какой файл ты сохраняешь это всё? В файл полёта или в отдельный? И на каком этапе происходит загрузка? Спрашиваю так ехидно, потому что сам малость посидел над этой темой (хотя и девятке).
serg_p591
19.10.2012 в 08:20
… STL — удобная вещь, не более. А скажи-ка мне, в какой файл ты сохраняешь это всё? В файл полёта или в отдельный? И на каком этапе происходит загрузка? Спрашиваю так ехидно, потому что сам малость посидел над этой темой (хотя и девятке).
Я тоже это сейчас делаю в девятке (в ПТ Ту-154М). Узнаю имя полета, используя недокументированные возможности, ну, ту, классную библиотечку (причем, получаю полное имя файла). А дальше к этому полному имени просто прибавляю расширение .pt154msave и соответственно сбрасываю туда map при сохранении полета. При загрузке читаю свой файл (имя которого отличается от имени файла полета расширением) и закидываю в map.
Здесь собственно все прозрачно.
Единственное, есть две трудности, которые непреодолимы при использовании штатного SDK:
1. Получить имя файла текущего полета;
2. Сесть на событие сохранение полета.
Но все это позволяет преодолеть, как говорилось выше — «золотая библиотека» (для FS9).
Edited by serg_p
seycovip3029
20.10.2012 в 23:00
А у меня так и получилось, пока все 2D панели с тумблерами не откроешь (тумблеры уже включены из памяти cfg-а), приборы не хотят работать, даже после того, как всю логику работы перенес из одного прибора в логику симконнекта.
…
Проблему решил просто — открыл, закрыл все панели (кроме 1-й) в инициализации.
Пересмотрел полностью весь проект — от отсутствия опыта конечно много накосячил, ночь убил на пересмотр и отладку проекта. Вот теперь не надо панели открывать, все начинает работать через несколько секунд после загрузки самолета.
Но появился еще вопрос, на который сам пока не могу найти ответ.
Это определение статической переменной, которая тут же и инициализируется. Т.к. tank_2_list_2[] — это массив, то инициализация здесь производится не одним значением, а списком значений. NULL — это тоже значение. По этому значению симулятор определяет, что это конец массива. Стандартная практика в C.
{(PELEMENT_HEADER)&tank_2_03, NULL};
и
{&tank_2_03.header, NULL};
Это одно и тоже, за исключением того, что в верхней строке — явное приведение типа указателя, это хорошая практика, приведение типов осуществлять самому, т.е. явно. & — операция взятия адреса.
seyco
Это последний раз, когда я разъясняю элементарщину. И других программеров, жаждущих Вам объяснять элементарные вещи, Вы здесь не увидите. По этому еще раз настоятельно рекомендую Вам пройти, какую-нибудь книгу, прорешав все примеры, где поэтапно разжевываются все элементарные понятия. Без этого Вы будете постоянно спотыкаться.
На эту книгу я наткнулся, введя сейчас в гугле: «книга C++ элементарные понятия».
Про нет времени — не аргумент.
Тут либо делать на XML, на котором мало чего можно сделать, причем все делается через задницу, или использовать инструмент профессионалов, т.е. C/C++. В случае с C/C++ — все сложно, но других путей MS нам не дал. Было бы все по-другому, если бы было так, например: приборы описывались бы в XML, а логику их работы можно было бы реализовать в lua, это бы было бы здорово. Но в FS9/FSX — не так.
seyco
Вот выдрал из одного своего проекта.
DXUTsound.cpp + DXUTsound.h — классы оболчки для работы с DirectSound
play_sounds.cpp + play_sounds.h — определение проигрываемых звуков, общие функции управления звуками и функции уже прогрывания некоторых конкретных звуков. Последние, естественно, менять на свои. Или Удалить. Для проигрывания любого звука используется функция
SoundFilePlay(int sound_type, BOOL flag_looping, DWORD pos)
Первый параметр — номер звука из массива структур. Для прямого доступа лучше использовать именованные константы, определяемые в play_sounds.h в enum ids_sounds
Второй — флаг проигрывания по кругу
Третий — позиция с которой будет проигрываться звук, по умолчанию — 0
Уровень для каждого звука и путь получения его значения описывается в массиве структур.
естественно enum нужно привести в соответствие с массивом структур звуков.
В массиве структур — sounds описываются все звуки:
-Первое поле — обязательно NULL
-Второе — 0
-Третье — имя wav вайла. После к нему будет прибавлен путь до папки со звуками
-Четвертое — имя параметра в конфиге, для регулирования уровня данного звука. Можно иметь один параметр, но обязательно строку с его именем тогда задать для всех звуков.
-В последнем поле задается уровень от 0 до 100% по умолчанию.
В play_sounds.cpp
в стоках
sprintf_s(path_to_gau_cfg, «%s%s», path_to_sim, «gauges\…\….cfg»);
…
sprintf_s(path_to_sound, MAX_PATH, «%s%s», path_to_sim, «gauges\…\…\»);
там где … обязательно задать имена папок и файлов.
Вообще хранить файлы звуков в gauges не очень хорошо. Но так исторически сложилось в тех проектах, где я работаю.
Хранить все свое стоит в папке с моделью, т.е. где-то в ..Aircraft{папка самолета}{например, в папке cfg_and_res}
Но тут, тогда нужно будет обязательно считать имя самолета из Aircraft и папку с самолетом называть именно так.
Другой вариант — хранить в определенной подпапке самолета и gau и уже получив, через функции API, полный путь к gau файлу, отсчитывать от него путь к конфигам и звукам.
Функция initialization_play_sounds() — должна обязательно вызываться в инициализации gau, т.е. в module_init
Функция deinitialization_play_sounds() — в module_deinit
Последние функции становятся доступными, если раскрыть макрос — GAUGE_TABLE_BEGIN()
В архиве есть папка libs
В ней заголовочный файл и lib из DirectX SDK 2007 для работы с DirectSound. (dxguid.lib — кажется не нужна)
После DirectX SDK 2007 уже DirectSound нет. Там уже другой, более крутой механизм проигрывания звуков.
Для сима вполне достаточно возможностей, которые предоставляет DirectSound из DirectX SDK 2007.
PlaySounds.zip
Edited by serg_p
PlaySoynd проигрывает файл, если я правильно понял. Мне нужно чтобы при загрузке самолета все используемые файлы писались в буферы, и там хранились до выхода из сима(самолета). Моё мнение это должно повысить производительность. Может я не прав, поправте меня, я ведь только учусь.
В приведенном мной примере, как раз эти буферы и создаются в инициализации. В инициализации в них заливаются звуки из wav файлов и задается уровень громкости. Далее проигрывание производится уже загруженного звука. В деинициализации все удаляется.
Спасибо большое, очень выручили, я как раз и не хотел .dll загружать WAVE файлами. Я даже понять не смог в моем вареанте WAVE файл компилируется или просто считывается каждый раз при запуске самолета из директории. Теперь буду спокойно разбираться.
Edited by seyco
Я уже понял, спабибо еще раз
Мысли вслух:
1. А SetCooperativeLevel(NULL,) реально работает?
2. Не вижу ничего плохого в хранении звука как ресурса. Придется только написать собственную разборку RIFFа для получения WAVEFORMATEX и остального. Некоторые мысли по этому поводу есть в DX SDK
3. У меня в June 2010 DX SDK (Latest вроде как) DSound вполне наличествует
4. Если пишем звук под FSX — GUIDы надо брать из fsx.cfg
5. Опять же, если пишем под FSX — неплохо бы отработать кнопочку Mute
Это ты, я так понял, про код seyco?
Тут да — нехорошо.
Если нужно заменить звук (на другой, ну мало ли, доработали вдруг), то что, будем компилить заново gau (dll)? Случай с reshack не рассматриваем, ибо если размер нового звука больше, воспользоваться reshack-ом нельзя. Да и думаю вообще, хранить данные и ресурсы в теле модуля — зло.
Точно помню, когда хотел найти dsound.h — не нашел его в June 2010 DX SDK. А в доке было написано, что XAudio2 заменил Direct Sound с , точно не помню, кажется с версии DX SDK 2008. Сейчас некогда ставить June 2010 DX SDK, но вот, например, сейчас наткнулся на статью:
Программирование звука с использованием XAudio2
Edited by serg_p
Именно там
Насчет замены — согласен, насчет зла — нет
Вот сейчас посмотрел в свой DXSDK/Include — вот он, dsound.h, размером 113801 байт…
Ну значит я ошибся.
Хотя, MS точно не рекомендовала использовать его. Этот текст на англицком я точно видел. Сейчас некогда искать.
Спасибо, Сергей, за ответ, но может кто из знающих все же подскажет=)
Определение статической переменной:
ID id_agr72_sprite_y = -1;
В инициализации (лучше всего в module_init()):
// проверяем есть ли L:переменная, если нет - создаем if((id_agr72_sprite_y = check_named_variable("agr72_sprite_y")) == -1) id_agr72_sprite_y = register_named_variable("agr72_sprite_y");Чтение:
agr72_sprite_y_cbvar = get_named_variable_value(id_agr72_sprite_y);
Запись:
set_named_variable_value(id_agr72_sprite_y, agr72_sprite_y_cbvar);
// id_agr72_sprite_y — числовой идентификатор данной переменной
// agr72_sprite_y_cbvar — некая переменная C.
В деинициализации (лучше в module_deinit()):
unregister_all_named_vars ();
Лучше всего все ID и нэймы L:переменных запихнуть в массив структур (который инициализировать сразу же при определении, так удобней) и уже оперировать с ним (тут уже многие операции можно будет производить в циклах).
Можно сделать связанный список структур или класс, например, LVars, содержащий связанный список экземпляров классов, например, LVar.
Edited by serg_p
Спасибо Сергей! Приятно, когда есть отзывчивые люди.
serg_p
Спасибо!
Был вопрос про SimConnect в отдельной ветке.
Вот небольшой пример.
Мож пригодится.
Это для FSX.
Определены классы для работы с L:переменными, класс-родитель всех систем, пример топливной системы, пример системы управления центровкой.
Все файлы cpp — отдельно-компилируемые модули (далее по тексту просто модули).
Модуль sim (sim.h и sim.cpp) — все дела связанные с симконнектом. Там подробные комментарии (в файлах sim.h и sim.cpp). SimConnect.dll загружается явным образом из предопределенного места. Соответственно все вызовы функций SimConnect-а — через указатели, которые получаются через вызов функции API — GetProcAddress(). Прибегнуть к такому варианту зугрузки SimConnrect-а заставили постоянные траблы у пользователей с симконнектом.
SimConnect.dll от FSX+SP1 лежит в fsx_gaufor_simpanelSimConnectSP1
Уровень логики полностью отвязан от приборов визуализации. Но для того, что бы произошла инициализация — необходимо прописать в Panel.cfg хотя бы один прибор из dll. В примере это невидимый прибор — LogicLevel. Определен в главном модуле (main.cpp).
В main.rc определны свойсва dll.
Там все «NO NAME» и «No copyright».
Я специально все убрал.
Проект сделан в VC++ 2008.
Все из SDK для FSX + SP1
В проекте используется только одна конфигурация — Release. Debug я удалил. Но я изменил параметры компиляции так, что при компиляции и сборке генерится отладочная информация. Вся она записывается в файл fsx_gau.pdb. В fsx_gau.dll прописан только путь к fsx_gau.pdb. Такой вариант, по моему мнению, более удобен по сравнению с работой в двух конфигурациях проекта. Всегда есть релизная dll и всегда есть возможность ее отладить. Для отладки нужен только pdb файл. Естественно пользователям его не даем. Даем только dll. Но здесь есть минус. Пришлось отключиь оптимизацию. Помню читал статейку про то, что оптимизация — зло. Для меня было достаточно убедительно. Правда ссылку потерял. Это конечно все спорно, но я выбрал этот вариант работы и все gau делаю именно так, с генерацией отладочной информации и отключенной оптимизацией.
Edited by serg_p
Серёга, до сих пор? Можно же сделать как в кишках девятки с инициализацие в модуле и вклиниванием в общую цепь обновления гауг. Вроде даже обсуждали это уже. Я точно помню, что Денис говорил, что в десятке симконектом это можно сделать штатно.
Свой модуль, в FSX, ты должен класть инсталлером в определенное место и еще обязательно прописать его в xml файле, где прописываются внешние, по отношению к симу, модули. Т.е. твой инсталлер должен будет корректно модифицировать этот xml файл. Ну шо бы сим знал, что ету dll надо загружать при старте. Плюс твой модуль будет висеть всегда в памяти, нужен он, ненужен, он будет там пока не умрет сим.
Для меня все это зло!
Мне легче dll положить в папку Panel (ну или в предопределенную папку внутри папки модели) и прописать одну строчку с фейковым прибором в Panel.cfg (если в dll нет ни одного видимого прибора) и все, уровень логики заработал.
Тут принцип простой. Если в dll есть хотя бы один прибор, пусть даже невидимый, причем не важно, где в Panel.cfg он прописан, то этого достаточно, что бы сим загрузил эту dll и выполни ее инициализацию. После загрузки срабатывает module_init(), инициализируется SimConnect, происходит подписка на системное событие Frame — все, моя логика заработала и заработала совершенно независимо от уровня представления.
Т.е. достаточно просто добавить одну строку в Panel.cfg, не важно куда, и моя dll будет работать, как надо и загружаться только с моей моделью. Более того, повторюсь, если в dll есть хотя бы один видимый прибор, то фейковый, невидимый прибор уже не нужен.
Так, кстати, у меня сейчас работает и тушка в FS9. 5 gau (это сложилось исторически). Фейковые приборы тут даже и не нужны, я их все поубивал, ибо в каждой из gau куча видимых приборов. Т.е. загрузка и инициализация моих dll (gau) обязательно произойдет, а при их инициализации и запуск моего уровня логики (вклинивание в цепочку). Естественно все это ща в тушке работает не через симконнект, а сам знаешь чрез что. Более того, если я захочу все причесать и свести весь уровень логики в одну dll уровня логики, то и в этом случае я не буду ее делать как модуль. Мне не трудно прописать одну строку в Panel.cfg и при этом получить независимый уровень логики загружающийся вместе с моей моделью.
Ну и скажи, накой мне городить в тушке модуль?
Если конечно у меня не возникнет необходимость «ожить» до загрузки моей модели. Тут да — без модуля не обойтись!
Правда в связи с FSX смущает немного одно обсоятельство. Если у тебя, например, 3 dll, то в этом случае будут открыты три сессисии SimConnect-а. Но я думаю (я точно не проверял), что это совсем не накладно. Так шо особо-то причиной городить модуль,это обстоятельство тоже не может быть.
Ну а вообще, лучше все пробовать самому, а не говорить, что вот Денис говорил, а ты до сих пор. Т.е. попробуй сам и тогда ты точно будешь знать ценость любого совета для себя и соответственно для конкретного контекста.
Edited by serg_p
Нуууу, не ругайся. Про части, называемые модуль в понятии сима, ты прав. Но я так обычную гаугу обозвал и попробовал на девятке такой «модуль». Грузится на ура только с тем самолётом, где используется, выгражуется тоже вместе с самолётом и иницилизации не надо через невидимый прибор. А как твой способ при загрузке полёта сразу ВК? Пойми мне правильно, я противник подходов «загрузи самолёт, вылези из него, залезь в цессну». Я не думаю, что эйсы в десятке сделали другое что-то, просто сделали доступ к этой цепочке документированым и всё. Но опять же, могу быть не прав, десятку в книжках видел.
Если уровень логики крутится не CalBack-ом прибора, а обработчиком события (что в FS9, что в FSX) — логика систем работает вне зависимости от того работают ли приборы или нет. Т.е. это означает, что вне зависимости от того, где ты загрузился в 2D или в ВК, твоя топливная система, гидросистема, курсовая система и т.д. — будут работать, тока надо потыкать тумблера. Т.е. здесь не получится так, что загрузившись в ВК, тебе обязательно надо показать главную панель, что бы все закрутилось.
Так у меня в примере.
Так сейчас у меня в тушке.
За исключение прибора ККП и озвучки экипажа. Думаю, даст Бог — доделаю. Сейчас делаю сохранение/восстановление состояния систем. Данные сначала запихиваю в map (контейнер map из STL, а затем сбрасываю в файл. При загрузке — из файла в map. Переменная в map-е ищется по ключу, по своему найму (поиск очень быстрый, в одноразовом событии загрузки полета — вполне все к месту). Далее извлекается Value и присваивается соответствующему полю, переменной.
STL — обалденная вещь. Жалею, что поздно ее для себя открыл.
Edited by serg_p
Ах вот почему у меня логика да и вообще все начинает работать только после переключения в 2D.
Вовремя прочитал, теперь надо думать как пользоваться обработчиком событий…
Edited by seyco
А у меня так и получилось, пока все 2D панели с тумблерами не откроешь (тумблеры уже включены из памяти cfg-а), приборы не хотят работать, даже после того, как всю логику работы перенес из одного прибора в логику симконнекта.
…
Проблему решил просто — открыл, закрыл все панели (кроме 1-й) в инициализации.
Edited by seyco
Это не решение.
Собственно это решение первое, что приходит в голову. Но это — не решение.
Тогда уж вот так:
пост #56
Но это тоже не решение.
Единственно правильное решение «вклится в цепочу».
Как?
Для FSX все показано и рассказано.
Здесь.
Для FS9 решение есть, но это через личку.
Причем, за неимением времени — передача библиотеки и небольшой пример.
Я вернусь к этой теме, когда перелезу на десятку. Как в девятке знаю, давно уже всё отвязали, всё крутится вне зависимости от способа загрузки самолёта и т.п.
STL — удобная вещь, не более. А скажи-ка мне, в какой файл ты сохраняешь это всё? В файл полёта или в отдельный? И на каком этапе происходит загрузка? Спрашиваю так ехидно, потому что сам малость посидел над этой темой (хотя и девятке).
Я тоже это сейчас делаю в девятке (в ПТ Ту-154М). Узнаю имя полета, используя недокументированные возможности, ну, ту, классную библиотечку (причем, получаю полное имя файла). А дальше к этому полному имени просто прибавляю расширение .pt154msave и соответственно сбрасываю туда map при сохранении полета. При загрузке читаю свой файл (имя которого отличается от имени файла полета расширением) и закидываю в map.
Здесь собственно все прозрачно.
Единственное, есть две трудности, которые непреодолимы при использовании штатного SDK:
1. Получить имя файла текущего полета;
2. Сесть на событие сохранение полета.
Но все это позволяет преодолеть, как говорилось выше — «золотая библиотека» (для FS9).
Edited by serg_p
Пересмотрел полностью весь проект — от отсутствия опыта конечно много накосячил, ночь убил на пересмотр и отладку проекта. Вот теперь не надо панели открывать, все начинает работать через несколько секунд после загрузки самолета.
Но появился еще вопрос, на который сам пока не могу найти ответ.
В отрисовки приборов есть такая строка:
PELEMENT_HEADER tank_2_list_2[] = {&tank_2_03.header, NULL};
еще можно писать так:
PELEMENT_HEADER tank_2_list_2[] = {(PELEMENT_HEADER)&tank_2_03, NULL};
Объясните пожалуйста, в чем разница?
В СДК есть пример:
PELEMENT_HEADER cs_sliders_list[] = {&cs_slider_trim.header, &cs_slider_ailerons.header, &cs_slider_elevator.header, &cs_slider_rudder.header, NULL};
Если я правильно понял, это обозначение последовательности отрисовки деталей или нет?
PELEMENT_HEADER tank_2_list_2[] = {&tank_2_03.header, NULL};
Это определение статической переменной, которая тут же и инициализируется. Т.к. tank_2_list_2[] — это массив, то инициализация здесь производится не одним значением, а списком значений. NULL — это тоже значение. По этому значению симулятор определяет, что это конец массива. Стандартная практика в C.
{(PELEMENT_HEADER)&tank_2_03, NULL};
и
{&tank_2_03.header, NULL};
Это одно и тоже, за исключением того, что в верхней строке — явное приведение типа указателя, это хорошая практика, приведение типов осуществлять самому, т.е. явно. & — операция взятия адреса.
seyco
Это последний раз, когда я разъясняю элементарщину. И других программеров, жаждущих Вам объяснять элементарные вещи, Вы здесь не увидите. По этому еще раз настоятельно рекомендую Вам пройти, какую-нибудь книгу, прорешав все примеры, где поэтапно разжевываются все элементарные понятия. Без этого Вы будете постоянно спотыкаться.
Вот например
C++. Бархатный путь
На эту книгу я наткнулся, введя сейчас в гугле: «книга C++ элементарные понятия».
Про нет времени — не аргумент.
Тут либо делать на XML, на котором мало чего можно сделать, причем все делается через задницу, или использовать инструмент профессионалов, т.е. C/C++. В случае с C/C++ — все сложно, но других путей MS нам не дал. Было бы все по-другому, если бы было так, например: приборы описывались бы в XML, а логику их работы можно было бы реализовать в lua, это бы было бы здорово. Но в FS9/FSX — не так.
Edited by serg_p