Показаны сообщения с ярлыком игрострой. Показать все сообщения
Показаны сообщения с ярлыком игрострой. Показать все сообщения

суббота, 24 июля 2021 г.

Игра "Морской бой. След торпеды" Альфа-версия.

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


И вот подумалось, а почему бы не попробовать сделать то же самое в БГЕ. Пусть и мертв ныне этот движок, в смысле, не занимаются им больше создатели Блендера, но уж такое-то должен он потянуть.

Сказано- сделано. Альфа версия


Простенькая игра. "Морской бой. след торпеды" Создана в BGE, для работы игры испольуйте Blender 2.79b.Управление - перископ влево-вправо - стрелочки влево-вправо, выстрел - - пробел. При переходе на сцену подведения итогов - выход из игры - стрелочка вниз, новый круг - стрелочка вверх.
Длительность игрового сеанса - 3 минуты, боезапас - 20 торпед. После первого сеанса в разделе "Лучший результат будут нули, затем идет сравнение и результат улучшается в первую очередь по количеству побед за сеанс, во-вторых, если количество текущих побед совпало с лучшим результатом, идет сравнение с количеством израсходованного боезапаса, чем меньше израсходовано торпед на одну цель, тем лучше.

Можете поэкспериментировать с дальностью до генерируемых кораблей - открывайте скрипт Submarine_Control.py и ищите строчку почти в самом конце randomXY = random.randrange(200, 1400). В скобках эта самая дальность, можете расширить ее пределы, но не более 4500, хотя сомневаюсь, что на такой дистанции удастся вообще когда-нибудь попасть. А вот уменьшить, скажем до 800-1000 - улучшит количество попаданий. Отрицательные цифры ставить нельзя, и меньше 100 тоже.

Объем упакованного файла - 49 Мб, распакованного проекта - 74. Запускаемый файл - бленд SeaBattle>blend. Скрипт, о котором я говорил, находится в нем же.

Альфа версия. Только один тип мишени - незатекстуренный, тонет при попадании без всяких дополнительных эффектов, движение слева-направо. Предполагаю следующие изменения/дополнения:
1) Еще пара-тройка моделей кораблей.
2) Все модели с текстурами.
3) Смена текстуры неба случайным образом при старте (для разнообразия).
4) Возможность появления кораблей с другой стороны, но движение все равно будет только в одну сторону (типа конвой в море)
5) Если БГЕ не будет сильно возмущаться - добавить эффект разрушения - пожар на тонущем корабле с дымом.

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

https://drive.google.com/file/d/1cfOjeJLvPIUFGBjxt1e19u2ubN6V5XBh/view?usp=sharing
https://yadi.sk/d/nqPDWcWfxCe93Q


Скрины:

Старт


Сама игра.

Подведение итогов



суббота, 14 декабря 2019 г.

Дорогу осилит ползущий...

Долгое время не писал. Особо не о ч ем было. Как-тог подзабросил дела - очередное лечение с его порцией уколов в глаза, виски и прочие места, чтение накопившихся книг, ползанья по Сети в поисках учебников, чтение оных же, поиск информации и примеров. Да и лень-матушка, куда ж без нее...
На днях выправил ситуацию с неправильной индикацией выбранного оружия на подвесках самолета игрока. Как оказалось, задача была не такой страшной, как виделось. Для этого понадобилось ввести в стартовый json летательного аппарата еще одну переменную, раскомментировать строку в одном скрипте, добавить пару строк в другом. В итоге теперь информация с названием и оружия и его БК послушно высвечивается при перебре оружия и гаснет при выключении системы управления вооружением. Вот так:
Цель - F-16C ВВС США, удаление 24 км, тип оружия - УРСД Р-23Р, БК-2, режим - РЛС с дальностью обнаружения - 60 км.

воскресенье, 4 августа 2019 г.

Четвертая операция.

Почти ровно четыре недели тому назад прошла четвертая для моего правого галаз операция - дисцизия вторичной катаракты. Если перевести на обычный язык, то лазером рассекли постепенно густеющую пленку позади искусственного хрусталика. Делали ее у нас, никуда ехать не пришлось, все прошло быстро и безболезненно. 
Согбственно, речь в этом посте пойдет не столько об операции (которая выступает в роли очередной вехи на жизенном пути), сколько о том, чего удалось сделать за время, прошедшее со дня моего предыдущего поста, то бишь продолжение большого апдейта.
На некоторое время я резко затормозил, бывает со мной такое - внутреннее сопротивление к работе, которое надо рано или поздно давить. После преодоления нежелания работать,дело опять потихоньку стронулось с мертвой точки. Работа теперь идет по двум направлениям - апдейт БГЕ и освоение Юнити. Так, вчера умудрился понять принцип создания деревьев - вроде бы и несложно, но раньше я тупил с добавлением материалов на ветки и листья. Все-таки в Юнити рабочий процесс сильно завязан на интерфейс, и временами таскание переменных туда-сюда начинает раздражать - там ведь еще надо не промахнуться мимо довольно маленькой графы. Иногда проще набить ручками с клавиатуры. По-хорошему, стоило бы ввести поиск перемнных по набираемым символам - например, начинаешь вводить, а тебе в выпадающем меню высвечивается список возможных вариантов переменной. А может, он в Юнити уже и есть, проверить просто надо? 
Ну, кроме брюзжания (возможно, что и незаслуженного), удалось в юнити написать серию скриптов на С#, обеспечивающих работу анимации подвижных частей самолетов. Собственно говоря, как таковой анимации в моем проекте пока нет - идет просто вращение или передвижение нужных деталей-потомков в нужном направлении скриптоами. Вводятся строгие ограничения по скоростям и границы перемещений. Все это, хоть не сразу, но заработало, и из всех нужных скриптов остался недоведенным только скрипт для флаперонов. Скрипты для элеронов, интерцепторов, стабилизаторов, рулей направления, подвижных консолей крыла, закрылков, воздушных тормозов и фонарей кабин были закончены. Как-нибудь потом распишу. Также с подсказкой моего более продвинутого в программировании коллеги удалось заставить скрипт читать файл json.
В Блендер-проекте идет пока отладка скрипта Питона для загрузки нужных данных и моделей через чтение все того же json. Модуль загрузки разбит на несколько более мелких и простых функций, но одна сильно большая, многоступенчатая и несколько запутанная, хотя и работает. Модуль загрузки можно счиать готовым процентов на 90, надо только решить, как реализовать погодные условия и время суток. Наверное, придется отказаться от сложных и сильно затратных шейдеров, а также от масштабных батальных сцен, потому что у БГЕ есть свой предел и через него не перепрыгнешь, хотя и стоит максимально постараться оптимизировать работу игры. Локальные конфликты малой интенсивности - вот на что будет способен проект. Ну и ладно. Лишь бы работало. Да и сам проект я хочу закончить скорее из-за чисто иррационального упрямства - жалко бросать так далеко продвинувшееся дело...

