Информация: Уважаемые посетители! В течение нескольких месяцев на форуме существовала проблема с регистрацией новых пользователей, о которой администрации стало известно недавно. Если вы ранее пытались зарегистрироваться на форуме, но не получили на ваш e-mail письмо с ссылкой для подтверждения регистрации, просим вас зарегистрироваться повторно. Приносим извинения за доставленные неудобства. Если вы все еще испытываете проблемы с регистрацией на форуме, обратитесь за помощью на e-mail: mr.angelo@railroadsim.net

sim

Обсуждение других железнодорожных симуляторов

Re: sim

Сообщение Modulator » 10.01.2010, 03:20

Как же я болею за Брейка, ребята, - что вы так... Ведь может родиться русский Е У Ноль Семь, и даже круче!
Будь бдителен, - впереди красный.
Modulator
 
Сообщения: 40
Зарегистрирован: 19.10.2008, 21:29
Откуда: Москва
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Играю в: Auran Trainz
Имя: Дмитрий

Re: sim

Сообщение TRam_ » 10.01.2010, 03:28

Ведь может родиться русский Е У Ноль Семь, и даже круче!
для этого тема и создана.

ЗЫ Повторяю еще раз, взаимные наезды через приват
OK, перемещаем
в z7 всё можно, а что нельзя - можно в sU
Аватара пользователя
TRam_
 
Сообщения: 1925
Зарегистрирован: 30.11.2007, 20:14
Благодарил (а): 2 раз.
Поблагодарили: 66 раз.
Играю в: Auran Trainz
Роль: Разработчик
Имя: Владимир

Re: sim

Сообщение AlexanderG » 10.01.2010, 04:16

Конкретней спроси что нужно - ни весь исходник ни какую-то рабочую часть не вышлю, часть исходника демонстрирующую решение проблемы могу показать.
Исходник одной ДЛЛ, которыми ты собираешься заменить скрипты.

а не потому что делаю сим для сообщества...
Так делай для себя, молча. Если на сообщество срать, на кой тогда тема на форуме?
Join Dropbox and SHARE YOUR SHIT FOR FREE!
AlexanderG
 
Сообщения: 761
Зарегистрирован: 27.06.2009, 16:54
Благодарил (а): 0 раз.
Поблагодарили: 1 раз.
Блог: Просмотр блога (2)
Имя: Александр

Re: sim

Сообщение agmike » 10.01.2010, 04:40

break писал(а):Вода в ступе 2
Что значит похоже? Есть поля - в них хранятся значения - на поля вешаются листенеры.

Вода в ступе 3. Сложно сказать, что ты имеешь в виду Q_PROPERTY(type name READ getFunction ...)? Или "это же очевидно!"?
Поля в С++ не имеют никаких листенеров, аксессоров, событий и т.д. — простое л-значение. А данный макрос — не более чем расширение языка препроцессором, применяемое лишь в Qt. Все же, неужели не ясно, что:
1. Здесь не форум программистов Qt.
2. Здесь не форум программистов.
3. Здесь нет телепатов.
Трудно расписать все чтобы было понятно всем? Я уже писал о том, что скриншоты мало о чем говорят, нужно нормальное словесное описание. Но, видимо, в пустоту.

Надеюсь, что воды в ступе 4 не будет.

TRam_ писал(а):
ЗЫ Повторяю еще раз, взаимные наезды через приват
OK, перемещаем

Лучше вообще без наездов :dont:
The Cake is a Lie.
agmike
 
Сообщения: 1025
Зарегистрирован: 26.08.2006, 12:43
Благодарил (а): 0 раз.
Поблагодарили: 3 раз.
Играю в: Пульт ДНЦ

Re: sim

Сообщение break » 10.01.2010, 05:26

Есть поля - в них хранятся значения - на поля вешаются листенеры.


Постараюсь объяснить понятно. Забудь про реализацию - не важно на чем - главное концепция.

Есть объект - у него есть поля, у других объектов тоже есть поля, объекты могут закинуть удочку на нужное поле свое или чужое и в случае изменения получать события. В таком виде - мол изменилось поле - с именем таким-то - теперь у него значение такое-то. (в данном случае объект получивший событие - листенер т.к. в свое время он закинул удочку на интересующее его свойство и получил событие - прослушал, без проверки этого поля по таймеру!) Внутри события делаем что хотим. Эта же схема будет работать и вунтри скрипта. Вагоны не изолированы друг от друга. Они могут трогать друг друга, также трогать свойства друг друга, свойства устройств друг друга.

Вообще не важно какой язык - это всего лишь подход (может и неверный ), я бы и в AURAN Script пытался сделать аналогичное. Вот почему:
1) Так как устройства независимы друг от друга - минимум связей - минимум проблем. - Нет такого базового устройства в котором были бы ф-ции которые не используются в одних наследниках, а используются в других и наоборот - те кто пробовал писать программы с наследование поймут о чем я. Иной раз базовый файл разрастается так уже что потом и не помнишь где и у кого требуются вот эта ф-сть.
2) Раз независимы - можно сделать библиотеку устройсв, кот. будет ускорять процесс создания новых локов. Понятно что полностью лок из типовых устройств не собрать, но все же быстрее. (А кстати не собрать только потому что оч. сложно написать классы всех всех типовых агрегатов - но теоритически реально с таким подходом, просто слишком трудоемко...)
3) Каждое устройство - конечный законченный объект, при правильном предварительном согласовании разные авторы смогут делать разные устройства. Один двигатель - другой фазорасщепитель, при этом потом при стыковке никаких косяков не полезет. Если они конечно заранее обговорят какие свойства друг друга будут трогать.
4) Сохраняется очень большая возможность расширения модели. Сделал модельку лока - просто меш. Захотелось отдать народу для теста чтобы просто катались - смотрели как блестит, неточности какие-то - может что-то еще. Пишется 1 супер тупое устройство заставляющее его двигаться с фиксированной скоростью, в зависимости от положения контроллера (причем пишется оно 1 раз - потом для всех локов также используется если надо). Потом добавляются уже детализированные устройства (речь идет о логике) - получается вторая версия - более детальная работа лока, но исправного. Последняя стадия все устройства еще расширяются на предмет неисправностей - получается еще версия - тот же лок только с возможностью ломаться! То есть возможность пошагового создания локов, на каждом шаге есть законченный продукт.
5) Разные авторы вполне могут написать 2 разных реализации устройства - "кран 395", а вдруг кому-то нравится 395 одного автора, а 254 другого - просто поменять устройство в вагоне (при условии что краны написаны правильно).

По сути это такой конструктор. Думаю в скриптах можно делать тоже самое - если они поддерживают классы или структуры.
Аватара пользователя
break
 
Сообщения: 202
Зарегистрирован: 26.02.2007, 16:49
Откуда: Voronezh
Благодарил (а): 0 раз.
Поблагодарили: 9 раз.

Re: sim

Сообщение agmike » 10.01.2010, 06:58

Идея понятна. В том же Auran Game Script много средств для ее реализации.
Но смотри, ты предлагаешь писать код устройств в ДЛЛ. Это более производительно и проще реализуется в движке. Но взамен мы получаем недостатки С++, а это важно в случае с пользовательским контентом, так как ошибка в скрипте — исключение, максимум вылет из игры, а в С++ может привести к краху всей системы. Также, я не уверен в переносимости таких ДЛЛ. К примеру, потребуется делать оболочку над АПИ ОС, ведь тот же КЛУБ должен иметь возможность писать в файл.
Поэтому конкретно для разработчиков контента было бы проще абстрагироваться от платформы и языка. Mono предоставляет практически тот же уровень доступа к системе. А современные JIT-компиляторы способны генерировать код, фактически идентичный обычным языкам.
Это сложнее для реализации в самом движке — в данном случае требуется настройка P/Invoke, зато потом это даст экономию во времени и силах, а также дополнительные удобства.
Что касается пользовательской ДЛЛ для скриптов — врядли она сможет сравниться по возможностям с полноценной платформой, также остается открытым вопрос о переносимости. Взаимодействие между объектами, использующими свои скрипты также осложняется, а множественное количество таких сред выполнения может серьезно затормозить игру.
Это по реализации.

