понедельник, 27 июня 2016 г.

И снова о сенсорах...

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

01_120_60_1.2_1_15 - так выглядит запись в текстовом файле для БРЛС истребителя МиГ-23МЛАЭ2. Для ее расшифровки сначала приведу список проперти юнита - в данном случае - летательного аппарата.
target - "краные" (0) или "синие" (1)
targetScan - тип сканирования - "земля" (1) или "воздух" (0)
sensBRLS - проперти бортовой РЛС (как раз первая строчка из цифр).
sensTP - проперти теплопеленгатора
sensLD - проперти лазерного дальномера
sensTV - проперти телевизионного прицела

А теперь расшифруем символы в трочке, перемежаемые подчеркиваниями.

01 - способность к отслеживанию целей, в данном случае - как воздушных, так и наземных (может быть так, что сенсор приспособлен исключительно для работы по земле или небу - 1 или 0 соответственно).

120 -  дальность действия - 120 км.

60 - угол обзора - в данном случае - 60 градусов

1.2 - пауза между сканирующими импульсами, иначе БГЕ может зависнуть. Величина идет скорее "на глазок, меньше секунды точно не будет.

1 - количество подсвечиваемых целей - означает возможность обстреливать одну или несколько целей сразу ракетами с РЛ ГСН (например МиГ-31 и F-14 долгое время в мире были единственными, способными на такое).

15 - это "мертвая зона"  радара. во многом эта величина взята от балды и нуждается в дополнительной проработке. Пока что мертвая зона вычисляется таким образом - сначала берется высота самого перехватчика, делится на то число и полученный результат сравнивается с текущей высотой цели над данным участком местности (не высотой над нулевой отметкой!!!). Но, скорее всего, придется внести коррективы - не абсолютная высота перехватчика, а относительная, как и у цели. Ну, здесь можно сильно поизвращаться... Главное, чтоб движок выдержал.

Вообще-то "мертвая" зона вводится именно для радара, причем только в режиме прицеливания "воздух". Для ракет же существует своя мертвая зона - по абсолютной максимальной высоте и текущей минимальной высоте над землей. К примеру, старые ракеты типа Р-98 на высоте меньше 2 км уже теряли цель в любом случае, что на фоне земли, что на фоне неба - достаточно было атакуемому "нырнуть" пониже к земле (но в данном случае это было не слишком опасно, от Р-24 увернуться было уже проблематично - требовалось опуститься на высоту ниже 25 метров).
Сейчас идет подгонка формата файлов под новые обстоятельства. Учитывая, что я не слишком сильно заморачивался этим в свое время не успел наплодить кучу юнитов, процесс переделки(доработки) будет не таким сложным, как казалось...

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

Сенсоры. Боты не должны видеть тебя все время, ибо это нечестно...