воскресенье, 4 марта 2018 г.

Доводка классов. Прячем все.

Вполне закономерным итогом работы с классами стал полный переход на "внутриклассовую" работу скриптов... В конце концов, под зонтик класса перешла и работа уровней детализации и расчет поправочного коэффициента для выпуска-уборки шасси, тормозов и крыла изменяемой стреловидности. Приводить здесь скрипт класса того же МиГ-23, как представителя юнитов, у которого присутствует все вышеперчисленное, не стоит. Он довольно длинный и особо ничем не отличается от приведенных ранее. Ну, добавилось в метод движения расчет положения крыла, ну появился в классе новый метод для расчета уровня детализации. Все это чисто рабочие моменты...
Главное, что все это работает - и слава Богу, без сбоев. Пока, во всяком случае.
А потом пришел черед выполнить еще один пункт - добавить в классы оружия метод движения. И поведения заодно. Как водится первой жертвой исследования стала ракета Р-27Р. Сам ее класс был слегка модифицирован - всего с полдюжины строчек, но работа себя оправдала. Даже на фоне того, что пришлось аврально вносить коррективы во все остальные классы управляемых ракет. Заодно, кстати, дополнительно "раздробил" скрипт движения оружия, выделив из негог первый тип - ракета. Он характерен для всех типов ракет, кроме НАР. Причина - ракеты такого типа летают не по прямой, поэтому для них невозможно сделать дым одной частицей. О частицах чуть позже. Итак. Скрипт движения ракеты.

import mathutils
import random
import bge
scene = bge.logic.getCurrentScene()

def control(self):
    cont = bge.logic.getCurrentController()
    own = self
    if own.engineWeapon == 'CatapultWeapon':
        CatapultWeapon(own)
    else:
        Missile(own)
   
   
#Полет ракеты
def CatapultWeapon(own):
    if own.vzryvatel == 10:
        own.suspendDynamics
        own.engineWeapon = "Missile"

#Полет ракеты
def Missile(own):
   
    own.applyMovement([0.0,own.speed/60,0.0],True)
    own.timerAmountFire += 1
    if own.amountFire > own.timerAmountFire:
        #Срабатывание добавления частиц дыма от ракет
        own.timerSmoke += 1
        if own.timerSmoke == 1:
            #Дым снаряда
            smoke = scene.addObject('ParticleUniversal', own)
            smoke.replaceMesh("SmokeLong", True, False)
            smoke.setParent(own, False, False)
        if own.timerSmoke == 3:
            if 'ParticleUniversal' in own.childrenRecursive:
                own.childrenRecursive['ParticleUniversal'].scaleX = own.speed/360
                own.childrenRecursive['ParticleUniversal'].scaleY = own.speed/12
                own.childrenRecursive['ParticleUniversal'].scaleZ = own.speed/360
                own.childrenRecursive['ParticleUniversal'].Delta_scaleX = 0.1
                own.childrenRecursive['ParticleUniversal'].Delta_scaleY = 0.1
                own.childrenRecursive['ParticleUniversal'].Delta_scaleZ = 0.1
                own.childrenRecursive['ParticleUniversal'].Delta_colorAlpha = -0.0005
                own.childrenRecursive['ParticleUniversal'].colorAlpha = 0.2
                own.childrenRecursive['ParticleUniversal'].removeParent()
        if own.timerSmoke == 5:
            own.timerSmoke = 0
             


А теперь скрипт класса Р-27Р, который вызывает этот самый скрипт и скрипт головки самонаведения.

import bge

from ClassWeapon import typeWeapon

class R27R(typeWeapon):
       
    import Weapon_Missile as __Weapon_Missile
    import Weapon_GSN as __Weapon_GSN
   
    def __init__(self, old_owner):
        typeWeapon.__init__(self, old_owner)

    def engine(self):
        self.__Weapon_GSN.GSN(self)
        self.__Weapon_Missile.control(self)
       
def mutate(cont):
    R27R(cont.owner)
             

Ну, и собственно, функция работы оружия в игровом файле.

#Функция эффекта взрывов
def controlWeapon():
    cont = bge.logic.getCurrentController()
    own = cont.owner
    own.engine()
   

Как видно, опять "матрешка".  Так сказать, в прямом смысле - в собранной матрешке не видно внутренних составляющих. Но они есть. Как тот суслик из фильма ДМБ".
За это время я восстановил работу РЭБ, восстановил катапультирование из сбитого самолета, и, наконец, добавил огонь для сбитого. Псевдочастицами-плейнами.
А теперь по поводу частиц. К сожалению, БГЕ имеет ограничения и довольно существенные, как раз в этой области, поэтому эти меры - паллиатив. Правда, есть возможность отобрать у БГЕ почти все функции, оставив только загрузку окна и еще что-то по мелочи. Но для этого нужен другой уровень программирования, мой очень сильно недотягивает. Хотя, повторяю, часть функций БГЕ можно передать другим программам. Поэтому извращаться по поводу частиц огня, дыма, облаков и прочего я прекращаю и сосредотачиваюсь на ИИ, оружии, систем противодействия и защиты, выстраивания иерархии ботов, поиска путей и так далее. А еще, наверное, я радикально сокращу количество блоков ландшафта. Раз в 10. Схема вполне работоспособна, но ее можно и нужно оптимизировать.
Все же приведу скрипт работы частиц огня. Суть в том, что их число растет, пока не достигает определенного предела. Все частицы являются потомками и занимают свое место в списке childrenRecursive. Они расставляются на удалении от родителя согласно своему номеру в списке - чем он больше, тем дальше от родителя частица. При этом присутствует некий элемент случайности. По координатам и размерам, но в некоем диапазоне.