Единственное, что я считаю узким местом в твоей концепции — это то, что все другие элементы игрового мира с не вписываются в модель ПС-устройства. Я считаю оптимальным такой подход, при котором классы, представляющие объекты в игре, связаны в иерархию: к примеру MeshObject — класс, имеющий модели и реализующий необходимый интерфейс для управления ими, к примеру, показать/скрыть лампочку, запустить анимацию, сменить текстуру и т.д. Класс Vehicle — производный от MeshObject и, возможно, других — зависит от реализации. Такая иерархия полностью соответствует тому, что мы видим в реальном мире.
Соответственно, базовая функциональность, наподобие езды с определенной скоростью в зависимости от положения контроллера не требует ничего от пользователя, достаточно лишь написать конфигурационный файл. Другое дело, что в эту базовую функциональность вполне вписываются базовые модули — КЛУБы, САУТы, ВРы и т.д. Элементарно просто реализовывать свои объекты — пишем наследника от базового абстрактного класса, чуть-чуть исправить логику по умолчанию — пишем наследника от конкретного класса, КЛУБа и т. п. Устройства, наподобие фазорасщепителя, удобно рассматривать не как полностью независимые модули, а как части электрической схемы, задаваемой графом и рассчитываемой методами линейной алгебры. Воздухораспределитель — класс, реализующий свойства тормозной системы, но ничто не помешает пользователю в его наследнике добавить код для другого интерфейса и подключить датчик 418 к электрической схеме. Т.е. при наличии критической массы кода все программирование становится по большей части декларативным.
По-моему, такая архитектура полностью вписывается в твои пункты, при этом обладая большим потенциалом по расширяемости, и решает проблему обособленности других объектов. К примеру, класс Светофор может быть наследником класса Путевой объект, наследника MeshObject, впрочем, это детали.
Такую модель, НЯП, можно реализовать в ДЛЛах, ведь можно экспортировать не только функции, но и типы. Но ведь в абстрагированной среде это будет гораздо удобнее и красивее :)
Еще одно преимущество такого похода — в строгом контроле типов. Если я использую для моего КЛУБа ЭПК программиста Пети, я буду иметь перед глазами точный его интерфейс и строгий контроль типов со стороны компилятора, что гарантирует мне, что никакой другой ЭПК не сможет неявно работать с моим КЛУБом и являться источником потенциальных ошибок. Конечно, этот пример кажется немного неудачным — ведь если я делаю вагон, то и знаю какой на нем стоит ЭПК. Но представим, что моему КЛУБу нужно обратиться к ЭПК на другом вагоне — и тут возможные различия могут сыграть свою роковую роль. Особенно если вместо ЭПК и КЛУБа будут стоять объекты, обладающие более сложной логикой взаимодействия.

И собственно, раз мы дошли до окружения, хочется узнать как обстоит дело с другими объектами игрового мира — окружением, сигналами, путями, а также глобальным кодом, задающим, к примеру, сценарий.

Это все, конечно, мое ИМХО. Я не утверждаю, что это правильно и грамотно, но просто с моей позиции разработчика дополнений мне кажется, что такая модель будет наиболее близка к идеальной :)

Еще вопросы:
1. Какой используется движок и каков планируется графический уровень?
2. Какой планируется метод распространения?
3. Открыт ли будет исходный код?

P.S. Вот, к примеру, задание простой схемы и вход в поток ее расчета на АГС:
Код: Выделить всё
include "xlse_base.gs"
include "xlse_analogscheme.gs"

class XCHS4_Locomotive isclass LseLocomotive
{
   public void Init(Asset asset);
   
   void InitFinal(void)
   {
      inherited();
      
      AnalogScheme gs = new AnalogScheme();
      SetGraphScheme(gs);
      
      gs.SetCircuit("GV1.A, R2.A, R2.B, GV1.B, GV1.A");
      gs.SetCircuit("R2.A, R3.A, R3.B, R2.B");
      gs.SetCircuit("R3.A R4.A, R4.B GV1.B");
      gs.SetCircuit("R2.A R1.A, R1.B GV2.A, GV2.B GV1.B");
      
      gs.SetObject(new AS_BasicBipolar(), "GV1", "V = 5, R = 0", null);
      gs.SetObject(new AS_BasicBipolar(), "GV2", "V = 1, R = 0", null);
      gs.SetObject(new AS_BasicBipolar(), "R1", "R = 1", null);
      gs.SetObject(new AS_BasicBipolar(), "R2", "R = 2", null);
      gs.SetObject(new AS_BasicBipolar(), "R3", "R = 2", null);
      gs.SetObject(new AS_BasicBipolar(), "R4", "R = 4", null);
      
      GraphSchemeMain(gs);
   }
   
   
   public void Init(Asset asset)
   {
      inherited(asset);
   }
};
Последний раз редактировалось agmike 10.01.2010, 07:32, всего редактировалось 1 раз.
The Cake is a Lie.
agmike
 
Сообщения: 1025
Зарегистрирован: 26.08.2006, 12:43
Благодарил (а): 0 раз.
Поблагодарили: 3 раз.
Играю в: Пульт ДНЦ

Re: sim

Сообщение break » 10.01.2010, 07:27

1. Какой используется движок и каков планируется графический уровень?

Движок написан с 0. Уровень планируется постоянно поднимать - но это не превостепенная задача.

2. Какой планируется метод распространения?

Очень сложный вопрос не зависящий от меня одного. И основная зацепка - надо ли это тем кто его делает.

3. Открыт ли будет исходный код?

Если бы решался такой вопрос - то открытыми стали бы те части, которые позволили делать свой Подвижной Состав, Сигнализацию, Сценарии.
Аватара пользователя
break
 
Сообщения: 202
Зарегистрирован: 26.02.2007, 16:49
Откуда: Voronezh
Благодарил (а): 0 раз.
Поблагодарили: 9 раз.

Re: sim

Сообщение AlexanderG » 10.01.2010, 14:48

Очень сложный вопрос не зависящий от меня одного. И основная зацепка - надо ли это тем кто его делает.
Ну ок, поговорим, когда сим станет радикально лучше ТРС, КРС и МСТС во всем.
Join Dropbox and SHARE YOUR SHIT FOR FREE!
AlexanderG
 
Сообщения: 761
Зарегистрирован: 27.06.2009, 16:54
Благодарил (а): 0 раз.
Поблагодарили: 1 раз.
Блог: Просмотр блога (2)
Имя: Александр

Re: sim

Сообщение АЧ2-047 » 10.01.2010, 15:04

Ведь может родиться русский Е У Ноль Семь, и даже круче!

EU07 вроде с открытым кодом. Что мешает просто прикрутить к нему редактор и сделать наш ПС. Возможно вмонтировать вякие КЛУБ, САУТ, САВПЭ и иже с ними. Да и по графике его можно хотя бы до МСТС подтянуть. И в EU07 тяговые характеристики сделаны через сопротивления якорей, реостатов и шунтов, а не ломаными линиями.
TS2009 v.3.1 (Акелла)
MaSzyna EU07 v. 1.2.0.2, сборка 2009
MSTS bin v.1.8
Аватара пользователя
АЧ2-047
 
Сообщения: 374
Зарегистрирован: 12.11.2006, 18:30
Откуда: Москва
Благодарил (а): 0 раз.
Поблагодарили: 0 раз.
Играю в: ZDSim
Имя: Алексей

Re: sim

Сообщение break » 10.01.2010, 23:27

EU07 вроде с открытым кодом

Да ну& - дай ссылку - а может и MSTS открытый?, а может и TRAINZ? - Я кроме Open BVE еще ни одного открытого ж/д сима не видел.

Да и по графике его можно хотя бы до МСТС подтянуть.
- ну да хотя бы до 2000 года в 2010

а не ломаными линиями.

К твоему сведению эти ломанные линии тяговые характеристики взятые из ПТР(сомневаюсь что ты в курсе что-это иначе бы такую глупость не сказал). При расчете значение берется с интерполяцией - так что их ломанность никак не влияет. Кроме того
И в EU07 тяговые характеристики сделаны через сопротивления якорей, реостатов и шунтов

очень и очень врят ли - скорее всего берутся тяговые характеристики и на основе них выводятся токи на якоре и т.д. Чтобы перейти от напряженности магнитного потока на статоре двигателя к скорости вращения якоря - а потом и к скорости вращения бандажей с учетом всех редукторов, передаточных чисел и т.д. надо провести большое количесвто расчетов, для которых тупо может не быть исходных данных - количество зубьев на валах и т.д.

Для примера приведите мне хотя бы формулу расчета частоты вращения машины постоянного тока если известно сопротивление ее обмотки якоря - и не просто формулу а с возможностью расчета - и когда дойдете там до коэффициент-а C зависящего от конструкции двигателя - дайте мне ссылку где он указывается хоть для одного двигателя кот. используется в подвижном составе.