Давным-давно как-то раз я просматривал форум, посвященный знаменитой серии "Ил-2" (благодаря которой на Западе таки выучили слово "штурмовик", поняв, что "стормовик" - это неправильно). И был там вопрос по поводу "зрения" ботов. Вопрошающий, получив ответ: "Боты видят тебя всегда", возопил: "Но так нечестно!!!". Вот и я тоже считаю, что нечестно. Разумеется, "мне сверху видно все, ты так и знай" (С), но все же очень не хотелось бы, чтобы бот сумел бы разглядеть тебя, крадущегося, где-нибудь по ущелью прямо сквозь горный хребет... К тому же есть такая штука, как помехи , создаваемые подстилающей поверхностью, которые причиняли на заре развития БРЭО (да и потом) разработчикам этого самого БРЭА и летчикам немало хлопот. Известно, например, что БРЛС "Фантомов" довольно плохо видит цели на фоне земли и неспособна произвести захват и сопровождение цели. Поджобные недостатки имеют и БРЛС МиГ-21, ранних МиГ-23, и в какой-то степени МиГ-25 и F-14(как ни странно). Во время ирано-иракской войны иракцы изрядно проредили парк "Фантомов" ВВС Ирана, применяя тактику засад и приманок. Обычно пара МиГ-23МС или МиГ-23БН начинала либо бомбить и обстреливать позиции наземных войск иранцев, либо демонстративно обращалась в бегство, провоцируя F-4 на погоню. Но убегали иракцы не абы куда, а в заранее оговоренный район, в котором на малых высотах нарезали круги и восьмерки МиГ-25 или Mirage F.1. Их летчики, получив соответствующую информацию с земли или от своих товарищей, работавших в качестве "приманки", шли навстречу  "Фантомам" на предельно малой высоте, РЛС иранцев их не видели. Проскочив под оппонентами, перхватчики выполняли полупетлю с полупереворотом и оказывались на хвосте у "Фантомов". Как правило, когда иранцы понимали, что из охотников они сами превратились в жертву, предпринимать что-либо было уже поздно. За довольно короткое время иранцы недосчитались примерно десятка F-4/Любопытно, что против "Тайгеров" F-5 подобная тактика почти не работала - у них просто не хватало скорости, чтобы хотя бы не отстать от МиГов. Похоже, при схожих же обстоятельствах иранцы потеряли и два "Томкэта" от МиГ-23МЛАЭ-2 (экспортный вариант МЛД, поставлявшийся в Ирак, без "клыков" у неподвижной части крыла) -  во всяком случае, на сайте Тома Купера указывается, что один из F-14 был сбит ракетой Р-60 (учитывая ее очень небольшой радиус действия и высокие летные характеристики  "Томкэта", рискну предположить, что МиГ-23 достал своего противника неожиданно и с задней полусферы, БРЛС "Томкэта" видит очень далеко, но на фоне земли цели различает плоховато).
Ну да ладно, вернемся к проекту, а точнее, к созданию скрипта-сенсора. Когда-то denis8424 создал пару примеров радара с использованием Питона. Я же, всячески модифицируя, дополняя и подгоняя под свои требования скрипт, получил в итоге пару скриптов-монстров, которые, тем не менее, все-таки работали и вокруг них во многом игра и строилась.
Теперь же задачка стояла создать на основе того же скрипта радара более совершенный скрипт-сенсор. Дабы отделить одно от другого, чтобы потом не морщить лоб в попытках вспомнить, что же я имел в виду этой строчкой, я решил в модуле-сенсоре сделать несколько функций, которые будут отвечать за разные способы навигации, прицеливания и ориентирования.
Было сделано ника не меньше дюжины попыток, которые заканчивались иногда более-менее приемлемыми результатами, но, поскольку я толком сам не понимал, чего хотел, изыскания пришлось продолжить. в конце концов я пришел к следующей схеме - вначале идет так называемый сканирующий импульс, который в списке оппонентов отсекает всех, кто не укладывается в конус радара или скрыт за препятствием. А уже затем идет "сопровождающий" импульс, который будет повторяться до тех пор, пока цель не будет сменена, сорвет завхват или будет уничтожена. Была сперва мысль сделать для каждого типа сенсора свою функцию, но пока я от этого отказался (хотя и не окончательно). Сейчас у меня идет работа над отладкой двух типов сенсоров - радара и "взгляда летчика". Но сначала я отладил принцип сортировки юнитов в игре. Занимается этим объект с говорящим названием "Arbitr". скрипт его работы привожу чуть ниже, думаю, все понятно:

 import bge
cont = bge.logic.getCurrentController()
own = cont.owner
scene = bge.logic.getCurrentScene()
sens = cont.sensors[0]
    
#Главный список всех задействованных юнитов
listUnit = [[[],[]],[[],[]]]
bge.logic.globalDict['listUnit'] = listUnit
  