import random
scene = bge.logic.getCurrentScene()

#Эта переменная определяет длину "хвоса" огня
fireLong = random.randrange(8, 20)

def FireAir():
    cont = bge.logic.getCurrentController()
    own = cont.owner
   
    #Длина списка потомков
    particleLen = len(own.childrenRecursive)
   
    #Это просто списко для ускорения добавления частиц - удвоение или утроение за один проход в тик
    listObj = ["num0"]
    #listObj = ["num0","num1"]
   
    #Характеристики частицы - локация, размер и цыкт с прозрачностью
    partColor = random.randrange(2, 10)/10
    partLoc = random.randrange(particleLen, particleLen+2)
    partScale = random.randrange(particleLen, (particleLen+2)*2)/(particleLen+2)*4
   
    #Эта переменная используется для отслеживания индекса потомка в списке
    indexObj = 0
   
    #Этап1 - добавляем, парентим и раставляем частицы, отслеживая длину списка потомков
    if particleLen < fireLong:
        for newParticle in listObj:
            newParticle = scene.addObject('Plane', own)
            newParticle.setParent(own, False, False)
            newParticle.replaceMesh("FireAir_", True, False)
            newParticle.localPosition = [partLoc/10, -partLoc, partLoc/10]
            newParticle.worldScale = [partScale, partScale, partScale]
           
    #Этап 2 - работаем с тем, что есть, больше ничего не добавляем
    else:
        for obj in own.childrenRecursive:
            #Здесь переменные локации и размера используются в качестве эталона,
            #к которому подтягиваются ТТХ частиц
            indexObj = own.childrenRecursive.index(obj)
            #partLoc = random.randrange(indexObj, indexObj*indexObj*indexObj+2)
            partLoc = random.randrange(indexObj, indexObj+2)
            partScale = random.randrange(indexObj, (indexObj+2)*2)/(indexObj+2)*3
           
            #Можно поиграться с цветом и прозрачностью
            obj.color = [1.0, partColor, partColor, partColor]
           
            #Хвост пламени - локальные координаты Х
            if obj.localPosition[1] < -partLoc:
                obj.localPosition[1] += partLoc/50
            elif obj.localPosition[1] > -partLoc:
                obj.localPosition[1] -= partLoc/50 
            #Размазанность и толщина хвоста пламени - координаты Икс и Зет
            obj.localPosition[0] = partLoc/4
            obj.localPosition[2] = partLoc/4
           
         
Вот так. Хотя, все это - костыли. Пусть и работающие. Подожду пока прояснения обстоятельств с перхватом рендера и управления БГЕ. Если обстоятельства позволят, то откроются новые перспективы.

вторник, 12 декабря 2017 г.

Прерву несколько затянувшееся молчание...

Некоторое время не писал по причине разом свалившихся проблем, как чисто технических, так и отсутствия вдохновения (бывает со мной такое). Сначала пришлось чистить комп от скопившихся файлов - как дублей, так и устаревших и ставших мусором. Потом воевать с модемом от Билайна - складывается стойкое подозрение, что доблестные связисты зажрались, обленились и перестали ловить мышей - хронически слабый сигнал, но трафик тот же и денбги те же. Только качество стало хуже. А я еще на ни ив чем не повинный модем грешил...
Как всегда, как только я начинаю осваивать новые методы программирования, Вечно Голубое Небо посылает конкретный намек: "Верной дорогой идешь, товарищ!", через наших невероятно трудолюбивых энергетиков, которые проводят "плановые реконструкционно-восстановительные работы на объектах энергообеспечения". Для этого им нужен именно декабрь... Впрочем, см. чуть выше. Два вторника подряд нашу улицу ы числе прочих отключали на весь день. Хотелось бы послущать, что об энергетиках в это время говорили, хотя и так понятно...
Тем временем, проект со страшным скрипом опять сдвинулся с места и пополз вперед. Но для начала мне пришлось опять откатиться назад с шейдерами неба. Причина нетривиальная - перестали нормально работать текстовые маркеры объектов - они стали появляться только в верхней половине экрана. После возврашения старого шейдера неба все опять заработало. Ну ладно, в конце концов небо все равно придется переделывать под свой код...
А затем пришло время новшеств. А именно - назрела необходимость "дробления" скриптов и их вызова из папок. Это позволит разгрузить пусковой файл, сделать скрипты более компактными и понятными, правда, их станет больше. Но все-таки можно теперь не крутить скрипт из полторы тыщи строк, отыскивая нужную функцию и корректируя строчки именно в ней. Особено это касается ИИ ботов. Сурипт раздут очень сильно и его придется разбить на множество "типов поведения" - полет по маршруту, ведение боя, взлет, посадка, уклонение от препятствия и так далее.
Пока что не привожу ни картинок, ни кода, поскольку работа в процессе и код меняется очень быстро, скажу лишь, что с подсказки dron-а используется sys.path(путь к папкам). Этот метод планируется запустить в самом начале при старте игры и в него загонять все нужные пути к папкам со скриптами. Прикол еще в том, что теперь "раздробленные" скрипты при вызове сами вызывают дополнительные надстройки  - еще дополнительные модули, к примеру скрипт для движения юнита тащит за собой модуль анимации подвижных частей, модули управления 9бот или игрок) и модуль сенсоров.
По идее, в самом пусковом файле останутся "узловые" скрипты, которые и будут дкргать цепочки нужных модулей и не все подряд, а только те, что необходимы. Придется, конечно, повозиться, выстраивая новую систему связей, но оно того стоит...
А, да, сделал было приборные панели МиГ-21, но в кабину пока не вставил - см. выше.

понедельник, 9 октября 2017 г.

Отработка действия БЧ снарядов на юниты. Наведение артиллерийских орудий.