Это более производительно и проще реализуется в движке.

Не так уж и просто это реализовать - как упомянул выше AlexandrG надо разобраться с линковками экспортом и т.д. Но разработчиком дополнений это не может коснуться т.к. реализовано в SDK.

Но взамен мы получаем недостатки С++,

Я бы скорее подумал о достоинствах С++ - и о том какие исходя из этого не ограниченные никакими интерфейсами, скриптами и т.д. можно делать дополнения.

F это важно в случае с пользовательским контентом, так как ошибка в скрипте — исключение, максимум вылет из игры, а в С++ может привести к краху всей системы.

Это вы сами себе напридумывали - ошибка в любой программе должна приводить в крайнем случае только к ее вылету, и к коректному освобождению всех ресурсов после этого самой ОС. Если при ошибке программы вылетае ОС или еще хуже перестает запускаться - это ошибка или охрененный недостаток самой ОС. Мне такие случаи даже не известны! Не путайте с тем когда вирус стирает на вашем диске системные файлы - это не ошибка вируса и не ошибка ОС - а все работает так как и задумал автор вируса!
Кроме того в C++ достаточно средств для контроля таких возможных вылетов - например "умные указатели" - кто-то удалил объект - указатель сам себя очищает - при следующей попытке не произойдет обращение по старому адресу, где объекта уже нет. В современных скриптовых языках тоже есть подобные вещи - даже на уровне самого языка.

Также, я не уверен в переносимости таких ДЛЛ. К примеру, потребуется делать оболочку над АПИ ОС, ведь тот же КЛУБ должен иметь возможность писать в файл.

С платформонезависимостью в объектах хранящихся в DLL все в порядке, они читают из файла и пишут в него тоже, абсолютно независимо от платформы.
3)
agmike - разъясни мне некоторые свои доводы, а то что-то не понятно:

P.S. Вот, к примеру, задание простой схемы и вход в поток ее расчета на АГС:

Ну к сож. оценить не могу - может и круто, но мало что из исходника можно уловить - задаются параметры и все.

2)
Я считаю оптимальным такой подход, при котором классы, представляющие объекты в игре, связаны в иерархию: к примеру MeshObject — класс, имеющий модели и реализующий необходимый интерфейс для управления ими, к примеру, показать/скрыть лампочку, запустить анимацию, сменить текстуру и т.д.

Этот подход однажды приведет в тупик, потребуется использовать множественное наследование а потом и виртуальное наследование от которого больше проблем чем пользы. Во всех современных движках от него отказались, даже не в очень больших - Unity, UnEngine, кстати проблемы будут как раз у разработчиков дополнений. (Пример ошибочности данного подхода будет ниже с кранами, ВР-рами и двигателем...)
Класс Vehicle — производный от MeshObject и, возможно, других — зависит от реализации. Такая иерархия полностью соответствует тому, что мы видим в реальном мир

Наследование в реальном мире? Если вы имеете ввиду что с пом. этого подхода можно сделать то что мы видим в реальном мире - то да, но есть и другие более гибкие методы.
Другое дело, что в эту базовую функциональность вполне вписываются базовые модули — КЛУБы, САУТы, ВРы и т.д. Элементарно просто реализовывать свои объекты — пишем наследника от базового абстрактного класса, чуть-чуть исправить логику по умолчанию — пишем наследника от конкретного класса, КЛУБа и т. п.

Как то совсем голословно - и так есть базовый класс - в скрипте которого достаточно что-то прописать - и он сможет двигаться(вашит слова). Стоит сделать наследника - и он уже КЛУБ? (ну чуть-чуть подправиив логику?) А вас не смущает что клуб и тот класс который едет имеют мало общего (даже из вашего описания). Или может мы о разных КЛУБ-ая говорим (электронная карта, АЛСН, проверки бдительности, отработка кривой в зависимости от разных факторов а не только приближение к светофору, взаимодействие с пользователем - что тут общего с классом который может передвигаться в виртуальном мире?)

Элементарно просто реализовывать свои объекты — пишем наследника от базового абстрактного класса, чуть-чуть исправить логику по умолчанию — пишем наследника от конкретного класса, КЛУБа и т. п.

Если я вас понял (если нет поправьте) - то вы предлагаете например написать класс "УСТРОЙСТВО БЕЗОПАСНОСТИ" - которое унаследовано от базовго виртуального класса (вроде того самого который умеет ездить через указание параметров скрипта) и потом делаем класс КЛУБ, САУТ, САВП его наследниками?. Так вот - я был на этом пути и заметил что КЛУБ, САУТ, САВП имеют столько же общего как и "двигатель" и "кран машиниста". Они имеют общее название - но работают по разному - у каждого своя логика, базовый класс для них и получился на уровне "базовое вагонное устройство". А много ли общего у "Крана 395" и "Крана 254" - они подключаются к магистралям - внутри какие-то поршни - и все. Но работают совершенно по разному, неужели их тоже делать на уровне базового класса "Базовый кран машиниста". Аналогично ВР-ры. Тут вдруг появляется мысль - о "Базовое пневматическое устройство" - все его наследники - краны, ВР-ы и т.д. "Базовое электрическое устройство" - его наследники "двигатель, фаз-тель или что-то еще". И соответственно разнести функциональность по этим базовым классам. И тут вдруг надо сделать "Пневматический контактор" - который 100% пневмоустройство и 100% электроустройство - делаем двойное наследование? Мало того - в каждом из 2-х предков еще и предок "Виртуальное устройство которое может ездить скриптом" - нам будет палки в колеса совать. А если часть методов была одинаковой - даже простые - типа "setWagonNum()" - как быть? Какой из двух методов предков вернее использовать?

Устройства, наподобие фазорасщепителя, удобно рассматривать не как полностью независимые модули, а как части электрической схемы

Согласен так и делаю пока не потребуется задать для него неисправность - а это фактически добавить пару трпойку свойств - не логичнее чтобы св-ства объекта хранились в нем самом.

К примеру, класс Светофор может быть наследником класса Путевой объект, наследника MeshObject, впрочем, это детали.

Развитие примера: Класс Путь, Класс Путевой Объект, Класс Стрелка
Стрелка стоит на опр. линейной координате - значит Путевой объект, но она является частью Пути - Значит Путь? Опять двойное наследование?
А если потом нужно поставить Светофор на стрелку?
Я понимаю что Trainz и MSTS это реализовано - и нормально работает - но не факт что тем способом (бесконечное наследование одного от другого) о котором вы говорите. Хотя внутренностей этих игр не знаю - если есть подтверждение обратного готов выслушать.

По-моему, такая архитектура полностью вписывается в твои пункты, при этом обладая большим потенциалом по расширяемости, и решает проблему обособленности других объектов.

Так это не проблема обособленности объектов а фича такая, которая делалась специально - это удобно всем и объектам и тем кто их делает. Опишите мне саму проблему то в чем она? - как вы ее понимаете?

Еще одно преимущество такого похода — в строгом контроле типов. Если я использую для моего КЛУБа ЭПК программиста Пети, я буду иметь перед глазами точный его интерфейс и строгий контроль типов со стороны компилятора, что гарантирует мне, что никакой другой ЭПК не сможет неявно работать с моим КЛУБом и являться источником потенциальных ошибок. Конечно, этот пример кажется немного неудачным — ведь если я делаю вагон, то и знаю какой на нем стоит ЭПК. Но представим, что моему КЛУБу нужно обратиться к ЭПК на другом вагоне — и тут возможные различия могут сыграть свою роковую роль. Особенно если вместо ЭПК и КЛУБа будут стоять объекты, обладающие более сложной логикой взаимодействия.

Очень хороший пример - только доказывает проблему вашей концепции а не моей - смотрите сами - я обращаюсь через свойства, и не знаю "Класс ЭПК другого вагона" - если у того нет такого свойства к которому я обращаюсь, или он с ним не работает -то в моей структуре - как я и говорил уже несуществующее свойство создасться, работать правильно не будет и все. А в вашем случае вы просто не сможете написать Клуб который будет работать с "ЭПК программиста Пети" на другом вагоне. Т.к. Программист Петя не дал вам исходник своего ЭПК и компилятор не может осуществить контроль типов и т.д. А если вы скомпиляете со своим классом ЭПК - а подсунете класс ЭПК Пети - то здесь то и возможны проблемы вылета из игры.. Это и есть пример демонструрующий выгодность обособленности объектов. Кроме того далеко не все захотят делиться исходниками - а вот сказать какимим свойствами нужно пользоваться для правильной работы и выложить скомпиленную DLL не проблема - вы же свободно обмениваетесь "скомпиленными" моделями 3D.

