Чтение учебной литературы по разным темам отнимает много времени, но работа над проектом все ще продолжается, хотя и непонятно, чем все это закончится и закончится ли вообще. Но и сидеть, ничего не делая, тоже неохота.
Недавно отработал самонаведение ракеты в Unity, отыскал аналогичный урок для UE4, провел массовое обновление ПО - Юнити и UE4, плюс VisualStudio, обновил Блендер несколько раз, пробовал UPBGE для EEVEE. Увы, для последнего альфа сборка - это альфа и есть. Категорически не хочет работать подгрузка бленд-файлов через LibLoad - UPBGE мгновенно вылетает. Смотрел и Armory3D, но толком не занимался. Просмотрел и прослушал курсы по Блендеру от А. Слаквы, для Блендер 2.8, пытаюсь в нем работать - с непривычки тяжело.
Есть мысли по поводу упрощения и сокращения проектов в Юнити и БГЕ, касающиеся прежде всего моделей оружия и их json файлов. Если вкратце - стоит провести объединение в одном файле вариантов подвески для ракет однотипного семейства, например AIM-120, AIM-7, Р-3/13, Р-23/24, Р-27 и так далее. Все дело в том, что для нескольких файлов json имеются одинаковые координаты и углы поворота ракет для подвески, отличаются они лишь наименованиями самих ракет - всего-то пара слов, даже не строчек. Поэтому имеет смысл просто перечислить в отдельной строке меши ракет, которые надо найти для подгрузки, а вместо названий ракет в словах проставить missileStr, а не R-23R, которые будут указаны выше.
{
"objList":["R-23R", "R-23T", "R-24R", "R-24T", "R-24RM"],
"obves":{"FLG_APU23_|":{"parentObj":"CntAircraft","locObj":[0.0,0.0,0.0],"rotObj":[0.0,0.0,0.0]},
"missileStr|1":{"parentObj":"CntAircraft","locObj":[-1.428,-2.0,0.03],"rotObj":[-0.035,0.0,0.0],"weapon":1,"CatapultSbros":0},
"missileStr|2":{"parentObj":"CntAircraft","locObj":[1.428,-2.0,0.03],"rotObj":[-0.035,0.0,0.0],"weapon":1,"CatapultSbros":0}
}
}
Поскольку у меня отлажена система поиска файлов с разным расширением, то поисковик-скрипт отыщет и подгрузит все нужное. А вместо пяти файлов для ракет можно получить один. Это для Р-23 и Р-24, а для aIM-120 вместо 8 будет 1 и для "Спэрроу" вместо 12 - 1, столько же для "Сайдуиндеров"...
Есть еще один нюанс. Для ракет типа "Спэрроу" и "АМРААМ модели внешне почти неотличимы или совсем неотличимы, поэтому в файле ТТХ ракеты надо просто перечислить названия моделей ракет например Sparrow_II и скоратить число блендов. А сами ТТХ ракет объединить в json - поисковик все найдет...
Но все это по ракетам, а есть еще ландшафт. Тут тоже есть новые задумки. Ландшафт разбивается на квадраты типа А1, Б4 и так далее. Все эти квадраты упакованы в отдельные бленды, и снабжены json с перечислениями стоящих на них объектов. В зависимости от положения активной камеры сначала грузятся стартовый квадрат и 8 квадратов вокруг него. В адльнейшем идет отслеживание положения камеры и "догрузка", если надо, но происходить это будет редко. Фактически, выбирается один квадрат, что-то вроде "центра мира" и вокруг него выстраивается "периферия". Но и это еще не все. Новый "центр мира" "оттаскивается" в нулевое исходное положение, вместе с ним на ту же величину переносятся и ранее сгенеренные "квадраты" со всем их содержимым. Плюс юниты игры также сменяют сове положение на величину "единицы" ландшафта. А создавалась эта система с прицелом на Юнити. Большой ландшафт единым кусокм делать неудобно, плюс говорилось, что координаты больше 100 тысяч единипц приводят к некорректной работе и тормозам, значит, надо уменьшать масштаб самих юнитов, ну раз в 10. Тогда надо учесть, что и их скорости и величина ускорения свободного падения и размеры статических объектов (деревья, здания, дороги) надо также отмасшатбировать, уменьшив в 10 раз.
Возвращаясь к ландшафтуи отрабатываемой сейчас системой его "постройки", скажу, что с "передвиганиями" юнитов, по идее, должно получиться "удерживать" юнит игрока внутри некоторого предела, да и остальные юниты, в общем-то тоже.
Чкрипт на данный момент:
import bge
scene = bge.logic.getCurrentScene()
cont = bge.logic.getCurrentController()
own = cont.owner
bge.logic.globalDict["nameBlock"] = "D4"
scaleBlock = 2.5
#Конфигурация расположения блоков террайна - вложенные списки
configBlock = [
["A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8"],
["B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8"],
["C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8"],
["D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8"],
["E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8"],
["F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8"],
["G1", "G2", "G3", "G4", "G5", "G6", "G7", "G8"],
["H1", "H2", "H3", "H4", "H5", "H6", "H7", "H8"]
]
def BlockTerrain():
cont = bge.logic.getCurrentController()
own = cont.owner
#Индексы списка блоков - внешний и вложенный
x = 0
y = 0
#Величина перемещения блоков и их направление
posX = 0.0
posY = 0.0
nameBlock = bge.logic.globalDict["nameBlock"]
#Список элементов, содержащих информацию о блоках и их смещении при появлении
listIndex = []
#Список уже имеющихся блоков террайна
terrainList = []
#Сначала ищем в общем списке вложенный с наименованием "центра", вокруг которого
# выстраиваются еще 8 дополнительных блоков террайна
for listObj in configBlock:
for obj in listObj:
#После нахождения "центра мира" в списке блоков внутри общего списка блоков террайна
if nameBlock == obj:
#Заносим его в список индексов, это обязательно, смещение для "центра" нулевое
listIndex.append( str( configBlock.index(listObj) ) + "_" + str( listObj.index(obj) ) + "|" + "0.0" + "_" + "0.0" )
#Загоняем в список блоки "перед" и "позади" "центра мира", учитывая пределы индексов списка
if listObj.index(obj)-1 > -1:
listIndex.append( str( configBlock.index(listObj) ) + "_" + str( listObj.index(obj)-1 ) + "|" + "0.0" + "_" + str(-scaleBlock) )
if listObj.index(obj)+1 < len(listObj):
listIndex.append( str( configBlock.index(listObj) ) + "_" + str( listObj.index(obj)+1 ) + "|" + "0.0" + "_" + str(scaleBlock) )
#А теперь осматриваем вложенные списки "выше" и "ниже" найденного, опять учитываем пределы индексов
#Если такие списки есть, то заносим в listIndex информацию о блоках с индеками "центра мира" и плюс-минус 1
if configBlock.index(listObj)-1 > -1:
listIndex.append( str( configBlock.index(listObj)-1 ) + "_" + str( listObj.index(obj) ) + "|" + str(scaleBlock) + "_" + "0.0" )
if listObj.index(obj)-1 > -1:
listIndex.append( str( configBlock.index(listObj)-1 ) + "_" + str( listObj.index(obj)-1 ) + "|" + str(scaleBlock) + "_" + str(-scaleBlock) )
if listObj.index(obj)+1 < len(listObj):
listIndex.append( str( configBlock.index(listObj)-1 ) + "_" + str( listObj.index(obj)+1 ) + "|" + str(scaleBlock) + "_" + str(scaleBlock) )
if configBlock.index(listObj)+1 < len(configBlock):
listIndex.append( str( configBlock.index(listObj)+1 ) + "_" + str( listObj.index(obj) ) + "|" + str(-scaleBlock) + "_" + "0.0" )
if listObj.index(obj)-1 > -1:
listIndex.append( str( configBlock.index(listObj)+1 ) + "_" + str( listObj.index(obj)-1 ) + "|" + str(-scaleBlock) + "_" + str(-scaleBlock) )
if listObj.index(obj)+1 < len(listObj):
listIndex.append( str( configBlock.index(listObj)+1 ) + "_" + str( listObj.index(obj)+1 ) + "|" + str(-scaleBlock) + "_" + str(scaleBlock) )
#Проверка на нличие блоков террайна в сцене
for obj in scene.objects:
if "Terrain" in obj.name:
terrainList.append(obj.name)
#По окончании составления списка препарируем каждый его элемент типа 3_2|2.5_-2.5
for element in listIndex:
#Перед "|" указаны индексы общего списка и вложенного списка, они дают выход на элемент "D3" в данном случае
x = int( element.split("|")[0].split("_")[0] )
y = int( element.split("|")[0].split("_")[1] )
if "TerrainQuad_" + configBlock[x][y] not in terrainList:
#Добавляем блок террайна и препарируем элементы после "|"
BlockTerrain = scene.addObject("TerrainQuad_" + configBlock[x][y], own)
#Получаем смещение ОТНОСИТЕЛЬНО "ЦЕНТРАЛЬНОГО" блока, весь отсчет идет относительно него
posX = float( element.split("|")[1].split("_")[1] )
posY = float( element.split("|")[1].split("_")[0] )
#Смещаем только что добавленный блок и переходим к следующему - и так до конца списка
BlockTerrain.worldPosition[0] += posX
BlockTerrain.worldPosition[1] += posY
def control():
cont = bge.logic.getCurrentController()
own = cont.owner
cam = scene.objects["Camera"]
deltaX = 0.0
deltaY = 0.0
nameBlock = ""
if cam.worldPosition[0] < -scaleBlock or cam.worldPosition[1] < -scaleBlock or cam.worldPosition[1] > scaleBlock or cam.worldPosition[0] > scaleBlock:
if cam.worldPosition[0] < -scaleBlock:
deltaX = -scaleBlock
elif cam.worldPosition[0] > scaleBlock:
deltaX = scaleBlock
elif cam.worldPosition[1] < -scaleBlock:
deltaY = -scaleBlock
elif cam.worldPosition[1] > scaleBlock:
deltaY = scaleBlock
for obj in scene.objects:
if "Terrain" in obj.name:
obj.worldPosition[0] -= deltaX
obj.worldPosition[1] -= deltaY
if -scaleBlock * 0.1 < obj.worldPosition[0] < scaleBlock * 0.1 and -scaleBlock * 0.1 < obj.worldPosition[1] < scaleBlock * 0.1:
bge.logic.globalDict["nameBlock"] = obj.name.split("_")[1]
cam.worldPosition[0] -= deltaX
cam.worldPosition[1] -= deltaY
BlockTerrain()
#Первый стартовый запуск функции генерации и расстановки блоков террайна
BlockTerrain()
Недавно отработал самонаведение ракеты в Unity, отыскал аналогичный урок для UE4, провел массовое обновление ПО - Юнити и UE4, плюс VisualStudio, обновил Блендер несколько раз, пробовал UPBGE для EEVEE. Увы, для последнего альфа сборка - это альфа и есть. Категорически не хочет работать подгрузка бленд-файлов через LibLoad - UPBGE мгновенно вылетает. Смотрел и Armory3D, но толком не занимался. Просмотрел и прослушал курсы по Блендеру от А. Слаквы, для Блендер 2.8, пытаюсь в нем работать - с непривычки тяжело.
Есть мысли по поводу упрощения и сокращения проектов в Юнити и БГЕ, касающиеся прежде всего моделей оружия и их json файлов. Если вкратце - стоит провести объединение в одном файле вариантов подвески для ракет однотипного семейства, например AIM-120, AIM-7, Р-3/13, Р-23/24, Р-27 и так далее. Все дело в том, что для нескольких файлов json имеются одинаковые координаты и углы поворота ракет для подвески, отличаются они лишь наименованиями самих ракет - всего-то пара слов, даже не строчек. Поэтому имеет смысл просто перечислить в отдельной строке меши ракет, которые надо найти для подгрузки, а вместо названий ракет в словах проставить missileStr, а не R-23R, которые будут указаны выше.
{
"objList":["R-23R", "R-23T", "R-24R", "R-24T", "R-24RM"],
"obves":{"FLG_APU23_|":{"parentObj":"CntAircraft","locObj":[0.0,0.0,0.0],"rotObj":[0.0,0.0,0.0]},
"missileStr|1":{"parentObj":"CntAircraft","locObj":[-1.428,-2.0,0.03],"rotObj":[-0.035,0.0,0.0],"weapon":1,"CatapultSbros":0},
"missileStr|2":{"parentObj":"CntAircraft","locObj":[1.428,-2.0,0.03],"rotObj":[-0.035,0.0,0.0],"weapon":1,"CatapultSbros":0}
}
}
Поскольку у меня отлажена система поиска файлов с разным расширением, то поисковик-скрипт отыщет и подгрузит все нужное. А вместо пяти файлов для ракет можно получить один. Это для Р-23 и Р-24, а для aIM-120 вместо 8 будет 1 и для "Спэрроу" вместо 12 - 1, столько же для "Сайдуиндеров"...
Есть еще один нюанс. Для ракет типа "Спэрроу" и "АМРААМ модели внешне почти неотличимы или совсем неотличимы, поэтому в файле ТТХ ракеты надо просто перечислить названия моделей ракет например Sparrow_II и скоратить число блендов. А сами ТТХ ракет объединить в json - поисковик все найдет...
Но все это по ракетам, а есть еще ландшафт. Тут тоже есть новые задумки. Ландшафт разбивается на квадраты типа А1, Б4 и так далее. Все эти квадраты упакованы в отдельные бленды, и снабжены json с перечислениями стоящих на них объектов. В зависимости от положения активной камеры сначала грузятся стартовый квадрат и 8 квадратов вокруг него. В адльнейшем идет отслеживание положения камеры и "догрузка", если надо, но происходить это будет редко. Фактически, выбирается один квадрат, что-то вроде "центра мира" и вокруг него выстраивается "периферия". Но и это еще не все. Новый "центр мира" "оттаскивается" в нулевое исходное положение, вместе с ним на ту же величину переносятся и ранее сгенеренные "квадраты" со всем их содержимым. Плюс юниты игры также сменяют сове положение на величину "единицы" ландшафта. А создавалась эта система с прицелом на Юнити. Большой ландшафт единым кусокм делать неудобно, плюс говорилось, что координаты больше 100 тысяч единипц приводят к некорректной работе и тормозам, значит, надо уменьшать масштаб самих юнитов, ну раз в 10. Тогда надо учесть, что и их скорости и величина ускорения свободного падения и размеры статических объектов (деревья, здания, дороги) надо также отмасшатбировать, уменьшив в 10 раз.
Возвращаясь к ландшафтуи отрабатываемой сейчас системой его "постройки", скажу, что с "передвиганиями" юнитов, по идее, должно получиться "удерживать" юнит игрока внутри некоторого предела, да и остальные юниты, в общем-то тоже.
Чкрипт на данный момент:
import bge
scene = bge.logic.getCurrentScene()
cont = bge.logic.getCurrentController()
own = cont.owner
bge.logic.globalDict["nameBlock"] = "D4"
scaleBlock = 2.5
#Конфигурация расположения блоков террайна - вложенные списки
configBlock = [
["A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8"],
["B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8"],
["C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8"],
["D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8"],
["E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8"],
["F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8"],
["G1", "G2", "G3", "G4", "G5", "G6", "G7", "G8"],
["H1", "H2", "H3", "H4", "H5", "H6", "H7", "H8"]
]
def BlockTerrain():
cont = bge.logic.getCurrentController()
own = cont.owner
#Индексы списка блоков - внешний и вложенный
x = 0
y = 0
#Величина перемещения блоков и их направление
posX = 0.0
posY = 0.0
nameBlock = bge.logic.globalDict["nameBlock"]
#Список элементов, содержащих информацию о блоках и их смещении при появлении
listIndex = []
#Список уже имеющихся блоков террайна
terrainList = []
#Сначала ищем в общем списке вложенный с наименованием "центра", вокруг которого
# выстраиваются еще 8 дополнительных блоков террайна
for listObj in configBlock:
for obj in listObj:
#После нахождения "центра мира" в списке блоков внутри общего списка блоков террайна
if nameBlock == obj:
#Заносим его в список индексов, это обязательно, смещение для "центра" нулевое
listIndex.append( str( configBlock.index(listObj) ) + "_" + str( listObj.index(obj) ) + "|" + "0.0" + "_" + "0.0" )
#Загоняем в список блоки "перед" и "позади" "центра мира", учитывая пределы индексов списка
if listObj.index(obj)-1 > -1:
listIndex.append( str( configBlock.index(listObj) ) + "_" + str( listObj.index(obj)-1 ) + "|" + "0.0" + "_" + str(-scaleBlock) )
if listObj.index(obj)+1 < len(listObj):
listIndex.append( str( configBlock.index(listObj) ) + "_" + str( listObj.index(obj)+1 ) + "|" + "0.0" + "_" + str(scaleBlock) )
#А теперь осматриваем вложенные списки "выше" и "ниже" найденного, опять учитываем пределы индексов
#Если такие списки есть, то заносим в listIndex информацию о блоках с индеками "центра мира" и плюс-минус 1
if configBlock.index(listObj)-1 > -1:
listIndex.append( str( configBlock.index(listObj)-1 ) + "_" + str( listObj.index(obj) ) + "|" + str(scaleBlock) + "_" + "0.0" )
if listObj.index(obj)-1 > -1:
listIndex.append( str( configBlock.index(listObj)-1 ) + "_" + str( listObj.index(obj)-1 ) + "|" + str(scaleBlock) + "_" + str(-scaleBlock) )
if listObj.index(obj)+1 < len(listObj):
listIndex.append( str( configBlock.index(listObj)-1 ) + "_" + str( listObj.index(obj)+1 ) + "|" + str(scaleBlock) + "_" + str(scaleBlock) )
if configBlock.index(listObj)+1 < len(configBlock):
listIndex.append( str( configBlock.index(listObj)+1 ) + "_" + str( listObj.index(obj) ) + "|" + str(-scaleBlock) + "_" + "0.0" )
if listObj.index(obj)-1 > -1:
listIndex.append( str( configBlock.index(listObj)+1 ) + "_" + str( listObj.index(obj)-1 ) + "|" + str(-scaleBlock) + "_" + str(-scaleBlock) )
if listObj.index(obj)+1 < len(listObj):
listIndex.append( str( configBlock.index(listObj)+1 ) + "_" + str( listObj.index(obj)+1 ) + "|" + str(-scaleBlock) + "_" + str(scaleBlock) )
#Проверка на нличие блоков террайна в сцене
for obj in scene.objects:
if "Terrain" in obj.name:
terrainList.append(obj.name)
#По окончании составления списка препарируем каждый его элемент типа 3_2|2.5_-2.5
for element in listIndex:
#Перед "|" указаны индексы общего списка и вложенного списка, они дают выход на элемент "D3" в данном случае
x = int( element.split("|")[0].split("_")[0] )
y = int( element.split("|")[0].split("_")[1] )
if "TerrainQuad_" + configBlock[x][y] not in terrainList:
#Добавляем блок террайна и препарируем элементы после "|"
BlockTerrain = scene.addObject("TerrainQuad_" + configBlock[x][y], own)
#Получаем смещение ОТНОСИТЕЛЬНО "ЦЕНТРАЛЬНОГО" блока, весь отсчет идет относительно него
posX = float( element.split("|")[1].split("_")[1] )
posY = float( element.split("|")[1].split("_")[0] )
#Смещаем только что добавленный блок и переходим к следующему - и так до конца списка
BlockTerrain.worldPosition[0] += posX
BlockTerrain.worldPosition[1] += posY
def control():
cont = bge.logic.getCurrentController()
own = cont.owner
cam = scene.objects["Camera"]
deltaX = 0.0
deltaY = 0.0
nameBlock = ""
if cam.worldPosition[0] < -scaleBlock or cam.worldPosition[1] < -scaleBlock or cam.worldPosition[1] > scaleBlock or cam.worldPosition[0] > scaleBlock:
if cam.worldPosition[0] < -scaleBlock:
deltaX = -scaleBlock
elif cam.worldPosition[0] > scaleBlock:
deltaX = scaleBlock
elif cam.worldPosition[1] < -scaleBlock:
deltaY = -scaleBlock
elif cam.worldPosition[1] > scaleBlock:
deltaY = scaleBlock
for obj in scene.objects:
if "Terrain" in obj.name:
obj.worldPosition[0] -= deltaX
obj.worldPosition[1] -= deltaY
if -scaleBlock * 0.1 < obj.worldPosition[0] < scaleBlock * 0.1 and -scaleBlock * 0.1 < obj.worldPosition[1] < scaleBlock * 0.1:
bge.logic.globalDict["nameBlock"] = obj.name.split("_")[1]
cam.worldPosition[0] -= deltaX
cam.worldPosition[1] -= deltaY
BlockTerrain()
#Первый стартовый запуск функции генерации и расстановки блоков террайна
BlockTerrain()
Думаю, комментарии делают этот код понятным... Надеюсь, во всяком случае. )))
Сам же террайн в БГЕ (или УПБГЕ, когда его отладят) планируется рскрасить по способу denis8424 - с разделением материалов по высоте, но с одним дополнением. Для каждого блока террайна провести смешивание текстур через маски, правда, это уж как получится. Там надо большое разрешение масок, все же даже масштабированные блоки - это 10 км, но можно попробовать маски при наложении дублировать - при больших размерах повторяемость не будет сильно бросаться в глаза, плюс для разных блоков маски будут разными, а число блоков в сумме - не слишком велико, вряд ли больше 100 (уж точно не 2500).