В двух предыдущих постах  я писал про взаимодействие снарядов и юнитов. Точнее, воздействие поражающих факторов на сами юниты. Было это все чисто умозрительно и пока не было воплощено на практике, так и оставалось у меня в голове.
Скрипт работы снаряда, точнее, его БЧ (боевой части) был собран не сразу. Точнее, не скрипт, а функция в скрипте CONTROL_Weapon. А когда она была написана, то пришлось поломать голову, почему оно не работает (ну как всегда - там опечатка, там не то имя указал). А главной причиной была нихкая точность - снаряды рвались уж очень далеко от зенитки.  Я использовал миссию теста МиГ-23БН для проверки работы НАР С-8 по зенитке GDF-001 Oerlicon. Выяснилось, что прицельная сетка на самолете не соответствует дальности полета НАР. Пришлось лезть в файл кабины и корректировать ее положение. Теперь, видимо, ту же процедуру надо провести и в остальных машинах. Ничего не поделаешь - до НАР и пушек я просто до сих пор еще не добирался - руки просто не доходили.
Но в конце концов  скрипт заработал полностью в том виде, какой он сейчас есть. Необходимо дописать проверку лучом от эпицентра взрыва до юнита на наличие препятствия (укрытия) на пути ударной волны и осколков. Приведу текст функции для БЧ типа "осколочно-фугасная":
 def OskolFugas(own):
  
    for units in ArbitrGame.UNITS[1]:
        #Проверяем наличие атрибута повреждений у объекта - ударной волне и осколкам все равно, что разрушать
        if hasattr(units, "crash") == True:
            #В зависимости от расстояния подрыва  рассчитывается величина поражающего фактора
            if own.radiusExplode*1.5 < own.getDistanceTo(units) < own.radiusExplode*3:
                own.LEVELS_CRASH = 0.4*own.levelsCrash*own.radiusExplode/own.getDistanceTo(units)
            elif own.radiusExplode < own.getDistanceTo(units) < own.radiusExplode*1.5:
                own.LEVELS_CRASH = 0.8*own.levelsCrash*own.radiusExplode/own.getDistanceTo(units)
            elif own.getDistanceTo(units) < own.radiusExplode:
                own.LEVELS_CRASH = own.levelsCrash
           
            #Вычисление нанесенного урона
            if own.LEVELS_CRASH > units.levelDefens:
                #При условии, что защита "пробита", смотрим на уровень повреждений юнита и вносим коррективы
                if own.LEVELS_CRASH/units.levelDefens < units.crash:
                    units.crash -= own.LEVELS_CRASH/units.levelDefens
                else:
                    units.crash = 0.0
            print(units, units.crash, own.getDistanceTo(units), own.LEVELS_CRASH)

Последнюю строчку можног не принимать во внимание, я ее потом закомментирую или вообще уберу. В ней я отсматривал работу функции. В принципе, все остальные функции типа "проникающе-фугасной", "Фугасной" и прочей БЧ будут работать так же. Разница будет заключаться лишь в градации расстояния для ослабления действия снаряда.
А вот ненаписанные пока функции для кумулятивных БЧ и бронебойно-подкалиберных снарядов будут вести себя по-другому. Там не нужен цикл перебора юнитов сцены - цель одна-единственная и вступают в действие такие факторы, как толщина брони, угол встречи с броней, наличие динамической защиты и ее тип... То же самое, кстиати, относится к пулям стрелкового оружия - они действуют примерно по тому же принципу - скорость, калибр, плюс дальность выстрела. Мда, придется еще как-то по бронепробиваемости в зависимости от дальности , с которой был сделан выстрел, что-то придумывать...
И в конце об артиллерии. Здесь я приведу  скрипт работы артиллерийского орудия. На данный момент на нем работает "Эрликон", но там еще надо смотреть по его точности - в скрипт введен разброс снарядов и ошибки прицеливания. Весьма вероятно, что с этим я переборщил...
import bge
import json
import sys
import random

cont = bge.logic.getCurrentController()
own = cont.owner
scene = bge.logic.getCurrentScene()
ArbitrGame = scene.objects["ArbitrGame"]
#Импортируем модуль юнита
#unit_module = __import__(own.unitModule)
t = 0.0
xS = 0.0
yS = 0.0
zS = 0.0
S = 0.0

newPos = [xS, yS, zS]
import CONTROL_Operations
import CONTROL_Sensor
import mathutils

scene = bge.logic.getCurrentScene()


def UnitArtillery():
    cont = bge.logic.getCurrentController()
    own = cont.owner
   
    ################################################################
    #Просчет уровней детализации
    if own.maxVisibleDist < own.getDistanceTo(scene.active_camera):
        own.levelsDetails = 2
    elif own.maxVisibleDist/10 < own.getDistanceTo(scene.active_camera) < own.maxVisibleDist:
        own.levelsDetails = 1
    elif own.maxVisibleDist/10 > own.getDistanceTo(scene.active_camera):
        own.levelsDetails = 0
    #print(own.getDistanceTo(scene.active_camera))
       
    #Работа с детализацией   
    if own.Temp_levelsDetails != own.levelsDetails:
        CONTROL_Operations.levelsDetailArtillery(own)
        own.Temp_levelsDetails = own.levelsDetails
   
    if own.crash > 0.1:   
        if own.typeMissions != "":
            if own.statusBattery == "Commander":
                own.timerTargetChanged += 1
                if own.timerTargetChanged == 600:
                    targetChangedOwn(own)
                    own.timerTargetChanged = 0
                if own.targetID != "":
                    Ballistica(own)
   
        #Блокировка возможности стрельбы при отсутствии бокомплекта
        if own.BK == 0:
            own.shoot = 0
            own.targetID = ""
            own.PR = 0
       
        #Разрешение на открытие огня
        if own.PR == 1:
            own.shoot = 1
        else:
            own.shoot = 0
   
        #Стрельба
        if own.shoot == 1:
            shooting(own)   
        #Остановка стрельбы
        if own.Temp_shoot != own.shoot:
            if own.Temp_shoot == 1:
                own.Temp_shoot = own.shoot
           
           
           