AlexandrG просил пример DLL - вот он: в отличие от ваших примеров это полный класс сидящий в DLL - кран 395
Код: Выделить всё

#include "BC_395.h"

#include <QDebug>
#include "PhUtils.h"
#include "XmlSettings.h"
#include "ServerTrainController.h"
#include "ServerTrainWagonController.h"
#include "AirConnection.h"
#include "AirVolume.h"

#define DEFAULT_OVER_EQHOLE_TO_EQ_K    (0.0016 / 27.0)
#define DEFAULT_GM_TO_OVER_EQHOLE_1_K  (0.005 / 27.0)
#define DEFAULT_GM_TO_TM_1_K           (0.007 / 10.0)
#define DEFAULT_GM_TO_OVER_EQHOLE_2_K  (0.003 / 27.0)
#define DEFAULT_RES_EQ_TO_TM_3_K       (0.010)
#define DEFAULT_RES_EQ_TO_ATM_51_K     (0.00075 / 37.0)
#define DEFAULT_RES_EQ_TO_ATM_5_K      (0.0023 / 10.0)
#define DEFAULT_OVER_EQHOLE_TO_ATM_6_K (0.0035)
#define DEFAULT_RES_EQ_TO_ATM_6_K      (0.003)
#define DEFAULT_TM_TO_ATM_6_K          (0.016)
#define DEFAULT_GM_TO_TM_K             (0.018 / 27.0)
#define DEFAULT_TM_TO_ATM_K            (0.018 / 17.0)

#define DEFAULT_VENT_2S_MIN_P  0.001f
#define DEFAULT_VENT_2S_MAX_P  0.1f
#define DEFAULT_REDUCT_P       4.7
#define DEFAULT_RES_EQ_P       4.7
#define DEFAULT_GM_CHARGE_P    8.0

#define DEFAULT_ENTER_GM "BC_395_GM_Pipe__head"
#define DEFAULT_ENTER_TM "BC_395_TM_Pipe__head"

CBC_395::CBC_395()
{
   m_pOverEQHole_Vol           = 0;
   m_pResEQ_Vol                = 0;

   m_pOverEQHole_to_EQ_Conn    = 0;
   m_pGM_to_OverEQHole_1_Conn  = 0;
   m_pGM_to_TM_1_Conn          = 0;
   m_pGM_to_OverEQHole_2_Conn  = 0;
   m_pResEQ_to_TM_3_Conn       = 0;
   m_pResEQ_to_Atm_51_Conn     = 0;
   m_pResEQ_to_Atm_5_Conn      = 0;
   m_pOverEQHole_to_Atm_6_Conn = 0;
   m_pResEQ_to_Atm_6_Conn      = 0;
   m_pTM_to_Atm_6_Conn         = 0;

   m_pGM_to_TM_Trigger         = 0;
   m_pTM_to_Atm_Trigger        = 0;
}

CBC_395::~CBC_395()
{
}

void CBC_395::onValueChanged( CSharedVariant& Value )
{
   IWagDev::onValueChanged( Value );

   if ( &Value == m_CDP.m_pGear_BC_395 )
   {
      updateHoles();
      return;
   };

   if ( &Value == m_CDP.m_pGear_EPT )
   {
      updateEPT_Switches();
   };
}

void CBC_395::onTick( double fSec )
{
   m_pGM_to_OverEQHole_2_Conn->setK( 0 );

   switch ( m_CDP.m_pGear_BC_395->asInt() )
   {
   case (1):
      {
         m_CDP.setSndGain( m_CDP.m_pSound_BC_395_GM_to_TM_1, (getEnter_GM_P()-getEnter_TM_P()) / (m_fGM_Charge_P-m_fReductP) );

         break;
      };
   case (2):
      {

         // разность давлений на кот. отрегулирован редуктор и Ур. рез.
         float delta = PascalToKgF_SQcm( m_fReductP - getEQ_P() );
         if (delta > 0.001)                   // дозарядка до зарядного 0.003
            m_pGM_to_OverEQHole_2_Conn->setK( 1 );
         else if (delta < -0.001)             // ликвидация сверхзарядки постоянным темпом
            m_pResEQ_Vol->setPressure( getEQ_P() - 150*fSec );

         // пока звук редуктора + стабилизатора хаком
         m_CDP.setSndGain( m_CDP.m_pSound_BC_395_GM_to_TM_2, (getEnter_GM_P()-getEnter_TM_P()) / (m_fGM_Charge_P-m_fReductP) );
         //m_CDP.setSndGain( m_CDP.m_pSound_BC_395_GM_to_TM_2, 1 );
         break;
      };
   case (51):
      {
         float gain = getEnter_TM_P() / m_fReductP;

         m_CDP.setSndGain( m_CDP.m_pSound_BC_395_TM_to_ATM_5A, gain );
         m_CDP.playSnd( m_CDP.m_pSound_BC_395_TM_to_ATM_5A );
         break;
      };
   case (5):
      {
         float gain = getEnter_TM_P() / m_fReductP;

         m_CDP.setSndGain( m_CDP.m_pSound_BC_395_TM_to_ATM_5, gain );
         m_CDP.playSnd( m_CDP.m_pSound_BC_395_TM_to_ATM_5 );
         break;
      };
   case (6):
      {
         float gain = getEnter_TM_P() / m_fReductP;

         m_CDP.setSndGain( m_CDP.m_pSound_BC_395_TM_to_ATM_6, gain );
         m_CDP.playSnd( m_CDP.m_pSound_BC_395_TM_to_ATM_6 );
         break;
      };
   default: break;
   };

   // обновление параметров для передачи в сеть
   m_CDP.m_pBC_395_EQ_P-> setFloat( PascalToKgF_SQcm( getEQ_P() ), satNormal, 0.01f );
   //m_CDP.m_pBoard_OverEQHole_P->setFloat( PascalToKgF_SQcm( getOverEQHole_P() ), satNormal, 0.01f );


   // В 3-м положении крана необходимо обеспечить перекрышу без питания ТМ
   // воздух должен выйти через обратный клапан из полости над Ур.Поршнем в ТМ
   // и двухседельчатый клапан должен быть закрыт в обоих направлениях
   // но если темп утечки из ТМ больше чем m_Vent_2S_min_P(значение при кот. клапан полностью закрыт)
   // то происходит подпитка ТМ из ГМ, вероятно из-за того что в пневмосистеме не учитывается порядок
   // обработки соединений... В связи с этим блокируем работу двухседельчатого клапана
   // при 3-ем положении крана принудительно!!!

   m_pGM_to_TM_Trigger  -> setState( m_CDP.m_pGear_BC_395->asInt() != 3 );
   m_pTM_to_Atm_Trigger -> setState( m_CDP.m_pGear_BC_395->asInt() != 3 );
}

void CBC_395::initLogicParams()
{
   // Инициализация логических параметров устройства
   m_fOverEQHole_to_EQ_K    = DEFAULT_OVER_EQHOLE_TO_EQ_K;
   m_fGM_to_overEQHole_1_K  = DEFAULT_GM_TO_OVER_EQHOLE_1_K;
   m_fGM_to_TM_1_K          = DEFAULT_GM_TO_TM_1_K;
   m_fGM_to_overEQHole_2_K  = DEFAULT_GM_TO_OVER_EQHOLE_2_K;
   m_fResEQ_to_TM_3_K       = DEFAULT_RES_EQ_TO_TM_3_K;
   m_fResEQ_to_Atm_51_K     = DEFAULT_RES_EQ_TO_ATM_51_K;
   m_fResEQ_to_Atm_5_K      = DEFAULT_RES_EQ_TO_ATM_5_K;
   m_fOverEQHole_to_Atm_6_K = DEFAULT_OVER_EQHOLE_TO_ATM_6_K;
   m_fResEQ_to_Atm_6_K      = DEFAULT_RES_EQ_TO_ATM_6_K;
   m_fTM_to_Atm_6_K         = DEFAULT_TM_TO_ATM_6_K;
   m_fGM_to_TM_K            = DEFAULT_GM_TO_TM_K;
   m_fTM_to_Atm_K           = DEFAULT_TM_TO_ATM_K;

   m_fVent_2S_min_P = KgF_SQcmToPascal( DEFAULT_VENT_2S_MIN_P );
   m_fVent_2S_max_P = KgF_SQcmToPascal( DEFAULT_VENT_2S_MAX_P );
   m_fReductP       = KgF_SQcmToPascal( initParam( DEFAULT_REDUCT_P, "TM_Charge_P" ).toDouble() );
   m_fResEQ_P       = KgF_SQcmToPascal( initParam( DEFAULT_RES_EQ_P, "TM_P" ).toDouble() );
   m_fGM_Charge_P   = KgF_SQcmToPascal( initParam( DEFAULT_GM_CHARGE_P, "GM_Charge_P" ).toDouble() );

   m_sEnter_GM = DEFAULT_ENTER_GM;
   m_sEnter_TM = DEFAULT_ENTER_TM;

   m_processType   = TrainConsts::adptChargeAndRelease;
}