#Запись индексов объектов-юнитов в подсписки и общий список
if sens.positive:
    for obj in scene.objects:
          
        if 'target' in obj:
            #Если в имени присутствует 'Air'  - то это - летательный аппарат
            if 'Air' in obj.name:
                if obj.get('target') == 0:
                    listUnit[0][1].append(obj)
                elif obj.get('target') == 1:
                    listUnit[0][0].append(obj)
            #Если в имени присутствует 'Ground'  - то это наземный объект
            elif 'Ground' in obj.name:
                if obj.get('target') == 0:
                    listUnit[1][1].append(obj)
                elif obj.get('target') == 1:
                    listUnit[1][0].append(obj)
    #print(bge.logic.globalDict['listUnit'])

Сортировка идет по части названия объектов - чуть быстрее, как мне кажется, нежели чем искать какое-то проперти в свойствах объектов.
А далее мы имеем на ботах и своем юните проперти targetScan - которое отвечает за просмотр списка наземных (1) или воздушных (0) целей. Анаоргично 0 или 1 работает свойство target, которое, собственно, обозначаете сторону - условно - 0 - "красные", 1 - "синие". Я не стал во второй версии умножать сущности и вводить еще два значения проперти target, для наземки. И так сработает.
На данный момент скрипт радара выглядит так:
import bge
import mathutils

#Сенсор обнаружения и сопровождения цели
def unitSensor():
    cont = bge.logic.getCurrentController()
    own = cont.owner
    scene = bge.logic.getCurrentScene()
    sens = cont.sensors[0]
   
    print(own['PR'])
   
    #Создаем словарь свойств
    if 'unitSensor' not in own:
        own['unitSensor'] = {}
        own['unitSensor']['idTarget'] = own['idTarget'] #Индекс текущей цели
   
   
    if sens.positive:
       
       
        if own['idTarget'] == '' or own['unitSensor']['idTarget'] != own['idTarget']:
            def inConeOfRadar(own, target):
               axisVect = mathutils.Vector((0.0, 1.0, 0.0))
               targetData = own.getVectTo(target)
               targetVect = targetData[2]
               dist = targetData[0]
               angle = own['radarAngle']
               if angle > axisVect.angle(targetVect, None): 
                   rayOwnTarget = own.rayCastTo(target, dist, 'objScene')
                   if rayOwnTarget == None: 
                       #Если тип сканирования - воздушные цели, то дополнительно проверяем еще и "мертвую зону" радара
                       if own['targetScan'] == 0:
                           #Некоторые радары плохо видят цель на фоне земли, поэтому не способны засекать низколетящие цели
                           #Высота "мертвой зоны радара" - по высоте цели над землей
                           deadZoneRadar = own.worldPosition[2]/own['antiEarth']
                           #Введение поправки на мертвую зону
                           targetDeadZone = [target.worldPosition[0], target.worldPosition[1], target.worldPosition[2] - deadZoneRadar]
                           targetPosition = target.worldPosition
           
                           #Мертвая зона радара
                           hitEarth = target.rayCast(targetPosition ,targetDeadZone, deadZoneRadar, 'objScene', 0)               
                           if hitEarth == (None, None, None):
                               return True
                   
                       #В противном случае для наземных объектов такой проверки не требуется
                       else:
                           return True
                   
                   
               else:
                   return False
               return False      
                               
            def aiming():
                cont = bge.logic.getCurrentController()
                scene = bge.logic.getCurrentScene()
                own = cont.owner
   
                ownTargetList = []
                sceneObjList = bge.logic.globalDict['listUnit'][own['targetScan']][own['target']]
                       
                if len(sceneObjList) > 0:
               
                    for target in sceneObjList:
                           
                        if own['distRadarMax']*target['stealth'] > own.getDistanceTo(target):
                            if inConeOfRadar(own, target):
                                ownTargetList.append(target)
                                if len(ownTargetList) - 1 == own['enemy']:
                                    own['idTarget'] = str(id(target))
                    #print(own, ownTargetList, own['idTarget'])
                               
            aiming()
            own['unitSensor']['idTarget'] = own['idTarget']
           
            #
            if own['unitSensor']['idTarget'] == own['idTarget']:
               
               
               
               
                #print(own, own['idTarget'])
                try:
                    ob = scene.objects.from_id(int(own['idTarget']))

                    #if inConeOfRadar(own, target):                                    #Это - условие НАВЕДЕНИЯ на цель
                    vect = own.getVectTo(ob)[1]
                    own.alignAxisToVect(vect, 1, 0.5)
                   
                    vectX = own.getVectTo(ob)[2][0]
                    vectY = own.getVectTo(ob)[2][1]
                    vectZ = own.getVectTo(ob)[2][2]
                   
                    if abs(vectX) < 0.2 and abs(vectZ) < 0.2:
                        own['PR'] = 1
                    else:
                        own['PR'] = 0
                       
                except:
                    pass