#Функция выбора ближайшей цели. Используется для зениток и стрельбы прямой наводкой
#по конкретной цели, для стрельбы с закрытых позиций по площадям и квадратам
#используются координаты
def targetChangedOwn(own):
    if own.typeMissions == "AntiAircraft":
        own.targetType = 0
    sceneObjList = ArbitrGame.UNITS[0][own.targetType][own.target]
    tempSortedList = []
    if len(sceneObjList) > 0:
        tempsortedList = sorted(sceneObjList, key = lambda obj:own.getDistanceTo(obj))
        #print(tempsortedList)
        own.targetID = str(id(tempsortedList[0]))
    else:
        own.PR = 0
        own.targetID = ""

#Расчет точки упреждения      
def Ballistica(own):
   
    try:
        target = scene.objects.from_id(int(own.targetID))
        #Тип прицеливания - отслеживание самой цели
        if own.typeCoordTarget == "AimingTarget":
            newPos = target.worldPosition
        #Тип прицеливание с упреждением
        if own.typeCoordTarget == "VisibleTarget":
            # Рассчитываем время полета снаряда.       
            t = own.getDistanceTo(target) / own.speedBullet  
            # Рассчитываем путь перемещения объекта за это время.
            S = target.worldLinearVelocity * t
       
            xS = target.worldPosition[0] + S[0] + random.randrange(-own.razbros,own.razbros)
            yS = target.worldPosition[1] + S[1] + random.randrange(-own.razbros,own.razbros)
            zS = target.worldPosition[2] + S[2] + abs((-10*t*t)/2) + random.randrange(-own.razbros,own.razbros)
            newPos = [xS, yS, zS]
        #print(target)
        Turret(own, newPos)
    except:
        own.PR = 0
        own.targetID != ""

#Управление наведением в горизонтальной плоскости       
def Turret(own, newPos):
    #print(own.PR)
    Turret = own.childrenRecursive[own.unitName + "Turret_"]
    #Данные по ориентации
    orientY = Turret.getVectTo(newPos)[2][1]
    orientX = Turret.getVectTo(newPos)[2][0]
   
    #Скорость наведения
    kZ = own.speedMaxGor
   
    correct = 1.0
    znak = 0
   
    if orientX > 0:
        znak = -1
    elif orientX < 0:
        znak = 1
   
    if orientY > 0.9:
        correct = 1 - orientY
    else:
        correct = 1.0  
   
    Turret.applyRotation([0.0,0.0,kZ*correct*znak], True)
    Canon = own.childrenRecursive[own.unitName + "Canon_"]
    orientZ = Canon.getVectTo(newPos)[2][2]
    kX = own.speedMaxVert
    correctCanon = 1.0
    znakCanon = 0
   
    if orientY > 0.7:
        if orientZ > 0:
            znakCanon = 1
        elif orientZ < 0:
            znakCanon = -1
     
        if abs(orientZ) < 0.2:
            correctCanon = abs(orientZ)
        else:
            correctCanon = 1.0
       
        Canon.applyRotation([kX*correctCanon*znakCanon,0.0,0.0], True)
       
    if abs(orientZ) < 0.1 and orientY > 0.9 and own.getDistanceTo(newPos) < own.distMax:
        #print(own.getDistanceTo(newPos))
        if own.Temp_cassetteBK < own.cassetteBK:
            own.PR = 1
           
        else:
            own.PR = 0
    else:
        own.PR = 0
   
    #Перезарядка - магазин, кассета, обойма или снаряд
    if own.Temp_cassetteBK == own.cassetteBK:
        own.PR = 0
        if own.Temp_cassetteBK > 0:
            if own.Temp_timerCassetteChanged < own.timerCassetteChanged:
                own.Temp_timerCassetteChanged += 1
            elif own.Temp_timerCassetteChanged == own.timerCassetteChanged:
                own.Temp_timerCassetteChanged = 0
                own.Temp_cassetteBK = 0
               
       

   
def shooting(own):
    #Стрельба из пушек, пулеметов и многоствольных систем
    if own.typeShoot == "Zalp":
        for FLAME in own.fireGun:
            addBullet(own, FLAME)

    #Стрельба из РСЗО, РБУ и прочих реактивных(ракетных) систем
    elif own.typeShoot == "Paket":
        FLAME = own.fireGun[own.BK-1]
        addBullet(own, FLAME)
       
    own.BK -= 1
    own.Temp_cassetteBK += 1

#Функция добавления снаряда и прочего - звука, вспышки...           
def addBullet(own, FLAME):
    Canon = own.childrenRecursive[own.unitName + "Canon_"]
    #Вспышка - лампа
    vspyshka = scene.addObject('LampUniversal', Canon, own.gunPausa+1)
    vspyshka.setParent(Canon, False, False)
    vspyshka.localPosition = FLAME
    #Вспышка - меш
    vspyshkaMesh = scene.addObject('AudioGun', Canon, own.gunPausa+5)
    vspyshkaMesh.setParent(Canon, False, False)
    vspyshkaMesh["audioProp"] = own.audioGun
    vspyshkaMesh.replaceMesh("FireUniversal", True, False)
    vspyshkaMesh.localPosition = FLAME
    razmer = own.scaleGun
    vspyshkaMesh.worldScale = [razmer, razmer, razmer]
    vspyshkaMesh.visible = 1
       
    #Снаряд цепляется к самому юниту и происходит мутация
    #Проверяется наличие атрибута вроде калибрСнаряд = 23мм
    #и объект мутирует в своем классе
    dynObj = scene.addObject('UniversalBullet',vspyshka , 300)
    dynObj.worldScale = [1.0,1.0,1.0]
    if "calibr" not in dynObj:
        dynObj["calibr"] = own.gunBullet   
    dynObj.localLinearVelocity = [random.randrange(-own.randomSpeed,own.randomSpeed),
                                  random.randrange(-own.randomSpeed,own.randomSpeed)+own.speedBullet,
                                  random.randrange(-own.randomSpeed,own.randomSpeed)] 

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




пятница, 8 сентября 2017 г.

Бюрократия. Ревизионизм. Реанимация. Тестирование. Су-25. И снова про blf - избавление от кракозябр.