void CBC_395::loadFromXML( QString sFName )
{
   CXmlSettings xml( sFName );

   xml.settings().beginGroup( "Options" );

   m_fOverEQHole_to_EQ_K = readParamFromXML( xml, "OverEQHole_to_EQ_K",
                                   QString::fromUtf8("отверстие 1.6 мм соед. полость над поршнем с Уравнительным рез."),
                                   DEFAULT_OVER_EQHOLE_TO_EQ_K ).toDouble();

   // положение 1 - Зарядка и отпуск
   m_fGM_to_overEQHole_1_K = readParamFromXML( xml, "GM_to_overEQHole_1_K",
                                    QString::fromUtf8("отверстие 5 мм из ГМ для зарядки полости над уравнительным поршнем при 1 положении"),
                                    DEFAULT_GM_TO_OVER_EQHOLE_1_K ).toDouble();

   m_fGM_to_TM_1_K = readParamFromXML( xml, "GM_to_TM_1_K",
                              QString::fromUtf8("прямое соединение ГМ и ТМ при 1 положении"),
                              DEFAULT_GM_TO_TM_1_K ).toDouble();

   // положение 2 - Поездное
   m_fGM_to_overEQHole_2_K = readParamFromXML( xml, "GM_to_overEQHole_2_K",
                                    QString::fromUtf8("дозарядка до зарядного - через редуктор 3 мм - при 2 положении"),
                                    DEFAULT_GM_TO_OVER_EQHOLE_2_K ).toDouble();

   // положение 3 - Перекрыша без питания ТМ
   m_fResEQ_to_TM_3_K = readParamFromXML( xml, "ResEQ_to_TM_3_K",
                                 QString::fromUtf8("соед. Ур. поршня с ТМ для выравн давлений через обратный клапан при 3 положении"),
                                 DEFAULT_RES_EQ_TO_TM_3_K ).toDouble();

   // положение 4 - Перекрыша с питанием ТМ
   // никаких соединений не открывается

   m_fResEQ_to_Atm_51_K = readParamFromXML( xml, "ResEQ_to_Atm_51_K",
                                 QString::fromUtf8("положение 5А - Служебное положение длинносоставного поезда или ЭПТ 0.75 мм"),
                                 DEFAULT_RES_EQ_TO_ATM_51_K ).toDouble();

   m_fResEQ_to_Atm_5_K = readParamFromXML( xml, "ResEQ_to_Atm_5_K",
                                 QString::fromUtf8("положение 5 - Служебное торможение 2.3 мм"),
                                 DEFAULT_RES_EQ_TO_ATM_5_K ).toDouble();

   // положение 6 - Экстренное торможение
   m_fOverEQHole_to_Atm_6_K = readParamFromXML( xml, "OverEQHole_to_Atm_6_K",
                                     QString::fromUtf8("соединение полости над Ур. поршнем с АТМ"),
                                     DEFAULT_OVER_EQHOLE_TO_ATM_6_K ).toDouble();

   m_fResEQ_to_Atm_6_K = readParamFromXML( xml, "OverEQHole_to_Atm_6_K",
                                 QString::fromUtf8("соединение полости Ур. поршня с АТМ"),
                                 DEFAULT_RES_EQ_TO_ATM_6_K ).toDouble();

   m_fTM_to_Atm_6_K = readParamFromXML( xml, "TM_to_Atm_6_K",
                               QString::fromUtf8("соединение ТМ с АТМ"),
                               DEFAULT_TM_TO_ATM_6_K ).toDouble();

   // соединения для зарядки и разрядки ТМ с пом. двухседельчатого клапана
   m_fGM_to_TM_K = readParamFromXML( xml, "GM_to_TM_K",
                             QString::fromUtf8("соединение ГМ с ТМ через двухседельчатый клапан"),
                             DEFAULT_GM_TO_TM_K ).toDouble();

   m_fTM_to_Atm_K = readParamFromXML( xml, "TM_to_Atm_K",
                              QString::fromUtf8("соединение ТМ с АТМ через двухседельчатый клапан"),
                             DEFAULT_TM_TO_ATM_K ).toDouble();

   //*************************************************************************

   double fVal;

   fVal = readParamFromXML( xml, "Vent_2S_min_P",
                      QString::fromUtf8("минимальное значение разницы - ниже которого двухседельчатый клапан закрыт полностью"),
                      DEFAULT_VENT_2S_MIN_P ).toDouble();
   m_fVent_2S_min_P = KgF_SQcmToPascal( fVal );

   fVal = readParamFromXML( xml, "Vent_2S_max_P",
                      QString::fromUtf8("максимальное значение разницы - выше которого двухседельчатый клапан открыт полностью"),
                      DEFAULT_VENT_2S_MAX_P ).toDouble();
   m_fVent_2S_max_P = KgF_SQcmToPascal( fVal );

   fVal = readParamFromXML( xml, "Reduct_P",
                      QString::fromUtf8("Давление на которое отрегулирован редуктор"),
                      DEFAULT_REDUCT_P, "TM_Charge_P" ).toDouble();
   m_fReductP = KgF_SQcmToPascal( fVal );

   fVal = readParamFromXML( xml, "ResEQ_P",
                      QString::fromUtf8("Давление в Ур. резервуаре"),
                      DEFAULT_RES_EQ_P, "TM_P" ).toDouble();
   m_fResEQ_P = KgF_SQcmToPascal( fVal );

   fVal = readParamFromXML( xml, "GM_Charge_P",
                      QString::fromUtf8("Зарядное давление ГМ"),
                      DEFAULT_GM_CHARGE_P, "GM_Charge_P" ).toDouble();
   m_fGM_Charge_P = KgF_SQcmToPascal( fVal );

   //*************************************************************************

   m_sEnter_GM = readParamFromXML( xml, "Enter_GM",
                           QString::fromUtf8("подключение к ГМ"),
                           DEFAULT_ENTER_GM ).toString();

   m_sEnter_TM = readParamFromXML( xml, "Enter_TM",
                           QString::fromUtf8("подключение к ГМ"),
                           DEFAULT_ENTER_TM ).toString();

   xml.settings().endGroup();
}