Текст будет еще многократно меняться, в него будут внесены поправки  на использование средств РЭБ. Кроме того, отдельно будудт функции баллистического прицела и "взгляда летчика". Впрочем, последняя, уже создана и в ней большую роль играет проперти maxVisibleDist - у "просматриваемых" объектов - максимальная дистанция видимости. Дело в том, что здоровенную тушу Б-52 видно гораздо дальше, чем, скажем маленький Миг-21, поэтому и надо вносить коррекцию на размеры для ботов.
Отдельный вопрос - функции наведения для УР и всевозможныъ КАБов - там необходимо прописать скорость реакции на маневр цели, нужность-ненужность подсветки, условия прекращения наведения, снижение энергии при полете или маневре, реакцию на РЭБ, облака, дым, да много чего. Похоже, все это будет отлаживаться, как и в пераой версии - постепенно - шаг за шагом...

среда, 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 с хвостовых балок.
Как выглядит из кабины взрыв НАРа. Удавалось и сплошную дорожку из огня и взрывов создавать...

пятница, 10 июня 2016 г.

Явно верной дорогой идем, товарищи...

Есть какая-то мистическая взаимосвязь между успешным кодингом и отключением света в моем доме... уже давно заметил, чт стоит создать солидный кусочек нового кода и приготовить солидный задел на будущее, как наши доблестные энергетики гасят свет. Причем надолго. Бывает это нечасто, но совпадения с успешным продвижением  по проекту настораживают)))... Как это было вчера. После некоторой возни я отладил пуски НАР, одиночные пуски ракет типа "воздух-воздух" и приготовился реализовать пушечный огонь, как последовало отключение (давненько такого не было, чтобы на 8 часов). В иоге вчерашний день был потерян.
Сегодня опять занялся оружием и сделал огонь из пушки. А к аркетам присобачил факел огня. Ничего особо сложного там не оказалось, разве что отработал вызов функций из другого скрипта - примитивно, но работает. В начале работающего скрипта пику - import moduleclass
А потом в нужном месте - moduleclass.blablabla(). То есть пишу, какую функцию надобно использовать из загруженного модуля moduleclass. Как всегда, нужные мысли не всегда приходят в нужное время. Что мешало в первой версии  таким образом разбить на функции хотя бы тот же искусственный интеллект ботов и спокойно вызывать нужную функцию в зависимости от ситуации? Но лучше поздно, чем никогда... Пока у меня таким образом работают функции сброса и пуска, плюс функции смены оружия, я сейчас пока стараюсь побыстрее создать "скелет" игры, создавая код в меру своего умения и сопровождая его подробным комментарием, чтобы потом при совершенствовании не вспоминать, чего я там нагородил. ну и стараюсь, чтобы объем поменьше был у пускового файла.  Относительно недавно один пользователь БУ, с которым я списался в ВК, любезно продемонстрировал мне, как можно мыслить абстракциями и что из этого можно извлечь. С помощью Питона. Результат впечатляющий, и, после завершения работы над основной частью кода, я, скорее всго, начну пробовать 2мыслить абстрактно", что должно привести к резкому сокращению кода и должно повысить скорость. К тому же он меня предупредил, что реализованный в БГЕ ныне метод мутации объекта (после создания класса) не совсем оптимален и может вызвать утечку памяти при определенных условиях.  Если честно, я пока в мутации разбираюсь слабо, но это дело придется поправлять.
Пока что на данный момент имеем пуски неуправляемых ракет, сбросы бомб, и пуски пока еще болванок, которые должны стать управляемыми ракетами. Плюс пушка. Из крайне неоходимых операций добавления объектов мне осталось реализовать алгоритм отстрела тепловых ловушек, а также дымные следы. Есть предположение, что можн7о будет добавить дымные шлейфы и к НАРам, от которых я был вынужден в первой версии отказаться. Есть у меня анимированная текстура длинного дыма, которую я и использую. Частица дыма для НАР будет одна- ее длина будет расти сообразно скорости ракеты,а потом частица будет 2отцепляться" от ракеты с исчезновением факела огня и быстро таять... Таким образом, БГЕ не должен сильн перегружаться при массовых пусках ракет. Что касаемо УР большой дальности, то для них дымный след останется тем же, но в алгоритм добавления частиц дыма будет добавлено выставление длины частицы сообразно скорости ракеты. Также это правило будет действовать и для отстреливаемых ложных целей 9ловушек). В первой версии неестественность дыма бросалась в глаза на малых скоростях самолета. К тому же УР будут набирать скорость слежения за целью плавно, а не рывком, как в первой версии - из-за этого "ломаность" линии дыма также бросалась в глаза.
После завершения работы над отстрелом ловушек и дфмами можно будет приступать к возвращению и совершенствованию самонаведения для ракет, а потом очередь дойдет и до бронепробиваемости под разными углами для разных типов снарядов... Работы много еще. а вот после завершения "скелета" игры и отработки взаимодействия объектов уже можно клепать модели и разнообразить технофауну. В первой версии примерно так и было, с той лишь разницей, что новые объекты там добавлялись с большим скрипом. Надеюсь, в этот раз такого безобразия не будет.
А теперь - красивые картинки (ну как красивые, довольно приешиеся, поди уже, с пустнным пейзажем и МиГ-23)...

 Пуск Р-23Р

 Пушечный огонь






 Залп НАРами
 Сброс бомб