Следующим после МиГ-27К к реанимации был назначен Су-25. Работа выдалась вполне рутинной. Сначала. А вот потом вдруг всплыла нерешенная еще в пераой версии проблема - кабина Су-25, которую я перенес во вторую версию, была меньше требуемых размеров. Произошло это из-за ошибки в моделировании Су-25 в первой версии. Тогда я вывернулся с оверлейной сценой и благополусно забыл об этом. во второй версии из-за ряда новых нюансов подобная халява не прокатила и пришлось кабину "увеличивать". А вместе с ней и остальные детали - индикаторы, стрелочки и тд. Также пришлось подгонять названия деталей под единый стандарт и править текст скрипта работы приборов. Попутно выяснил, что можно UV-скроллинг задавать из единого центра, называя имена объектов в скрипте - все равно мешей у них в списке всего один. по-видимому, придется все кабины зачистить от лишней логики работы курвиметров и вообще потихоньку оптимизировать скрипты, перечислив газвания стрелочек в "шапках" модулей. Ну, ладно, не в первый раз оптимизирую.
Пришлось повозиться с json для Су-25. Постоянно выплывала ошибка в строке с данными сенсора. В конце концов мое терпение лопнуло и я ее заменил на строчку из другого json, подкорректировав цифры. Ошибка пропала. Что это было я так и не понял.
Установил в кабине прицел АСП-17, про который я писал уже в своем блоге здесь, но пока толком не тестировал.
Большую работу пришлось проделать с меню. Серией различных ухищрений мне удалось достичь того, что теперь текст может более-менее точно располагаться на кнопке, а не только рядом с ней, он может быть русским или английским, иметь определенный цвет и прозрасность. К сожаленпию, смена текстур в 2.78 была таки сломана, да и видеотекстура теперь работает странно... Так что смена заставок в меню была сделана через замену мешей, зато раотает железно.
Наконец, с подсказки dron-а, были ликвидированы жуткие кракозябры вместо русского текста. Понятно, что во всем была виновата кодировка. преодолевается это так:

 with open(bge.logic.expandPath('//Menu/StartMenu.json'), 'r', encoding = 'utf-8') as directMenu:
        JSONmenu = json.load(directMenu)

В данном случае encoding = 'utf-8' - это убийца кракозябр. Русский текст после этого нормально воспринимается и читается в БГЕ и можно его пропечатать на экране хоть в текстовом объекте, хоть в blf. Кстати о последнем. Я уже писал о выведении текста на экран. У меня работают текстовые метки целей (наконец-то получилось отсечь цели позади активной камеры),  но надо было обязательно сделать меню справку о клавишах и командах. Приводить весь текст json, пожалуй, не буду, он длинный и однообразный. Приведу строчку с разъяснением структуры, хотя, там скорее всего и так будет более-менее поянтно.

"str1":{"az":35,"buki":45,"vediR":1.0,"vediG":1.0,"vediB":1.0,"vediA":1.0,"strX":0.01,"strY":0.975,
        "textRus":"Команды","textEng":"Option"},
"str2":{"az":35,"buki":45,"vediR":1.0,"vediG":1.0,"vediB":1.0,"vediA":1.0,"strX":0.01,"strY":0.95,
        "textRus":"+ - увеличение тяги двигателя","textEng":"+ - Engine power plus"}

Хотя нет, не все. Тут еще дело упирается в мой специфический юмор. Недолго думя, я обозвал переменные сами видите как. az и buki - это размер текста. vedi с заглавными буквами - это цвет и прозрасность текста - RGBA, strX-Y- координаты начала строчки на экране. Далее понятно - русский и английский текст. Дело в том, что я постепенно наращивал число ключей в словаре json, не зная толком, что понадобится в работе - в итоге вот так и получилось. Хотя можно и упростить.
Как бы то ни было, меню стало более вменяемым и происходит его сборка-пересборка при смене разделов. у меня не было ни малейшего желания громоздить кучу сцен ради меню, надеюсь, удастся итоговую сцену тоже не делать, а возвращаться в сцену с меню.
И да, наконец удалось ввести в сцену террайна наземную цель - бункер, взаимодействие которого при попадании оружия еще надо как-то отработать - обрушение, разлет обломков там...
Пока меню имеет пять миссий - для МиГ-23МФ и МиГ-29  это перехват Ф-16 и Ф-15 соответственно. Для Су-25, МиГ-23БН и МиГ-27К  я противников из воздуха убрал, но оставил в качестве цели бункер. Надо попробовать ввести МЗА и СЗРК. В первой версии МЗА "Эрликон" был, надо перетаскивать. Плюс "Стрела-1" и БРДМ-2, но их текстурить надо. Когда-то я сделал модель БМП-1. Ее надо избавить от высокополигональных катков и гусениц, посмотреть, что можно упростить и туда же, тем более, она была затекстурена...
В общем, продолжим...
Ниже скрины - нельзя же совсем ез картинок - Су-25 и его кабина. Подвешены по две пары блоков С-8 и бомб ФАБ-250, плюс пара ракет Р-60М.


четверг, 10 ноября 2016 г.

Первый сбитый, сверхзвук, штопор и подопытные кролики.