void CBC_395::init()
{
   m_TDP.assign_connect_TrainProps( getServerTrain()->getTrainType(), satWeak );

   m_CDP.assignGears( getServerTrain()->getTrainType(), satWeak );
   m_CDP.m_pGear_BC_395->connectTo( this );
   m_CDP.m_pGear_EPT->connectTo( this );

   m_CDP.assignBC_395_Data();
   m_CDP.connectBC_395_Data( this );

   m_CDP.assignSounds( getServerTrain()->getTrainType(), satWeak );

   m_CDP.assignEPT_Props( satWeak );


   // создание резервуаров
   // уравнительный резервуар - 20л
   m_pResEQ_Vol      = getAirManager()->addReservoir( 0.02,   m_fResEQ_P );
   // 0,2л камера над поршнем
   m_pOverEQHole_Vol = getAirManager()->addReservoir( 0.0002, m_fResEQ_P );

   // создание пневмо соединений
   // отверстие 1.6 мм соед. полость над поршнем с Уравнительным рез.
   m_pOverEQHole_to_EQ_Conn = getAirManager()->addConnection( m_pOverEQHole_Vol, m_pResEQ_Vol,
                                                m_fOverEQHole_to_EQ_K, m_fOverEQHole_to_EQ_K, 1.0f );

   // положение 1 - Зарядка и отпуск
   // отверстие 5 мм из ГМ для зарядки полости над уравнительным поршнем при 1 положении
   m_pGM_to_OverEQHole_1_Conn = getAirManager()->addConnection( getEnter_GM(), m_pOverEQHole_Vol,
                                                 m_fGM_to_overEQHole_1_K,
                                                 m_fGM_to_overEQHole_1_K, 0 );
   // прямое соединение ГМ и ТМ при 1 положении
   m_pGM_to_TM_1_Conn = getAirManager()->addConnection( getEnter_GM(), getEnter_TM(),
                                          m_fGM_to_TM_1_K,
                                          m_fGM_to_TM_1_K, 0 );

   // положение 2 - Поездное
   // дозарядка до зарядного - через редуктор 3 мм - при 2 положении
   m_pGM_to_OverEQHole_2_Conn = getAirManager()->addConnection( getEnter_GM(), m_pOverEQHole_Vol,
                                                 m_fGM_to_overEQHole_2_K,
                                                 m_fGM_to_overEQHole_2_K, 0 );

   // положение 3 - Перекрыша без питания ТМ
   // соед. Ур. поршня с ТМ для выравн давлений через обратный клапан при 3 положении
   m_pResEQ_to_TM_3_Conn = getAirManager()->addConnection( m_pResEQ_Vol, getEnter_TM(),
                                             m_fResEQ_to_TM_3_K, 0, 0 );

   // положение 4 - Перекрыша с питанием ТМ

   // положение 5А - Служебное положение длинносоставного поезда или ЭПТ 0.75 мм
   m_pResEQ_to_Atm_51_Conn = getAirManager()->addConnection( m_pResEQ_Vol, getAirManager()->atmosphere(),
                                               m_fResEQ_to_Atm_51_K, 0, 0 );

   // положение 5 - Служебное торможение
   m_pResEQ_to_Atm_5_Conn = getAirManager()->addConnection( m_pResEQ_Vol, getAirManager()->atmosphere(),
                                              m_fResEQ_to_Atm_5_K, m_fResEQ_to_Atm_5_K, 0); // 2.3 мм

   // положение 6 - Экстренное положение
   m_pOverEQHole_to_Atm_6_Conn = getAirManager()->addConnection( m_pOverEQHole_Vol, getAirManager()->atmosphere(),
                                                  m_fOverEQHole_to_Atm_6_K, 0, 0 ); // 3.5 мм
   m_pResEQ_to_Atm_6_Conn      = getAirManager()->addConnection( m_pResEQ_Vol, getAirManager()->atmosphere(),
                                                  m_fResEQ_to_Atm_6_K, 0, 0 ); // 3 мм
   m_pTM_to_Atm_6_Conn         = getAirManager()->addConnection( getEnter_TM(), getAirManager()->atmosphere(),
                                                  m_fTM_to_Atm_6_K, 0, 0 ); //16 мм

   // триггеры двухседельчатого клапана
   m_pGM_to_TM_Trigger  = getAirManager()->addTrigger( getEnter_GM(), getEnter_TM(),
                                          getEnter_TM(), m_pOverEQHole_Vol,
                                          m_fVent_2S_min_P, m_fVent_2S_max_P,
                                          m_fGM_to_TM_K );
   m_pTM_to_Atm_Trigger  = getAirManager()->addTrigger( getEnter_TM(), getAirManager()->atmosphere(),
                                          m_pOverEQHole_Vol, getEnter_TM(),
                                          m_fVent_2S_min_P, m_fVent_2S_max_P,
                                          m_fTM_to_Atm_K );

   //test leak//getAirManager()->addConnection( getEnter_TM(), getAirManager()->atmosphere(), 0.0001, 0.0001, 1.0 );
}

void CBC_395::updateHoles()
{
   closeSomeConnections();

   switch ( m_CDP.m_pGear_BC_395->asInt() )
   {
   case 1:
      {
         m_processType = TrainConsts::adptChargeAndRelease;

         // отверстие 5 мм из ГМ для зарядки полости над уравнительным поршнем при 1 положении
         m_pGM_to_OverEQHole_1_Conn->setK( 1 );

         // прямое соединение ГМ и ТМ
         m_pGM_to_TM_1_Conn->setK( 1 );

         // озвучка
         m_CDP.playSnd( m_CDP.m_pSound_BC_395_GM_to_TM_1 );

         break;
      };
   case 2:
      {
         m_processType = TrainConsts::adptChargeAndRelease;
         // код в onAirStep() т.к. зависит от давлений

         // озвучка
         m_CDP.playSnd( m_CDP.m_pSound_BC_395_GM_to_TM_2 );
         break;
      };
   case 3:
      {
         m_processType = TrainConsts::adptCover;
         m_pResEQ_to_TM_3_Conn->setK( 1 );
         break;
      };
   case 4:
      {
         m_processType = TrainConsts::adptCover;
         break;
      };
   case 51:
      {
         m_processType = TrainConsts::adptBrake;
         m_pResEQ_to_Atm_51_Conn->setK( 1 ); // 0.00075
         break;
      };
   case 5:
      {
         m_processType = TrainConsts::adptBrake;
         m_pResEQ_to_Atm_5_Conn->setK( 1 ); // 0.0023
         break;
      };
   case 6:
      {
         m_processType = TrainConsts::adptExtraBrake;
         m_pOverEQHole_to_Atm_6_Conn->setK( 1 );
         m_pResEQ_to_Atm_6_Conn->setK( 1 );
         m_pTM_to_Atm_6_Conn->setK( 1 );
         break;
      };
   };

   CBC_395::updateEPT_Switches();
}

void CBC_395::updateEPT_Switches()
{
   // тумблер ЭПТ выключен, питание на вентили не подается с крана машиниста
   if ( !m_CDP.m_pGear_EPT->asInt() )
   {
      m_CDP.m_pEPT_OV_BrakeCrane->setInt( 0 );
      m_CDP.m_pEPT_TV_BrakeCrane->setInt( 0 );
      return;
   };

   // если тумблер включен, питание подается в соответствие с положением ручки крана
   switch ( m_CDP.m_pGear_BC_395->asInt() )
   {
   case (1):
   case (2):
      {
         m_CDP.m_pEPT_OV_BrakeCrane->setInt( 0 );
         m_CDP.m_pEPT_TV_BrakeCrane->setInt( 0 );
         break;
      };
   case (3):
   case (4):
      {
         m_CDP.m_pEPT_OV_BrakeCrane->setInt( 1 );
         m_CDP.m_pEPT_TV_BrakeCrane->setInt( 0 );
         break;
      };
   case (51):
   case (5):
   case (6):
      {
         m_CDP.m_pEPT_OV_BrakeCrane->setInt( 1 );
         m_CDP.m_pEPT_TV_BrakeCrane->setInt( 1 );
         break;
      };
   };
}

void CBC_395::closeSomeConnections()
{
   // закрываем все соединения определяемые положением ручки крана
   m_pGM_to_OverEQHole_1_Conn  -> setK( 0 );
   m_pGM_to_TM_1_Conn          -> setK( 0 );
   m_pGM_to_OverEQHole_2_Conn  -> setK( 0 );
   m_pResEQ_to_TM_3_Conn       -> setK( 0 );
   m_pResEQ_to_Atm_51_Conn     -> setK( 0 );
   m_pResEQ_to_Atm_5_Conn      -> setK( 0 );
   m_pOverEQHole_to_Atm_6_Conn -> setK( 0 );
   m_pResEQ_to_Atm_6_Conn      -> setK( 0 );
   m_pTM_to_Atm_6_Conn         -> setK( 0 );

   // выключаем все звуки крана
   m_CDP.stopSnd( m_CDP.m_pSound_BC_395_GM_to_TM_1 );
   m_CDP.stopSnd( m_CDP.m_pSound_BC_395_GM_to_TM_2 );
   m_CDP.stopSnd( m_CDP.m_pSound_BC_395_TM_to_ATM_5A );
   m_CDP.stopSnd( m_CDP.m_pSound_BC_395_TM_to_ATM_5 );
   m_CDP.stopSnd( m_CDP.m_pSound_BC_395_TM_to_ATM_6 );
}

float CBC_395::getOverEQHole_P()
{
   return m_pOverEQHole_Vol->pressure();
}

float CBC_395::getEQ_P()
{
   Q_ASSERT( m_pResEQ_Vol );
   return m_pResEQ_Vol->pressure();
}