понедельник, 30 мая 2016 г.

Поход за консенсусом.

Только что удалось отработать генерацию юнитов на сцене путем чтения файла миссии. Во многом вторая версия своим появлением обязана крайне неудачно выбранному способу создания миссии в первой. Как таковая, миссия создавалась в виде отдельной функции со своим уникальным названием и при старте БГЕ приходилось открывать модуль миссий, а затем построчно читать данные для каждого юнита, генеря их, расставляя и раздавая им потомков и нужные проперти.
Во второй версии все это достигается чтением текстового файла в папке Scenery. Разумеется, от генерации, расстановки и прочего для юнитов не обойтись, но данные теперь не повисают в памяти, к тому же становится на порядок легче добавлять новые миссии и кампании. Пока правда, есть одна загвоздка. Необходимо в меню при щелчках по кнопкам, собирать данные в некую структуру и затем полдученную строчку загонять в файл. Задача решаемая, только несколько занудная - необходимо четко соблюсти порядок записи новых данных, отвечающий вырабатываемым стандартам. Так что если угодно, нужен консенсус (согласие) между меню и игровой сценой. Чем и занимаюсь - сближением позиций заинтересованных сторон, так сказать...
А пока пришло время для красивой картинки - тест на чтение текстового файла (точнее файлов, ибо теперь все проперти и потомки с скоординатами и ориентацией раздаются юнитам сразу после появления, что позволило выбросить лишнюю функцию и убрать лишний объект-потомок, который эту функцию и исполнял). Вместо полусотни сточек кода на эти четыре объекта были потрачены 4 строчки в текстовом файле, плюс некоторое количество строчек для его открытия, чтения и закрытия. В любом случае, дело это окупится.
На скотне ниже - звено ливийских МиГ-23МФ с единообразными подвесками - три ПТБ плюс по паре Р-23Р и Р-60.