Несколько дней назад случилось знаменательное событие в жизни второй, пока еще строящейся версии проекта. Ракетой Р-23Р с борта МиГ-23МФ ВВС Ливии была поражена мишень, рольк оторой исполнил БПЛА Ла-17. Один подопытный кролик скушал второго и стех пор происходит подобное регулярно.
После долгой возни с амонведением ракет и вылавливанием ошибок в скрипте самонаведения (которые заключались лишь в неверной расстановке последовательности строчек, ракетам удалось объяснить, кого надо выбирать из скопища объектов в сцене, как на него ориентироваться . А потом пришлось думать над нанесением ущерба путем подрыва на случайной (в разумных пределах) дистанции. В зависимости от дистанции подрыва и выдается ущерб, причем не только цели но и всем объектам вокруг нее, опять-таки в некотором радиусе. Чем дальше подрыв от объекта, тем меньше вероятность для него получить смертельные повреждения. Это было сделано, чтобы при удачном стечении обстоятельств могла повториться ситуация поражения одной ракетой нескольких самолетов. как это случилось во время ирано-иракской войны, когда иранский "Томкэт" одной ракетой "Феникс" сбил сразу три иракских МиГ-23БН, шедших в плотном строю или во Вьетнаме, когда одним из первых пусков ЗРК С-75 тоже было сбито три "Фантома" (американские летчики тогда еще были непугаными).
Затем пришлось с помощью скриптов объяснять сбитой мишени, что она должна плавно падать по баллистической кривой, да еще при этом испуская огонь и дым. Дым-то она испускает, а вот огонь пока нет... Попутно на b3d.ua прозвучали предложения делать системы частиц одним объектом, состоящим из многих плейнов, управляя через скрипт их геометрией, расположением в пространстве и другими параметрами. Идея хорошая, только мой уровень пока не достиг дзена управления вершинами мешей. Я пока  ограничился беглым просмотром АПИ, но детально не вникал. Потому что впереди будет 2.78 официальная сборка, плюс я занялся еще пробитием звукового барьера и штопором.
в первой версии пробитие звукового барьера приводило к снижению слышимости двигателей, резкому хлопку с появлением быстро тающего облака и только. На сей раз я не снижаю громкость двигателя, я просто отодвигаю все источники звука назад от самолета и возвращаю их на место при переходе со сверхвука на дозвуковой режим.
И вот сегодня утром мне удалось отрегулировать вывод самолета из штопора. Этот режим я так и не ввел в первой версии, зато теперь оттянулся. Обеспечив сваливание машины в штопор, мне пришлось искать условия выхода их него. Точнее, регулировать некоторые коэффиенты в  модели полета. Я прекрасно отдаю себе отчет, что это - псевдоаэродинамика, к реальности имеющая отношение разве что лишь внешне, но это лучше, чем ничего. Кроме того, попутно ввел ограничения по крену - чем больше тангаж самолета (опущен или задран нос), тем хуже (медленнее) он крнеится (прочитал об этом на форуме Лок Она и немедленно всадил в скрипт по принципу "чтоб было и на что-то было похоже). Модель полета и раньше отличалась от первой версии, а сейчас - тем более.
В общем-то, теперь можно переходить на изготовление искусственного интеллекта летающих ботов, попутно вводя радиопереговоры, звуки кабины и прочее.
Нныче что-то Гугл не хочет картинки добавлять, не знаю уж почему, так что скрин добавить не удалось. Кому интересно, идите на b3d.ua, там последние скрины и увидите.


пятница, 19 августа 2016 г.

Контрольный выстрел. Анимации больше нет...

Как-то довольно быстро после последнего сообщения и боях с форматом json, было восстановлено все. Кроме текстовой индикации на кокпите, которую я намереваюсь рисовать через blf. К сожалению, то ли я удалил файлик с заготовкой, то ли запихнул его куда-то, но теперь придется это дело поновой начать, благо что образец скрипта я скопировас АПИ Блендера.
Все эти дни методично занимался подчисткой и сортировкой того, что уже было сделано и дописывал требующееся. Была восстановлена пушечная и ракетная стрельба, как УР, так и НАР, аварийный сброс подвесок, сброс топливных баков и бомб. Поскольку мои руки еще не добрались до кода со стрельбой я еще толком ничего не успел поломать, чтобы потом героически восстанавливать мною же порушенное. Так, переделал немного имена проперти в коде, поскольку лазить по json и исправлять там было влом.
Долго и тщательно "приглаживал" кокпит. В общем сама картина не поменялась - ноэто внешне. Хотя кое-какие видные глазу ихменения все же произошли. Я наконец добрался до стрелочек угла атаки, угла сноса и перегрузки. Эти стрелки у меня были фактически для декорации в первой версии, теперь у них функция несколько ближе к реальной. Поскольку изменения претерпела сама модель полета, появилась "боковая" составляющая и "вертикальная" составляющая. Это как имитация "заноса" машины на повороте. Только машину, по большому счету ведет влево-вправо, а самолет еще и вверх-вниз. Отдаю себе отчет в том, что деление "боковых" и "вертикальных" скоростей сноса на линейную скорость самолета это не аэродинамика, но все же лучше, чем ничего. Таким образом яполучил угол атаки, угол сноса и перегрузку (сумму "боковой" и "вертикально" составляющей, деленную на скорость машины). Пришлось повозиться с выставлением коэффициентов для ограничения работы стрелок, чтобы не вертелись как попало, но оно того стоило. Затем пришло время разбить приборы и индикаторы на группы объектов и создать в скрипте отдельные функции типа dvigInd, chassyInd, wingsInd и так далее. Все эти функции вызываются лишь при изменении текущих данных - выпуска-уборки тормозов-шасси-закрылков, изменении тяги двигателя и так далее. В итоге сама функция Cockpit в одноименном скрипте превратилась в своеобразный коммутатор, для вызова функций работы индикаторов и стрелочек. Индикаторов у меня что-то около 40 штук, плюс что-то около 20 стрелок. Все это хозяйство ныне исправно функционирует и выдает нужну. информацию.
После того, как кокпит МиГ-23МФ был отлажен и выловлены все ошибки и недочеты, занялся изничтожением оставшейся анимации. Дело Термидора должно было быть доведено до конца...
Как выяснилось, "глаз боится, руки стучат по клаве",  необходимо было убрать анимации из гидравлики и стоек шасси - всего - 16 объектов. Дело осложнялось тем, что некоторые объекты имели весьма сложную траекторию движения, по ходу исполнения самой анимации направление движения могло измениться на противоположное.
Тем не менее проблема была решена с помощью if own==blabla: own=bla. Я просто разбил участки работы проперти CHASSY на интервалы, внутри которых менялись скорости и направления движения. Пока, на мой взгляд, строчек многовато, но в будущем, надеюсь, и здесь часть строчек будет убрана. Пока работает и ладно. Что мне и нужно было. Таким образом, анимации в файлах модели больше нет. Совсем.
Возможно, что в 2.78 баг с проигрыванием анимации уже поправили,  но пока не проверял. Да и по большому счету, уже пока и не нужно.
Есть еще кое-какие фишки в Блендере, до которых пока руки не доходят. Так, есть возможность смешения текстур (декали, бортовые номера, имитация повреждений), но все это пока перекрывается тем, что объекты, добавленные в сцену через addObject, имеют одинаковый материал, поэтому и выглядеть будут одинаково...
В общем, пока вот так. Джейсон прочно утвердился в проекте (оказывается, есть еще кое-какие возможности, надо их изучить), анимация в модели и в кабине полностью убрана (это привело к уменьшению файлов примерно на 20 процентов), кабина отлажена полностью, за исключением прицела (не в кого пока целиться, Ла-17 взял из старого проекта, заодно выяснил, откуда там прозрачность и вывернутость полигонов - в настройках материала не отключил Transparency), работает оружие, механизация, стрельба и взрывы. Надо готовить мишени и на них отрабатывать до конца модель повреждений и воздействие оружия, плюс прицел и сенсоры.

суббота, 13 августа 2016 г.

Фредди против Джейсона. Ужасы перестройки.

Похоже, давать постам громкие заголовки, используя названия фильмов (особенно, когда сказать нечего по существу), становится у меня традицией. Почему "Ужасы перестройки"? Да потому что использование json (который я уже обозвал Джейсоном) несет массу неожиданностей. Почему "Фредди против Джейсона"? А потому, что такой фильм был. Даже два - у меня на самом первом компе завалялся огрызок этого фильма - файл был поврежден, поэтому какой маньяк с каким маньяком там воевал установить не удалось. Фредди - это, конечно Федя Крюгов (Фредди Крюгер) - так я с некоторых пор именую свой старый стиль программирования для выставления проперти юнитам (смотрим посты ниже с длинными рядами строк присвоения пропертей). Подобная простыня с многими отступами и занимающая больше 500 строчек способна вогнать в ужас любого мало-мальски сведущего в программировании человека (я имею в видк тех, кто знает не только if own: own, в отличие от меня). Джейсон (json) дает возможность не в пример быстрее и понятнее загрузить данные, правда, с некоторыми оговорками.
Дело в том, что, как мне объяснил dron, проперти в Блендере написаны на языке Си, а метод attrDict вообще-то дает питоновские проперти и, разумеется, вся система мгновенно рушится. Так что сам метод не виноват в том, что у меня ручки кривые (Питон и Си - языки вообще-то разные, а валить все на разработчиков Блендера  не стоит, хотя иногда знатные подарки они таки преподносят, как с проигрыванием анимации).
Поэтому был найден еще один способ раздать проперти, читая файл

jsonINIweaponFile = open(bge.logic.expandPath('//Weapon/'+pathObj+'/'+pathObj+'.json'),'r')
#Читаем файл с проперти
weaponINI = json.load(jsonINIweaponFile
 #Выдаем проперти со значениями и закрываем файл
  for key in weaponINI:
        if key not in newObject:
              newObject[key] = weaponINI[key]

Не сказать, что это меня сильно обрадовало, но, по крайней мере, пока срабатывает. Этот кусочек кода предназначен для выдачи проперти ракетам, бомбам, пилонам подвески - всему тому, что составляет внешнюю подвеску на самолете. Кстати, точно так же раздавались проперти двигателю самолета, с одной поправочкой - в последней строчке отсутствовало not, поскольку проперти я заранее там выставил в блоке редактирования логики, проставив нулевое значение.  И тут неожиданно всплыло еще одно препятствие...
Сначала вообще-то надо прочесть файл старта миссии - названия юнитов, их координаты, лриентация, сторона, способ управления и оружие. Чтение json по данным, не относящимся к проперти юнита проходило отлично - никаких отклонений, ошибок и прочего. Однако, стоило мне присвоить значение проперти target(сторона) и bot(способ управления), как все пошло кувырком после чтения второго json  с остальными проперти (маневренность, тяга, высотность, скорость). Такое впечатление, что повторное вмешательство в проперти опять же с чтением json вызывает какой-то сбой и в этом опять же виноваты особенности проперти в БГЕ.
В итоге на данный момент с помощью хитроумных извращений удалось сделать загрузку всех проперти юнита, сделать генерацию оружия с заменой мешей и работающей системой объектов, зависящей от требуемой детализации, но стартовую загрузку миссии все же оставить в формате txt. Со всеми вытекающими - чтнеием по маркерам-разделителям, резкой и преобразованием текстовых блоков и тд. Это не есть хорошо - Фредди прочно пока удерживает последние позиции (лишь бы не получилось, как с сериалом "Кошмар на улице Вязов" - серия 9 - "Фредди мертв. Последний кошмар", серия 10 "Фредди жив! Новый кошмар"), потому что к хорошему быстро привыкаешь и полста строчек кода вместо полтыщи выглыдят куда привлекательнее. К тому же удалось более-менее выстроить стройную систему генерации вооружения и начать клепать файлы с данными для конкретной ракеты или бомбы. Файлики небольшие, читать и понять их гораздо проще и легче. Посмотрим, не подведут ли меня эти методы генерации и раздачи свойств для оружия. Пуски-то и сброс я пока закомментил...
В результате всего этого произошел переход на 2.77, пусть в нем и присутствует баг с анимацией, но выправлены некоторые другие, да и анимация почти исчезла даже для кокпита - ее заменила ориентация стрелок, как выяснилось, надо просто правильно подобрать коэффициенты. Кроме того, как выяснилось, в БГЕ есть возможность рисовать текст на экране без использования текстовых объектов. Смотрим функцию blf в АПИ Блендера. Тексту можно давать цвет, размеры и расположение на экране. В свое время dron как-то делал GUI еще на старом сайте БлендерУкраина. Я же сделал вывод, что совершенно необязательно делать извращения с заменой мешей с текстурой текста или создавать еще одну оверлейную сцену с текстовыми объектами (есть в Блендере очень старый баг с невидимостью некоторых объектов при взгляде через текстуру с альфа-каналом - об этом, кажется писал еще O.din13 на БУ). Так что текст, скорее всего будет именно рисованным через blf, обновлять его придется либо при повороте камеры либо при поступлении новых данных, что будет происходить относительно редко, так что много сожрать не должно.
В общем перестройка после "термидориансокого переворота"  пусть и со страшным скрипом, но идет вперед.

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

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

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

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

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

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

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