среда, 15 июня 2016 г.

Огонь, дым и взрывы. Новый подход к снарядам...

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

#В этом блоке прописано поведение частицы дыма до и после отсоедиенения   
    if own['tikTimer'] < own['tikPausa']-1:  
        own['propScale'] += own.parent.localLinearVelocity[1]/60
      
    else:
        own.removeParent()
        own['propScale'] += 0.1
       
    own.color = [own['propRGB'], own['propRGB'], own['propRGB'], own['propAlpha']]
    own.worldScale = [own['standartScale'], own['propScale'], own['standartScale']]
   
    #Самоликвидация после вытаивания дыма   
    if own['propAlpha'] < 0.01:
        own.endObject()
    #print(own.color)

С прозрчностью дыма, которая постепенно растет, думаю, понятно. Кроме того, я выполнил свою угрозу насчет автоматического выставления длины частицы дыма в зависимости от скорости ее генератора - об этом говорится в строке с localLinearVelocity. У меня за НУРС и УРВВ работают две разные функции. Для НАР частица одна и некоторое время она прицеплена к ракете - за это отвечают таймеры, их значение сравнивается с временем жизни факела огня - как только переходится порог, частица растет уже не бешеными темпами, а весьма неторопливо, при этом еще и растворяясь в воздухе. По достижении некоторого порога прозрачности иедт самоликвидация отживших свое объектов.
Что касаемо долгоживущих УР, то там частица при появлении сразу приобретает величину скорости носителя, но к нему не прицепляется и ведет себя подобно вышеописанной. Только частиц гораздо больше (но пока на ФПС особо не влияет).
Разумеется, в реале дым тает не столь быстро, но БГЕ все же не настолько силен, чтобы угнаться за большим количеством объектов...
Была решена проблема пуска НАР из блоков. Все упиралось в то, что стартуют они из ячеек и координаты старта ракет не совпадают. В серии SF, из-за которой я и затеял весь этот долгострой, не стали заморачиваться - там НУРСЫ вылетают строго из центра блока. Но мы, русские, простых путей не ищем, нам подавай сложную проблему (которую мы себе же зачастую и сами придумали), чтобы героически ее решить...  Снова кусочек кода.
Строка проперти coordList для Б-8:
 -0.09,0.0,-0.07B0.09,0.0,-0.07B-0.11,0.0,0.03B0.11,0.0,0.03B-0.05,0.0,0.1B0.05,0.0,0.1B
Сие означает набор координат снарядов от 1 и до 20-го, который разделяется маркером  - буквой В (лат). Строчка гораздо длиннее и не самая страшная. Куда более жутко выглядит строка для УБ-32 с его 32 ракетами.
А теперь код извлечения цифр на свет божий:
if 's5' in obj.get('tipSbros'):
                            ownSelf['zalpSbros'] = 1
                            if obj['childBK'] > 0:
                                obj['timerTik'] += 1
                                if obj['timerTik'] == 10:
                                    #Стрельба ведется очередями, отсчет пауз идет через проперти timerMass
                                    #Сам снаряд
                                    dynObj = scene.addObject('dynObj',obj,2500)
                                    dynObj.setParent(obj, False, False)
                                    for i in obj.getPropertyNames():
                                        if i not in dynObj.getPropertyNames():
                                            dynObj[i] = obj[i]
                                        else:
                                            dynObj[i] = obj[i]
                                    #Дымная трасса
                                    smokeLong = scene.addObject('ParticlePlane',dynObj)
                                    smokeLong.setParent(dynObj,False,False)
                                    smokeLong['tikPausa'] = 75
                                    smokeLong['particleType'] = 'SmokeLong'
                                    smokeLong['propAlpha'] = 0.1
                                    smokeLong['propRGB'] = 0.95
                                    smokeLong['standartScale'] = 0.5
                                    #Трассер снаряда
                                    trasser = scene.addObject('UniversalMesh',dynObj,75)
                                    trasser.setParent(dynObj, False, False)
                                    trasser.replaceMesh('FireMissile',True,False)
                                    trasser.visible = 1
                                    trasser.worldScale = [obj['scaleFire'],obj['scaleFire'],obj['scaleFire']]
                                    #Вспышка - лампа
                                    vspyshka = scene.addObject('LampUniversal',trasser,75)
                                    vspyshka.setParent(trasser, False, False)
                                    #Звук снаряда
                                    audioEmitter = scene.addObject('AudioEmitter',dynObj,75)
                                    audioEmitter.setParent(dynObj, False, False)
                                    audioEmitter['audioProp'] = 'Missile'
                                    #Огонь из сопла блока НАР
                                    backFire = scene.addObject('UniversalMesh',obj,6)
                                    backFire.setParent(obj, False, False)
                                    backFire.replaceMesh('FireMissile',True,False)
                                    backFire.worldScale = [obj['scaleBackFire'],obj['scaleBackFire']/2,obj['scaleBackFire']]
                                    backFire.visible = 1
                                    #Вспышка пламени из сопла блока
                                    vspyshkaBack = scene.addObject('LampUniversal',backFire)
                                    vspyshkaBack.setParent(backFire, False, False)
                                    vspyshkaBack.localPosition[1] = -0.75
                                    #Отцепляем снаряд от блока и придаем ему начальную скорость и координаты (длинно, но ничего не поделаешь)
                                    dynObjX = float(obj['coordList'].split('B')[obj['childBK']-1].split(',')[0])
                                    dynObjY = float(obj['coordList'].split('B')[obj['childBK']-1].split(',')[1])
                                    dynObjZ = float(obj['coordList'].split('B')[obj['childBK']-1].split(',')[2])
                                    dynObj.localPosition = [dynObjX,dynObjY,dynObjZ]
                                    dynObj['engineWeapon'] = 'Ballistic'
                                    dynObj.removeParent()
                                    dynObj.localLinearVelocity = [random.randrange(-5,5),obj['speedBullet']+random.randrange(-20,20)+ownSelf.localLinearVelocity[1],random.randrange(-5,5)]      
                                    obj['childBK'] -= 1
                                    obj['timerTik'] = 0