суббота, 28 мая 2016 г.

Меню. Ощупью в полдень...

Теоретически создание меню вроде как вещь несложная.Небольшой опыт у меня худо-бедно имелся. Даже для создания меню выбора типа оружия когда-то добрался. Потом, правда все прикрыл, планируя заняться в конце создания первой версии. в итоге работу над первой версией остановил за ее бессмысленностью, и занялся относительно недавно тем же самым во второй версии.
В первую очередь занялся меню редактора миссии, как наиболее сложной частью меню. при создании миссии необходимо:
1. Создать коалиции
2. Выбрать юнит коалиции
3. Выдать юниту оружие (причем учесть все точки подвески).
4. Указать количество юнитов данного типа в группе
5. Цувзвть координаты группы на террайне
6. указать маршрут группы по точкам
7. Указать тип миссии юнитов группы (перехват, патруль, эскорт, БШУ, РБУ, разведка)
8. Собрать все данные в кучу в строго определенном порядке
9. Загнать весь список в большой мега-список миссии.
10. Выбрать следующий юнит и повторить вышеперечисленные пункты.
11. По окончании формирования сценария миссии записать мега-список в текстовый файл.

пока работа подошла к фазе выбора оружия. В моем меню сначала появляется набор флажков участвующих в данной миссии стран (потенциально участвующих). При нажатии на иконку флажка она помечается белой рамкой. Далее, нажав синюю или красную кнопку, отправляем флажок в нужный нам "лагерь" коалиции. По окончании формирования коалиции можно отменить результат или подтвердить, для этого есть кнопки с надписями рядом - Back (Назад) или Аccept(Принять).
После подтверждения появляется меню выбора юнитов и оружия для них. Названия юнитов формируются в виде столбца кнопок с иконками выбранной страны и текстом, цвет которого соотетствует "цвету стороны". При нажатии кнопки юнита появляется надпись Weapons(справа) и под ней кнопки выбора пар подвесок. Для МиГ-23МЛАЭ2 ВВС Лвии, к примеру, точек подвески три (считая нулевую - для подвесных топливных баков), но само оружие размещается на двух парах точек подвески. На скрине как раз показан набор оружия для подкрыльевых пилонов (пара точек подвески за номером 1).
Необходимо как-то отмечать выбранные (нажатые) кнопки юнитов и оружия (можно это сделать изменением цвета, но, скорее всего, это будет белая черта-подчеркивание - на мой взгляд - четче видно).
Пока чтог пишется скрипт управления меню, по мере 2отшлифовки" и вылавливания ошибок в него добавляются все новые и новые блоки генерации и расстановки кнопок, пишутся комментарии и пояснения, зачем все это нужно.. Помимо генерации самих кнопок их еще надо и расставить -так что там еще приходится учитывать координаты кнопок меню, чтобы они не "наезжали" друг на друга и на линии меню. Как обычно, скрины. Немного скучные - я не уделял пока оформлению меню много внимания, да и вообще, по идее, меню надо делать после окончания работы над самой игрой (так я думал раньше), но во второй версии слишком много завязано на меню, поэтому, сделав какой-то минимум в игровом процессе, пришлось браться за кногпки и надписи...
P.S. Пока в меню выбора сторон только два флага - Ливии и Саудовской Аравии- в папках имеются самолеты разной стпени готовности, но я пробовал и другие страны (пустые папки с названиями юнитов - чисто для теста). Все это работало, что позволяет надеяться, что в будущем процесс добавления новых юнитов будет походить быстро и безболезненно (а не так, как в первой версии, да и юниты могут стать какими угодно, к примеру имперский крейсер "Звездный разрушитель", хе-хе)...