CAirVolume * CBC_395::getEnter_GM()
{
   CAirVolume * pVolume = checkVolume( m_sEnter_GM );
   return pVolume;
}

CAirVolume * CBC_395::getEnter_TM()
{
   CAirVolume * pVolume = checkVolume( m_sEnter_TM );
   return pVolume;
}

float CBC_395::getEnter_GM_P()
{
   CAirVolume * pVolume = checkVolume( m_sEnter_GM );
   return pVolume->pressure();
}

float CBC_395::getEnter_TM_P()
{
   CAirVolume * pVolume = checkVolume( m_sEnter_TM );
   return pVolume->pressure();
}



2. Какой планируется метод распространения?

Очень сложный вопрос не зависящий от меня одного. И основная зацепка - надо ли это тем кто его делает.

Ну ок, поговорим, когда сим станет радикально лучше ТРС, КРС и МСТС во всем.

Честно не понял что вы имели ввиду.. Вообще не было цели сделать "самый лучший сим". И что бы изменилось если бы он стал таким?
Аватара пользователя
break
 
Сообщения: 202
Зарегистрирован: 26.02.2007, 16:49
Откуда: Voronezh
Благодарил (а): 0 раз.
Поблагодарили: 9 раз.

Re: sim

Сообщение AlexanderG » 11.01.2010, 00:11

не ограниченные никакими интерфейсами, скриптами и т.д. можно делать дополнения.
Возможность экспорта функций из ДЛЛ vs. возможность полного применения ООП? Дело явно не в пользу ДЛЛ. Я в ВЛ10, например, из кабины напрямую вызываю в локомотиве методы, безо всяких интерфейсов. КЛУБ-У я реализовал как прослойку между стандартным классом кабины и пользовательским — интеграция осуществляется в десять строчек. Опять же, никаких интерфейсов и возможность использования КЛУБа абсолютно везде без внесения изменений.

Ну к сож. оценить не могу - может и круто, но мало что из исходника можно уловить - задаются параметры и все.
Задается граф, описывающий электрическую цепь, создаются объекты, описывающие её элементы и запускается расчет. Опять же, можно откуда угодно получить доступ к чему угодно — ко всему графу, или к конкретной вершине, или перенастроить некие общие параметры моделиющего объекта.

Этот подход однажды приведет в тупик, потребуется использовать множественное наследование
Уже есть, очень удобно.

Стрелка стоит на опр. линейной координате - значит Путевой объект, но она является частью Пути - Значит Путь? Опять двойное наследование?
Класс Путь (независимый), классы ПутевойОбъект>Стрелка.

А если потом нужно поставить Светофор на стрелку?
Плохой пример.

но не факт что тем способом (бесконечное наследование одного от другого) о котором вы говорите
Тем-тем. Могу дерево классов предоставить.

А в вашем случае вы просто не сможете написать Клуб который будет работать с "ЭПК программиста Пети" на другом вагоне. Т.к. Программист Петя не дал вам исходник своего ЭПК и компилятор не может осуществить контроль типов и т.д.
Вот в этом случае, если выражаться метафорически, при отсутствии хидерных файлов, придется делать интерфейсы. Но у нас есть стандартная вещь, называемая Soup, фактически — база данных, которая есть у 95% всех объектов. Петя просто указывает в своем Супе некий параметр под определенным именем, дальше с ним может работать кто угодно. Если я правильно понял, это то же, что предлагаешь ты — публичные поля с заранее известными именами.

В библиотеке я не понял один момент — если симу от нее что-то нужно, тут понятно — он вызывает экспортированную функцию. А если библиотека хочет что-то сделать в симе? Звук проиграть, например? Тут всплывает непонятный объект m_CDP. И где объявлены функции getServerTrain() и иже с ними?

И что бы изменилось если бы он стал таким?
Я бы с радостью в него перешел :)

Вообще не было цели сделать "самый лучший сим"
А какая цель? Сделать сим, который чуть лучше в одном, но безнадежно отстает во всем остальном?
Join Dropbox and SHARE YOUR SHIT FOR FREE!
AlexanderG
 
Сообщения: 761
Зарегистрирован: 27.06.2009, 16:54
Благодарил (а): 0 раз.
Поблагодарили: 1 раз.
Блог: Просмотр блога (2)
Имя: Александр

Re: sim

Сообщение break » 11.01.2010, 00:43

Возможность экспорта функций из ДЛЛ vs. возможность полного применения ООП? Дело явно не в пользу ДЛЛ. Я в ВЛ10, например, из кабины напрямую вызываю в локомотиве методы, безо всяких интерфейсов. КЛУБ-У я реализовал как прослойку между стандартным классом кабины и пользовательским — интеграция осуществляется в десять строчек. Опять же, никаких интерфейсов и возможность использования КЛУБа абсолютно везде без внесения изменений.

В библиотеке я не понял один момент — если симу от нее что-то нужно, тут понятно — он вызывает экспортированную функцию. А если библиотека хочет что-то сделать в симе? Звук проиграть, например? Тут всплывает непонятный объект m_CDP. И где объявлены функции getServerTrain() и иже с ними?

Да нет здесь с ООП все в порядке - в ДЛЛ просто хранится класс, когда класс загружен (посредством указания имени ДЛЛ в фале вагона) - его экземпляр создается в вагоне и безо всяких интерфейсов дергаются ф-ции, св-ства, вагона, поезда и др. Есть способы хранить классы в ДЛЛ и в том числе кросплатформенные. Никто с экспортированными ф-ями не работает - может поэтому все дико отреагировали на ДЛЛ? - там только классы которые загрузившись 1 раз становятся такими же классми движка как все остальное.

m_CDP. И где объявлены функции getServerTrain()

Ну сори рабочий полностью код я не обещал выложить...

КЛУБ-У я реализовал как прослойку между стандартным классом кабины и пользовательским — интеграция осуществляется в десять строчек.

Ну не верю я что Клуб из 10 строчек будет работать как реальный - К799/800 может?, К0? П, Л, ВК, отработка кривой - только не давай ссылку на настоящий клуб - просто напиши по пунктам что может этот клуб - кот. вроде всего лишь 10 строчек в коде.

Тем-тем. Могу дерево классов предоставить.

давай

Вот в этом случае, если выражаться метафорически, при отсутствии хидерных файлов, придется делать интерфейсы. Но у нас есть стандартная вещь, называемая Soup, фактически — база данных, которая есть у 95% всех объектов. Петя просто указывает в своем Супе некий параметр под определенным именем, дальше с ним может работать кто угодно. Если я правильно понял, это то же, что предлагаешь ты — публичные поля с заранее известными именами.

И через 5 страниц выясняется что все спорили с тем же, чем сами пользуетесь.
Аватара пользователя
break
 
Сообщения: 202
Зарегистрирован: 26.02.2007, 16:49
Откуда: Voronezh
Благодарил (а): 0 раз.
Поблагодарили: 9 раз.

Re: sim

Сообщение agmike » 11.01.2010, 00:44

break писал(а):Я бы скорее подумал о достоинствах С++ - и о том какие исходя из этого не ограниченные никакими интерфейсами, скриптами и т.д. можно делать дополнения.

Ограничение аналогичны варианту с Моно — экспорт функций игры.
Это вы сами себе напридумывали - ошибка в любой программе должна приводить в крайнем случае только к ее вылету, и к коректному освобождению всех ресурсов после этого самой ОС. Если при ошибке программы вылетае ОС или еще хуже перестает запускаться - это ошибка или охрененный недостаток самой ОС. Мне такие случаи даже не известны! Не путайте с тем когда вирус стирает на вашем диске системные файлы - это не ошибка вируса и не ошибка ОС - а все работает так как и задумал автор вируса!

Возможно я переборщил с последствиями, но при программировании ПС приятнее видеть исключение и указанием номера строки, а не вылет из игры.
Кроме того в C++ достаточно средств для контроля таких возможных вылетов - например "умные указатели" - кто-то удалил объект - указатель сам себя очищает - при следующей попытке не произойдет обращение по старому адресу, где объекта уже нет. В современных скриптовых языках тоже есть подобные вещи - даже на уровне самого языка.

Не только в скриптовых языках — Java и языки дотНэт, конечно, могут использоваться как скриптовые, но они гораздо более широкого профиля. Причем это в них не просто на уровне языка, а одна из концепций, на которых они строятся.
С платформонезависимостью в объектах хранящихся в DLL все в порядке, они читают из файла и пишут в него тоже, абсолютно независимо от платформы.

