После успешного завершения работы над кабиной МиГ-23 и восстановлением систем РЭБ, прицеливания и наведения встал вопрос о восстановлении кабины МиГ-29. Кроме него надо было привести под общий стандарт F-5E и F-15C. Дабы оппоненты были более разнообразными. Это было проделано, правда половинчато. У "Тайгера" надо дописывать скрипт псевдоанимаций шасси (что меня не приводит в восторг из-за его сложности, точнее, многословности). Для МиГ-29 были сменены "шкурки" камуфляжа, а потом еще и кабины.
Дело в том, что Блендер начал ругаться на потерю способа компрессии dds, как я это понял из сообщений консоли. По совету Андрея (aka dron) я применил компрессию типа dxt1 после установки аддона для dds в ГИМПе, причем конверитровал картинки типа png. Пока ругань консоли ограничивается моими ошибками в коде, что радует. В сущности, кабина МиГ-29 особо не изменилась, если смотреть на текстуры. А вот ИЛС, работа приборов и СПО претерпели некоторые изменения. Особенно много возни было с системой предупреждения об облучении СПО-15. В отличие от СПО-10 в ней на порядок больше ламп и гореть должны только нужные.Первая версия СПО-15 двухлетней давности, если мнен не изменяет память, была мною здесь выложена, она длинная и выполнена методом "против лома нет приема" с помощью "дао дятла" - методичное построчное перебирание ламп, пусть и с некоторыми исключениями части кода с помощью условий. Меня не радовала перспектива повторить сей подвиг, тем более, что вводные данные изменились и перебирать строчки в поисках ненужных - да ну на фиг...
Вместо этого я обратился к спискам и сравнению списков. Я разбил имена объектов или сами объекты по спискам, к примеру лампы дистанции до угрозы, лампы вектора на угрозу, и тд. Некоторые списки содержат в именах объектв для сравнения например LampThreat60km. смотрим на последние символы в названии (в действительности оно немного другное, но суть та же). Режем имя методом split, чтобы "вышелушить" число 60. Чтобы строку превратить в число применяем int и умножаем на 1000. Все. Если в данных дистанция до угрозы больше 60000, зажигаем лампу с этим названием, если меньше - гасим.
С вектором на угрозу пришлось поступить хитрее. Кроме списка ламп для индикации вектора на угрозу был создан список,э-э, секторов угрозы вида [[-0.1,0.1],[-0.5,0.5]],[опять цифры во вложенном списке]. Список содержит примерно 10 элементов, в которых есть два вложенных списка - это вектор на угрозу справа и слева и вектор на угрозу спереди и сзади. На входе получается вектор на угрозу и проверяется на "укладывание" в некоторые условия, заданные этим списком с квадратными скобочками. Если данные вектора ПОЛНОСТЬЮ соответствуют вложенным спискам, то лампа горит, иначе - гаснет А прикол в том, что список секторов угрозы по последовательности соответствует списку лампочек. Все делает цикл. Ламп примерно дюжина, так что БГЕ несильно напрягается, если учесть, что СПО работает раз в пару секунд. В итоге код резко "съежился".
А теперь код для СПО-15. На лишние списки внимания не обращать - они для других функций.
import bge
import random
import mathutils
import CONTROL_gamer
A_X = 0
#Далее идет блок клавиатурных команд
keyboard = bge.logic.keyboard
JUST_ACTIVATED = bge.logic.KX_INPUT_JUST_ACTIVATED
JUST_RELEASED = bge.logic.KX_INPUT_JUST_RELEASED
INPUT_ACTIVE = bge.logic.KX_INPUT_ACTIVE
scene = bge.logic.getCurrentScene()
sceneCockpit = scene
pitchListDigital = [scene.objects["pitchILS0"],
scene.objects["pitchILS1"]]
spo15lampGrad = ["SPO-15grad10R","SPO-15grad30R","SPO-15grad50R","SPO-15grad90R",
"SPO-15grad10L","SPO-15grad30L","SPO-15grad50L","SPO-15grad90L",
"SPO-15LampLzps","SPO-15LampRzps","SPO-15PPS"]
spo15lampGreen = ["SPO-15green10R","SPO-15green30R","SPO-15green50R","SPO-15green90R",
"SPO-15green10L","SPO-15green30L","SPO-15green50L","SPO-15green90L",
"SPO-15greenLzps","SPO-15greenRzps","SPO-15PPS"]
spo15Grad = [[[0.01, 0.1],[0.0, 1.1]],[[0.1, 0.3],[0.0, 1.1]],[[0.3, 0.55],[0.0, 1.1]],[[0.55, 1.0],[0.0, 1.1]],
[[-0.1, -0.01],[0.0, 1.1]],[[-0.3, -0.1],[0.0, 1.1]],[[-0.55, -0.3],[0.0, 1.1]],[[-1.0, -0.55],[0.0, 1.1]],
[[-1.0, 0.0],[-1.1, 0.0]],[[0.0, 1.0],[-1.1, 0.0]],[[-0.01, 0.01],[0.0, 1.1]]]
spo15lampDist = ["SPO-15Lamp65km","SPO-15Lamp60km","SPO-15Lamp55km","SPO-15Lamp50km",
"SPO-15Lamp45km","SPO-15Lamp40km","SPO-15Lamp35km","SPO-15Lamp30km",
"SPO-15Lamp25km","SPO-15Lamp20km","SPO-15Lamp15km","SPO-15Lamp10km",
"SPO-15Lamp5km","SPO-15Lamp1km"]
spo15typeThreat = ["SPO-15AirObj","SPO-15ZRKBD","SPO-15ZRKSD","SPO-15ZRKMD","SPO-15DRLOW","SPO-15DRLOZ"]
textFuel = [scene.objects["fuel0"],
scene.objects["fuel1"],
scene.objects["fuel2"],
scene.objects["fuel3"]]
textSpeedTarget = [scene.objects["targetSpeed0"],
scene.objects["targetSpeed1"],
scene.objects["targetSpeed2"],
scene.objects["targetSpeed3"]]
textHeightTarget = [scene.objects["targetHeight0"],
scene.objects["targetHeight1"],
scene.objects["targetHeight2"],
scene.objects["targetHeight3"],
scene.objects["targetHeight4"]]
textSpeedOwn = [scene.objects["ownSpeed0"],
scene.objects["ownSpeed1"],
scene.objects["ownSpeed2"],
scene.objects["ownSpeed3"]]
textHeightOwn = [scene.objects["ownHeight0"],
scene.objects["ownHeight1"],
scene.objects["ownHeight2"],
scene.objects["ownHeight3"],
scene.objects["ownHeight4"]]
def spo15(own):
"""
bge.logic.globalDict['SPODATA'][0] = own.getDistanceTo(threat)
bge.logic.globalDict['SPODATA'][1] = threat.LockOn
bge.logic.globalDict['SPODATA'][2] = threat.PR
bge.logic.globalDict['SPODATA'][3] = threat.avto
bge.logic.globalDict['SPODATA'][4] = own.worldPosition[2] - threat.worldPosition[2]
bge.logic.globalDict['SPODATA'][5] = own.getVectTo(threat)[2][0]
bge.logic.globalDict['SPODATA'][6] = own.getVectTo(threat)[2][1]
bge.logic.globalDict['SPODATA'][7] = threat.unitName
bge.logic.globalDict['SPODATA'][8] = threat.subTypeUnit
"""
if bge.logic.globalDict['SPODATA'] != [0.0, 0, 0, 0, 0.0, 0.0, 0.0, "", ""]:
for element in spo15Grad:
#print(bge.logic.globalDict['SPODATA'][5],bge.logic.globalDict['SPODATA'][6])
if element[0][0] < bge.logic.globalDict['SPODATA'][5] < element[0][1] and element[1][0] < bge.logic.globalDict['SPODATA'][6] < element[1][1]:
scene.objects[spo15lampGrad[spo15Grad.index(element)]].visible = 1
if bge.logic.globalDict['SPODATA'][2] == 1:
scene.objects[spo15lampGreen[spo15Grad.index(element)]].visible = 1
else:
scene.objects[spo15lampGreen[spo15Grad.index(element)]].visible = 0
else:
scene.objects[spo15lampGreen[spo15Grad.index(element)]].visible = 0
scene.objects[spo15lampGrad[spo15Grad.index(element)]].visible = 0
CONTROL_gamer.SPOaudio()
#Распознавание типа угрозы
for typeThreat in spo15typeThreat:
if bge.logic.globalDict['SPODATA'][8] in typeThreat:
scene.objects[typeThreat].visible = 1
else:
scene.objects[typeThreat].visible = 0
if bge.logic.globalDict['SPODATA'][1] == 1:
scene.objects["SPO-15alarm"].visible = 1
if bge.logic.globalDict['SPODATA'][4] > 0:
scene.objects["SPO-15alarmUp"].visible = 1
scene.objects["SPO-15alarmDown"].visible = 0
else:
scene.objects["SPO-15alarmUp"].visible = 0
scene.objects["SPO-15alarmDown"].visible = 1
else:
scene.objects["SPO-15alarm"].visible = 0
scene.objects["SPO-15alarmDown"].visible = 0
scene.objects["SPO-15alarmUp"].visible = 0
#Дистанция до угрозы
for distObj in spo15lampDist:
#if distObj in scene.objects:
if int(distObj.split("SPO-15Lamp")[1].split("km")[0])*1000 < bge.logic.globalDict['SPODATA'][0]:
scene.objects[distObj].visible = 1
#print(scene.objects[distObj].visible)
elif int(distObj.split("SPO-15Lamp")[1].split("km")[0])*1000 > bge.logic.globalDict['SPODATA'][0]:
scene.objects[distObj].visible = 0
#При обнулении угрозы все лампы выключаются
else:
scene.objects["SPO-15alarm"].visible = 0
scene.objects["SPO-15alarmDown"].visible = 0
scene.objects["SPO-15alarmUp"].visible = 0
for obj in spo15lampGrad:
scene.objects[obj].visible = 0
for obj in spo15lampGreen:
scene.objects[obj].visible = 0
for obj in spo15lampDist:
scene.objects[obj].visible = 0
for obj in spo15typeThreat:
scene.objects[obj].visible = 0
Ободренный успехом с СПО-15, я принялся за ИЛС. В сущности, досточно стандартный набор вращений, замены мешей и так далее.
Вот только элементов много. Для цифр со сменой мешей пришлось ввести ограничение по исполнению - раз в 19 тиков, чтобы не утруждать БГЕ.
Из нововведений отмечу отклонение вверх вниз в некотором диапазоне указателя тангажа на ИЛС относительно линии горизонта, что показывает, вверх или вниз отклонен нос самолета. Кроме того рядом с линией горизонта на ИЛС появился цифровой указатель тангажа, замеряющий оный в пределах от минус до плюс 15 градусов. Также был введен более реалистичный монитор радара. По сути - это дубль ИЛС с индикатором крена и бегающей по экрану меткой цели. Круговой радар я делать непосредственно в кабинах не буду - нет смысла. Хватит и карты обстановки (которую тоже надо делать).
В итоге Ф-15 стали уверенно поражаться ракетами Р-27Р, СПО весело мигает лампочками и начинает орать при малейшем поводе, цифры на ИЛС мелькают, стрелочки крутятся, пушка тарахтит, ловушки отстреливаются с шипением и дымом...
Как общий результат - получена вторая более менее работоспособная миссия, отреставрирован МиГ-29 и не только он, изничтожено некоторое количество багов и получен задел на будущее. Дело в том, что СПО-15 стоит на МиГ-23МЛД, Су-33, Су-27. Су-25, Су-17М4, МиГ-27М/Д/К, а ИЛС МиГ-29 идентична ИЛС Су-27 и части его модификаций, вроде того же Су-33...
Дело в том, что Блендер начал ругаться на потерю способа компрессии dds, как я это понял из сообщений консоли. По совету Андрея (aka dron) я применил компрессию типа dxt1 после установки аддона для dds в ГИМПе, причем конверитровал картинки типа png. Пока ругань консоли ограничивается моими ошибками в коде, что радует. В сущности, кабина МиГ-29 особо не изменилась, если смотреть на текстуры. А вот ИЛС, работа приборов и СПО претерпели некоторые изменения. Особенно много возни было с системой предупреждения об облучении СПО-15. В отличие от СПО-10 в ней на порядок больше ламп и гореть должны только нужные.Первая версия СПО-15 двухлетней давности, если мнен не изменяет память, была мною здесь выложена, она длинная и выполнена методом "против лома нет приема" с помощью "дао дятла" - методичное построчное перебирание ламп, пусть и с некоторыми исключениями части кода с помощью условий. Меня не радовала перспектива повторить сей подвиг, тем более, что вводные данные изменились и перебирать строчки в поисках ненужных - да ну на фиг...
Вместо этого я обратился к спискам и сравнению списков. Я разбил имена объектов или сами объекты по спискам, к примеру лампы дистанции до угрозы, лампы вектора на угрозу, и тд. Некоторые списки содержат в именах объектв для сравнения например LampThreat60km. смотрим на последние символы в названии (в действительности оно немного другное, но суть та же). Режем имя методом split, чтобы "вышелушить" число 60. Чтобы строку превратить в число применяем int и умножаем на 1000. Все. Если в данных дистанция до угрозы больше 60000, зажигаем лампу с этим названием, если меньше - гасим.
С вектором на угрозу пришлось поступить хитрее. Кроме списка ламп для индикации вектора на угрозу был создан список,э-э, секторов угрозы вида [[-0.1,0.1],[-0.5,0.5]],[опять цифры во вложенном списке]. Список содержит примерно 10 элементов, в которых есть два вложенных списка - это вектор на угрозу справа и слева и вектор на угрозу спереди и сзади. На входе получается вектор на угрозу и проверяется на "укладывание" в некоторые условия, заданные этим списком с квадратными скобочками. Если данные вектора ПОЛНОСТЬЮ соответствуют вложенным спискам, то лампа горит, иначе - гаснет А прикол в том, что список секторов угрозы по последовательности соответствует списку лампочек. Все делает цикл. Ламп примерно дюжина, так что БГЕ несильно напрягается, если учесть, что СПО работает раз в пару секунд. В итоге код резко "съежился".
А теперь код для СПО-15. На лишние списки внимания не обращать - они для других функций.
import bge
import random
import mathutils
import CONTROL_gamer
A_X = 0
#Далее идет блок клавиатурных команд
keyboard = bge.logic.keyboard
JUST_ACTIVATED = bge.logic.KX_INPUT_JUST_ACTIVATED
JUST_RELEASED = bge.logic.KX_INPUT_JUST_RELEASED
INPUT_ACTIVE = bge.logic.KX_INPUT_ACTIVE
scene = bge.logic.getCurrentScene()
sceneCockpit = scene
pitchListDigital = [scene.objects["pitchILS0"],
scene.objects["pitchILS1"]]
spo15lampGrad = ["SPO-15grad10R","SPO-15grad30R","SPO-15grad50R","SPO-15grad90R",
"SPO-15grad10L","SPO-15grad30L","SPO-15grad50L","SPO-15grad90L",
"SPO-15LampLzps","SPO-15LampRzps","SPO-15PPS"]
spo15lampGreen = ["SPO-15green10R","SPO-15green30R","SPO-15green50R","SPO-15green90R",
"SPO-15green10L","SPO-15green30L","SPO-15green50L","SPO-15green90L",
"SPO-15greenLzps","SPO-15greenRzps","SPO-15PPS"]
spo15Grad = [[[0.01, 0.1],[0.0, 1.1]],[[0.1, 0.3],[0.0, 1.1]],[[0.3, 0.55],[0.0, 1.1]],[[0.55, 1.0],[0.0, 1.1]],
[[-0.1, -0.01],[0.0, 1.1]],[[-0.3, -0.1],[0.0, 1.1]],[[-0.55, -0.3],[0.0, 1.1]],[[-1.0, -0.55],[0.0, 1.1]],
[[-1.0, 0.0],[-1.1, 0.0]],[[0.0, 1.0],[-1.1, 0.0]],[[-0.01, 0.01],[0.0, 1.1]]]
spo15lampDist = ["SPO-15Lamp65km","SPO-15Lamp60km","SPO-15Lamp55km","SPO-15Lamp50km",
"SPO-15Lamp45km","SPO-15Lamp40km","SPO-15Lamp35km","SPO-15Lamp30km",
"SPO-15Lamp25km","SPO-15Lamp20km","SPO-15Lamp15km","SPO-15Lamp10km",
"SPO-15Lamp5km","SPO-15Lamp1km"]
spo15typeThreat = ["SPO-15AirObj","SPO-15ZRKBD","SPO-15ZRKSD","SPO-15ZRKMD","SPO-15DRLOW","SPO-15DRLOZ"]
textFuel = [scene.objects["fuel0"],
scene.objects["fuel1"],
scene.objects["fuel2"],
scene.objects["fuel3"]]
textSpeedTarget = [scene.objects["targetSpeed0"],
scene.objects["targetSpeed1"],
scene.objects["targetSpeed2"],
scene.objects["targetSpeed3"]]
textHeightTarget = [scene.objects["targetHeight0"],
scene.objects["targetHeight1"],
scene.objects["targetHeight2"],
scene.objects["targetHeight3"],
scene.objects["targetHeight4"]]
textSpeedOwn = [scene.objects["ownSpeed0"],
scene.objects["ownSpeed1"],
scene.objects["ownSpeed2"],
scene.objects["ownSpeed3"]]
textHeightOwn = [scene.objects["ownHeight0"],
scene.objects["ownHeight1"],
scene.objects["ownHeight2"],
scene.objects["ownHeight3"],
scene.objects["ownHeight4"]]
def spo15(own):
"""
bge.logic.globalDict['SPODATA'][0] = own.getDistanceTo(threat)
bge.logic.globalDict['SPODATA'][1] = threat.LockOn
bge.logic.globalDict['SPODATA'][2] = threat.PR
bge.logic.globalDict['SPODATA'][3] = threat.avto
bge.logic.globalDict['SPODATA'][4] = own.worldPosition[2] - threat.worldPosition[2]
bge.logic.globalDict['SPODATA'][5] = own.getVectTo(threat)[2][0]
bge.logic.globalDict['SPODATA'][6] = own.getVectTo(threat)[2][1]
bge.logic.globalDict['SPODATA'][7] = threat.unitName
bge.logic.globalDict['SPODATA'][8] = threat.subTypeUnit
"""
if bge.logic.globalDict['SPODATA'] != [0.0, 0, 0, 0, 0.0, 0.0, 0.0, "", ""]:
for element in spo15Grad:
#print(bge.logic.globalDict['SPODATA'][5],bge.logic.globalDict['SPODATA'][6])
if element[0][0] < bge.logic.globalDict['SPODATA'][5] < element[0][1] and element[1][0] < bge.logic.globalDict['SPODATA'][6] < element[1][1]:
scene.objects[spo15lampGrad[spo15Grad.index(element)]].visible = 1
if bge.logic.globalDict['SPODATA'][2] == 1:
scene.objects[spo15lampGreen[spo15Grad.index(element)]].visible = 1
else:
scene.objects[spo15lampGreen[spo15Grad.index(element)]].visible = 0
else:
scene.objects[spo15lampGreen[spo15Grad.index(element)]].visible = 0
scene.objects[spo15lampGrad[spo15Grad.index(element)]].visible = 0
CONTROL_gamer.SPOaudio()
#Распознавание типа угрозы
for typeThreat in spo15typeThreat:
if bge.logic.globalDict['SPODATA'][8] in typeThreat:
scene.objects[typeThreat].visible = 1
else:
scene.objects[typeThreat].visible = 0
if bge.logic.globalDict['SPODATA'][1] == 1:
scene.objects["SPO-15alarm"].visible = 1
if bge.logic.globalDict['SPODATA'][4] > 0:
scene.objects["SPO-15alarmUp"].visible = 1
scene.objects["SPO-15alarmDown"].visible = 0
else:
scene.objects["SPO-15alarmUp"].visible = 0
scene.objects["SPO-15alarmDown"].visible = 1
else:
scene.objects["SPO-15alarm"].visible = 0
scene.objects["SPO-15alarmDown"].visible = 0
scene.objects["SPO-15alarmUp"].visible = 0
#Дистанция до угрозы
for distObj in spo15lampDist:
#if distObj in scene.objects:
if int(distObj.split("SPO-15Lamp")[1].split("km")[0])*1000 < bge.logic.globalDict['SPODATA'][0]:
scene.objects[distObj].visible = 1
#print(scene.objects[distObj].visible)
elif int(distObj.split("SPO-15Lamp")[1].split("km")[0])*1000 > bge.logic.globalDict['SPODATA'][0]:
scene.objects[distObj].visible = 0
#При обнулении угрозы все лампы выключаются
else:
scene.objects["SPO-15alarm"].visible = 0
scene.objects["SPO-15alarmDown"].visible = 0
scene.objects["SPO-15alarmUp"].visible = 0
for obj in spo15lampGrad:
scene.objects[obj].visible = 0
for obj in spo15lampGreen:
scene.objects[obj].visible = 0
for obj in spo15lampDist:
scene.objects[obj].visible = 0
for obj in spo15typeThreat:
scene.objects[obj].visible = 0
Ободренный успехом с СПО-15, я принялся за ИЛС. В сущности, досточно стандартный набор вращений, замены мешей и так далее.
Вот только элементов много. Для цифр со сменой мешей пришлось ввести ограничение по исполнению - раз в 19 тиков, чтобы не утруждать БГЕ.
Из нововведений отмечу отклонение вверх вниз в некотором диапазоне указателя тангажа на ИЛС относительно линии горизонта, что показывает, вверх или вниз отклонен нос самолета. Кроме того рядом с линией горизонта на ИЛС появился цифровой указатель тангажа, замеряющий оный в пределах от минус до плюс 15 градусов. Также был введен более реалистичный монитор радара. По сути - это дубль ИЛС с индикатором крена и бегающей по экрану меткой цели. Круговой радар я делать непосредственно в кабинах не буду - нет смысла. Хватит и карты обстановки (которую тоже надо делать).
В итоге Ф-15 стали уверенно поражаться ракетами Р-27Р, СПО весело мигает лампочками и начинает орать при малейшем поводе, цифры на ИЛС мелькают, стрелочки крутятся, пушка тарахтит, ловушки отстреливаются с шипением и дымом...
Как общий результат - получена вторая более менее работоспособная миссия, отреставрирован МиГ-29 и не только он, изничтожено некоторое количество багов и получен задел на будущее. Дело в том, что СПО-15 стоит на МиГ-23МЛД, Су-33, Су-27. Су-25, Су-17М4, МиГ-27М/Д/К, а ИЛС МиГ-29 идентична ИЛС Су-27 и части его модификаций, вроде того же Су-33...