вторник, 17 мая 2016 г.

И снова бюрократия...

Без бюрократии никак. "Социализм - это учет" (с). Зачастую начинается процесс поисков и принятия стандартов и решений как в известной сказочек- "пойди туда, не знаю куда и принеси то, не знаю что". В принципее-то, понятно, что нужно, так сказать в глобальном смысле, но вот когда переходишь от общего к частному, вдруг оказывается, что мелочей многог и путей для них как бы не больше.
Аварийный сброс подвесок, сброс топливных баков и выборочный сброс подвесок был осовне и оказался он не таким уж сложным. Кроме того, наконец дошли руки до вычисления лобовогог сопротивления всех внешних потомков и учета влияния их веса. Также в зачаточном состоянии находится реализация столкновения с землей (вот тут придется лезть в ландшафт и присваивать всем его блокам проперти "земля", хотя надо поглядеть, может и на материал реакцию сенсора лучше поставить). Во всяком случае, при проверке поведения самолета после освобождения от подвесок выяснилось, что становится он куда как более разворотливым и пропечатывание принтом величины лобового сопротивления и веса потомков дало положительный результат - поправки вводятся и учитываются. Это, конечно, не аэродинамика, но что-то поближе к ней. Можно вконец обнаглеть и ввести учет по весу расходуемых снарядов виз БК пушек и блоков НАР...
Теперь начинается самое любопытное - обеспечение стрельбы. Как пушками, так и ракетами. Для начала управляемого оружия не будет - точнее данные по его параметрам введены-то будут, но их использование начнется после отработки пусков и сбросов "болванок". Потому что в этой версии управляемое оружие существенно усложнится.
Во-первых, набор оружия сильно возрастет. Это не будеут лишь УРВВ (с РГСН и ТГСН) и УРВП, а также бомбы (обычные и корректируемые) и блоки с НАР.
Во-вторых, параметров для тех же УРВВ станет гораздо больше. К примеру, вводятся ограничения по высоте применения (верхняя и нижняя границы), ограничения по превышению-принижению цели (теперь уже не стрельнешь снизу вверх на 15 км или наоборот),  также будет учитываться ракурс пуска - в переднюю или заднюю полусферу (тут надо хорошенько продумать - известно, что дистанция разрешения пуска в ЗПС меньше раза в 2-3, чем если бы пуск был в переднюю полусферу).
В-третьих широко будет применяться противодействие, причем помехи будут куда как разнообразнее. Кроме тепловых ловушек и диполей со встроенной РЭБ, влияющей на скорость наведения, будут применяться "уводящие" помехи, "подменные" помехи (ракете средства РЭБ смогут "подменить" индекс цели для ее РГСН), также "ослепляющие2 помехи для тепловых ГСН, наподобие "Витебска" или древней "Липы" (по слухам, исходящим из Сирии, экипажи вертолетов, на которых установлен "Витебск", могут не обращать внимания на почти все ПЗРК, кроме самых современных, а вот "Липа" гарантий в той же Чечне не давала против даже стареньких "Стрел"). Плюс дымовые помехи - например для дымовых гранат БТТ, сбивающих наводку УР с лазерной ГСН. В общем, много чего.
Пока что пишется очередной файл формата txt, в который и запихиваются все эти данные. Судя по всему, для каждого вида вооружения будет работать свой класс, который опять же придется писать отдельно. правда, в этом есть и свой плюс - можно не отвлекаться на строчки, относящиеся к другому типу оружия (как это было в первой версии, где я слишком сильно старался все объединить и создать что-то универсальное).
В этот раз картинок не будет и вообще процесс сейчас стал очень небыстрым. По не зависящим от меня обстоятельствам и из-за совершенно взбесившейся погоды с ее грозами много поработать за компом не удается... Да и частенько весь процесс игростроения сводится к высчитыванию на бумаге тех или иных вариантов.