Где dynObjX-Y-Z - и есть требуемое. в самом же коде прописано много чего. Например вспышка факела ракеты, вспышка факела из блока НАР, звук стартующей ракеты, и еще много чего. При авпуска всего арсенала  одной очередью из блока незначительно повышается уровень используемой логики, но ФПС не падает. Ну, во-первых, в код еще много можно чего подчистить, к примеру сделать факел из блока постоянным и его включать по мере необходимости. С копированием проперти я пока еще не возился досконально - там можно копировать не все. Во-вторых, снаряду еще надо прописать бронебойное, зажигательное, кумулятивное и фугасное действие. Эта работа еще впереди, тем более, что блоки можно снаряжать разными типами снарядов. Тут уже придется дописывать комплектацию блоков в файлах инициализации юнитов и оружия - это еще одно объяснение тому, почему я зациклился на МиГ-23. у него довольно широкий набор вооружения и можно отработать применение всех разновидностей оружия.
Мне был нужен более-менее реалистичный старт ракет из блоков и я его получил. Помимо всего мною, наконец, были введены в строй блоки УБ-32. Существует довольно много разновидностей блоков НАР для С-8 и С-5, но у всех у них одинаковый набор координат. Есть еще УБ-16, есть тяжелые пятизарядные блоки для С-13, есть еще иностранные блоки, о которых мне пока мало известно (в смысле размеров). Доберусь и до них как-нибудь.
в отличие от возни с НУРСами, доводка дыма для УР прошла как-то буднично и быстро. Зато я надолго застрял с разрывами от НАР и пушечных снарядов. Причина оказалась банальная - малое время жизни. Дым и огонь смотрелись красиво, но взрывов не было...
Но и эта проблема была решена. В отличие от первой версии, где каждый кадр взрыва вызывался отдельным объектом, во второй версии картинка взрыва показывается путем смены меша взрыва. Причем смена мешей происходит по принципу - "тип взрыва+кадр", который образует название меша, нужного в данный момент. снова кусочек кода:
        try:
            own['kadr'] += 1
            meshName = own['tipSprite'] + str(own['kadr'])
            own.replaceMesh(meshName, True, False)
        except:
            own.endObject()
Функция получилась совсем простенькая. Что касаемо взрывов, то у меня произошла некая "градация". Взрывы от УР, обычных бом или взрыв юнита - довольно большие по времени и количеству кадров. Взрывы от НАР - относительно короткие - 49 кадров вместо 256, а разрывы пушечных снарядов малого калибра -так и вообще 16 кадров. Что позволяет держать ФПС под контролем. За все это отвечает универсальный спрайт, на котором и меняются меши. Величина взрывов прописана в свойстве снаряда, так что здесь тоже все в порядке - взрыв полутонной фугаски куда как более впечатляющий, чем взрыв бомбы-"сотки" (кстати на одном из форумов бывший летчик ИБА назвал ФАБ-100 "мерзкой тварью" - несмотря на небольшой вес ВВ внутри, подброс осколков у нее достигал 99 с линим метров в высоту, и кидать ее следовало не абы как, можно было и самому пострадать).
В заключение - скрины.
 Первый и не вполне удачный тест с дымом - пришлось увеличить исходную прозрачность...
 МиГ-23БН - огонь из ГШ-23Л.
 МиГ-23БН - залп из УБ-32 НУРСами С-5.
 МиГ-23БН - бомбометание - ОФАБ-250 с хвостовых балок.
Как выглядит из кабины взрыв НАРа. Удавалось и сплошную дорожку из огня и взрывов создавать...

Комментариев нет:

Отправить комментарий