воскресенье, 31 июля 2016 г.

Переворот 12 Термидора. Великая Анимационная КОНТРРеволюция.

В названии этого поста скрывается грустная шутка. В свое время я писал посл "Вкликая Анимационная Революция", в котором подробно описал способ массового проигрывания анимации у объектов-потомков в БГЕ. К сожалению, иногда разработчики Блендера делают ляпы, из-за которых стройная и уже отлаженная система дает сбой. Тем более обидно, когда этот сбой проявляется в новой версии, вынуждая откатываться на старую и лишая тем самым новых плюшек. Так и получилось с версией 2.77. Проигрывание анимации при помощи скрипта там возможно лишь при 2прерывистом" состоянии сенсора - пульсация там должна быть равна 1, как минимум. Постоянно проигрываться анимация не в состоянии - происходит "рваный" переход от начального кадра к конечному по истечении некоторого времени. И если для работы приборов этого вполне хватит, то вод для проигрывания анимаций механики - никакне подходит (и какого художника я перешел со старой доброй ХР на "семерку", сидел бы себе на 2.75 и Виндовс ХР?!).
В свое время denis8424 как-то подначивал меня, задавая вопрос насчет того, когда же я буду просто вращать детали самолетов, не используя анимацию? Тогда я отбрехался сложной траекторией движения и всем таким. Однако жить захочешь - не так раскорячишься. Поэтому решение все же было найдено. Окончательно оно оформилось сегодня, после успешного добавления и отработки функции шасси. По республикансокму календарю сегодня 12 Термидора, получается прямо Термидорианский переворот ("Я тебя породил, я тебя и убью!"(С)). Для начала я принялся "искривлять" или, точнее, "перекашивать" детали самолета. Дело в том, что тормозные щитки, к примеру, расположены на том же Миг-23 не прямо, а под некоторым углом, то же касается деталей крыла. Поэтому я брал деталь, крутил ее, так чтобы передняя кромка становилась "прямой" и потом уже жал Ctrl+A и - Rotation, затем "доворачивал", чтобы деталь укладывалась обратно на место, но ее стартовый угол был уже ненулевым. Таким образом я получил возможность крутить деталь только по одной оси, а не по трем, как в анимации. Далее требовалось понять, как все это безобразие отклонить на нужный угол... Отклонить на нужный угол можно путем отсчета проперти, которое "гуляет" в строго отведенном ему промежутке от минимума до максимума. А ишшо нужна переменная, которая отслеживает, куда проперти идет - вправо или влево. Решалось это путем создания уже привычного словаря свойств и сравнения текущего значенияпроперти со словарным. И когда нужно - эти значения выравнивались. Сама команда н6а поворот детали осуществляется строчкой типа  obj.applyRotation([три цифрычереззапятую],True). Теперь предстояло понять, как эти трицифрычереззапятую выдавать. В Блендере поворот дается в радианах, что несколько неудобно, но справиться с этим можно. Я выбрал основной величиной полградуса. Градус при переводе в радианы давал 0.0174444444444444, я это число укоротил до первой четверки, полградуса выдается 0.087. И вот тогда началось самое интересное. Для наглядности приведу кусочек кода для тормозных щитков.
Команда для тормоза:
if keyboard.events[bge.events.AKEY] == JUST_ACTIVATED:
           
                if self['localDict']['AIRBRAKE'] == self['AIRBRAKE']:
                    self['AIRBRAKE'] += 1
Как видим, клавиша все  время дает прирост проперти на 1. Чтобы не возиться, потому как у разных самолетов времени анимации тормоза может отличаться. А вот как выглядит исполнение "поворотом":
#Псевдоанимации тормозных щитков               
def airbrake():
    cont = bge.logic.getCurrentController()
    own = cont.owner
   
    #Направоение перекладки крыла
    airbrakes = 0
   
    #Ограничения по максимальному и минимальному значению проперти
    if own['AIRBRAKE'] > 100:
        own['AIRBRAKE'] = 99
    elif own['AIRBRAKE'] < 0:
        own['AIRBRAKE'] = 0
   
    #Выставление напрaвления перекладки и убывания-возрастания проперти
    if own['localDict']['AIRBRAKE'] < own['AIRBRAKE']:
        airbrakes = 1
        own['AIRBRAKE'] += 1
    elif own['localDict']['AIRBRAKE'] > own['AIRBRAKE']:
        airbrakes = -1
        own['AIRBRAKE'] -= 1
   
    if own['levelsDetails'] == 0:       
        #Собственно, движение тормозных щитков
        if 0 < own['AIRBRAKE'] < 90:
            own.childrenRecursive['ArbUL_'].applyRotation([-0.0087*airbrakes,0.0,0.0],True)
            own.childrenRecursive['ArbUR_'].applyRotation([-0.0087*airbrakes,0.0,0.0],True)
        if 0 < own['AIRBRAKE'] < 80:
            own.childrenRecursive['ArbDL_'].applyRotation([0.0087*airbrakes,0.0,0.0],True)
            own.childrenRecursive['ArbDR_'].applyRotation([0.0087*airbrakes,0.0,0.0],True)
           
    #Остановка псевдоанимации на кадрах со значением 0,100  
    if own['AIRBRAKE'] in [0,100]:
        own['localDict']['AIRBRAKE'] = own['AIRBRAKE']
       