В случае с Qt не могу возражать :)

Ну к сож. оценить не могу - может и круто, но мало что из исходника можно уловить - задаются параметры и все.

Я и хотел показать, что если программирование и есть, то оно декларативно по большей мере. Если интересует исходник, я могу прислать их все в ЛС, так как объем все же велик.
Этот подход однажды приведет в тупик, потребуется использовать множественное наследование а потом и виртуальное наследование от которого больше проблем чем пользы.

От множественного наследования можно достаточно просто избавиться (см ниже).
Наследование в реальном мире? Если вы имеете ввиду что с пом. этого подхода можно сделать то что мы видим в реальном мире - то да, но есть и другие более гибкие методы.

Хотелось бы узнать про них, так как нигде еще на них сам не натыкался и потому не представляю о чем речь.
Как то совсем голословно - и так есть базовый класс - в скрипте которого достаточно что-то прописать - и он сможет двигаться(вашит слова). Стоит сделать наследника - и он уже КЛУБ? (ну чуть-чуть подправиив логику?) А вас не смущает что клуб и тот класс который едет имеют мало общего (даже из вашего описания).

Нет, я совсем не то имел в виду. Я хотел сказать, что если есть базовый класс, то в нем есть и базовая функциональность. Без необходимости писать модуль для езды с постоянной скоростью в зависимости от положения КМ.
Если я вас понял (если нет поправьте) - то вы предлагаете например написать класс "УСТРОЙСТВО БЕЗОПАСНОСТИ" - которое унаследовано от базовго виртуального класса (вроде того самого который умеет ездить через указание параметров скрипта) и потом делаем класс КЛУБ, САУТ, САВП его наследниками?. Так вот - я был на этом пути и заметил что КЛУБ, САУТ, САВП имеют столько же общего как и "двигатель" и "кран машиниста". Они имеют общее название - но работают по разному - у каждого своя логика, базовый класс для них и получился на уровне "базовое вагонное устройство". А много ли общего у "Крана 395" и "Крана 254" - они подключаются к магистралям - внутри какие-то поршни - и все. Но работают совершенно по разному, неужели их тоже делать на уровне базового класса "Базовый кран машиниста". Аналогично ВР-ры. Тут вдруг появляется мысль - о "Базовое пневматическое устройство" - все его наследники - краны, ВР-ы и т.д. "Базовое электрическое устройство" - его наследники "двигатель, фаз-тель или что-то еще". И соответственно разнести функциональность по этим базовым классам. И тут вдруг надо сделать "Пневматический контактор" - который 100% пневмоустройство и 100% электроустройство - делаем двойное наследование? Мало того - в каждом из 2-х предков еще и предок "Виртуальное устройство которое может ездить скриптом" - нам будет палки в колеса совать. А если часть методов была одинаковой - даже простые - типа "setWagonNum()" - как быть? Какой из двух методов предков вернее использовать?

Не вижу разницы во взаимодействии КЛУБа и САУТа с вагоном. Они обращаются к методам вагона, они подключаются к электрической цепи управления вагона, они отображают свое состояние на модели вагона. То, какая логика у них внутри без разницы, это вполне обычная ситуация для ООП. Точно так же, какая разница между кранами 254 и 395? Они подключаются к одной и той же пневматической цепи вагона. Что касается множественного наследования, то оно во многих случаях прекрасно заменяется агрегированием. Электропневматический контактор — электропневматическое устройство, имеющее в себе электрическую и пневматическую части.
Согласен так и делаю пока не потребуется задать для него неисправность - а это фактически добавить пару трпойку свойств - не логичнее чтобы св-ства объекта хранились в нем самом.

Да, только в одном вагоне данное устройство может соединяться с одними устройствами, а в другом — с другими. В случае с простыми устройствами мне придется переписывать их код.
К примеру, класс Светофор может быть наследником класса Путевой объект, наследника MeshObject, впрочем, это детали.

Развитие примера: Класс Путь, Класс Путевой Объект, Класс Стрелка
Стрелка стоит на опр. линейной координате - значит Путевой объект, но она является частью Пути - Значит Путь? Опять двойное наследование?
А если потом нужно поставить Светофор на стрелку?
Я понимаю что Trainz и MSTS это реализовано - и нормально работает - но не факт что тем способом (бесконечное наследование одного от другого) о котором вы говорите. Хотя внутренностей этих игр не знаю - если есть подтверждение обратного готов выслушать.[/quote]
Ты понимаешь ООП слишком прямо, как мне кажется. Путь — протяженный объект, характеризуемый свойствами в каждой его точке, в которых могут стоять путевые объекты. Никакой другой связи между путевым объектом и самим путем нет.
А ставить светофор на стрелку и считать их полностью равноценными никак не получается с точки зрения логики — или один зависит от другого, или это два отдельных объекта, пусть и взаимодействующих друг с другом. Случай с зависимостью решается агрегированием — это или стрелка со светофором, или светофор со стрелкой.
По-моему, такая архитектура полностью вписывается в твои пункты, при этом обладая большим потенциалом по расширяемости, и решает проблему обособленности других объектов.

К примеру, я хочу сделать интеллектуальный трафик, начиная от формирования грузов на прицепных путях, заканчивая раздачей локомотивов под поезда, формируемые на сортировочных станциях по задаваемому пользователем расписанию и потребностям самих предприятий владеющих подъездными путями. Тренажер ДНЦ, к примеру. Или тот же мультиплеер.
Очень хороший пример - только доказывает проблему вашей концепции а не моей - смотрите сами - я обращаюсь через свойства, и не знаю "Класс ЭПК другого вагона" - если у того нет такого свойства к которому я обращаюсь, или он с ним не работает -то в моей структуре - как я и говорил уже несуществующее свойство создасться, работать правильно не будет и все. А в вашем случае вы просто не сможете написать Клуб который будет работать с "ЭПК программиста Пети" на другом вагоне. Т.к. Программист Петя не дал вам исходник своего ЭПК и компилятор не может осуществить контроль типов и т.д. А если вы скомпиляете со своим классом ЭПК - а подсунете класс ЭПК Пети - то здесь то и возможны проблемы вылета из игры.. Это и есть пример демонструрующий выгодность обособленности объектов. Кроме того далеко не все захотят делиться исходниками - а вот сказать какимим свойствами нужно пользоваться для правильной работы и выложить скомпиленную DLL не проблема - вы же свободно обмениваетесь "скомпиленными" моделями 3D.

Для этого есть интерфейсы, которые представляют собой формализованный и структурированный набор полей с привязанными листенерами в твоем понимании.
А программист Петя не может не дать исходник своего ЭПК, ибо формат скриптов — простой текстовый файл, в отличии от ДЛЛ.

break писал(а):И через 5 страниц выясняется что все спорили с тем же, чем сами пользуетесь.

Это лишь один из возможных способов. Другое дело, что в АГС есть методы и поудобнее.
Последний раз редактировалось agmike 11.01.2010, 00:46, всего редактировалось 2 раз(а).
The Cake is a Lie.
agmike
 
Сообщения: 1025
Зарегистрирован: 26.08.2006, 12:43
Благодарил (а): 0 раз.
Поблагодарили: 3 раз.
Играю в: Пульт ДНЦ

Re: sim

Сообщение break » 11.01.2010, 00:46

А какая цель? Сделать сим, который чуть лучше в одном, но безнадежно отстает во всем остальном?

Давай по пунктам - это интересно!
Аватара пользователя
break
 
Сообщения: 202
Зарегистрирован: 26.02.2007, 16:49
Откуда: Voronezh
Благодарил (а): 0 раз.
Поблагодарили: 9 раз.

Re: sim

Сообщение break » 11.01.2010, 00:55

Ограничение аналогичны варианту с Моно — экспорт функций игры.

ничего не понял...

Возможно я переборщил с последствиями, но при программировании ПС приятнее видеть исключение и указанием номера строки, а не вылет из игры.

Согласен.. Но это возможно при обоих подходах.

Я и хотел показать, что если программирование и есть, то оно декларативно по большей мере. Если интересует исходник, я могу прислать их все в ЛС, так как объем все же велик.

Не откажусь, обещаю 100% нераспространение а только изучение мной!
Аватара пользователя
break
 
Сообщения: 202
Зарегистрирован: 26.02.2007, 16:49
Откуда: Voronezh
Благодарил (а): 0 раз.
Поблагодарили: 9 раз.

Пред.След.

Вернуться в Другие ЖД симуляторы

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8