Прикол тут в том, что в начале функции выставлены ограничители - которые "отбрасывают" проперти в рамки от 0 до ста. Внутри этого промежутка проперти НЕ ОСТАНАВЛИВАЕТСЯ, пока не упрется в границу. как видно из кода, переменная airbrake имеет значения 1 (выпуск тормоза) или -1(уборка тормоза). Оно-то и загнано в строчку applyRotation вместе с величиной разового поворота.
Таким же образом теперь работают практически все детали, кроме основных стоек шасси и гидравлики при этих самых стойках. Хотя с течением времени можно заменить и их. Плохо то, что их - 16 штук на МиГ-23/27, но это меркнет на фоне F-5. Там вообще кошмар. Поэтому я принял решение пока сохранить анимации для такой мелочи, но постепенно по возможности отказаться и от нее.
И пока еще есть нерешенная проблема - со стабилизаторами. Кроме флаперонов, этот вид деталей имеет двойное назначение - они работают синхронно при тангаже и ножницами при крене. Примерно как это решить, я знаю, попробую в ближайшее время с этим справиться...
Помимо войны с анимацией занимался поиском решений по генерации юнитов. Тут впечатления двойственные. С одной стороны кое-как освоил загрузку через json файлы для стартовых установок проперти (которых на двиагтеле почти не осталось - только два таймера). с другой  - хотелось бы иметь к примеру юнит-модель типа МиГ-29 и в папке с ним набор материалов с текстурами разных стран - при генерации присвоить модели нужный материал и вперед. увы. dron, который с некоторых пор натаскивает меня по некоторым аспектам программирования (надо признать, что ученик ему попался туповатый, увы и ах), долго бился над этой проблемой, нашел много чего интересного в бленд-файлах попутно, найти оптимального решения не смог, все это дело можно решить через код на Си плюс, но это уже придется забираться в основы самого кода Блендера. в общем, пока со сменой материалов дело не пойдет. Блендер, как объяснил мне Андрей, не может импортировать независимые от материалов меши (во всяком случае я так понял). Жаль, но отрицательный результат - тоже результат. Попутно dron написал класс для проигрывания звука, к которму я так, к стыду своему по-настоящему еще не подступался - все анимации, блин (хотя гильотина там поработала уже, да (черный юмор)).
В общем пока идет переформатирование уже имеющегося. JSON файлы гораздо лучше читаются и понимаются (в том числе и их создателем, который спустя некоторое время смотрит на свой текстовый файл с палочками и мучительно пытается вспомнить, что означает вот эта четвертая слева цифра). На JSON, скорее всего перейдет вся или почти вся стартовая генерация объектов.
Сама модель создания юнита также претерпела резкие изменения. Замена мешей резкао сократилась. Теперь смена уровней детализации идет путем добавления -удаления родителей с потомками. В принципе, все так и осталось - ведь ранее у меня импортировалась система-скелет для замены мешей, но там тоже были свои группы объектов и они также добавлялись-удалялись. После исчезновения почти всей анимации (шасс в расчет особо можно не брать - оно используется за игру пару раз, а чаще - так и вовсе не используется).отпал смысл в импорте скелета (я не хотед набирать в игровой файл большое количество абсолютно одинаковых анимаций). В общем, новая система ЛОДов - компромисс между продвинутой системой замены мешей, о которой я тут распространялся и системой из первой версии, в которой замены мешей не было. Опять таки цитата:"На всякое придыхательное пыльношлемие мы ответим самым суровым булкохрустом" - разумный консерватизм вполне оправдан. А революции часто или почти всегда заканчиваются контрревоюциями...
Ну вот, хоть одна запись в юле все-таки появилась.