Лучшее - враг хорошего. Иногда это утверждение верно, иногда - нет. Вышедший недавно blender 2.77a заставил меня предположить, что если в названии версии уже присутствует буква, то ее можно юзать и радоваться улучшениям. Увы, мои предположения оказались несколько наивными и преувеличенными. Меня ожидал мощный облом там, где я этого совсем не ждал (каламбурчик, однако). Не далее как пару постов назад я писал о "Великой анимационной революции" и разливался соловьем насчет плавности работы как анимации, так и физики. Новая версия мои ожидания обломала и весьма жестко.
Прикол заключается в новом толковании строчки obj.playAnimation(spisok). Длинный список аргументов этой функции я приводить не буду, скажу только, что строчки я переделывал в соответствии с новыми правилами, аргументов там стало 12, а 1, как написано в новом API 2.77. Но анимации не работают, как положено. Они отражают лишь начальный и конечный кадр. А у меня эти кадры задаются значением проперти. Хоть ты тресни - крыло 2перескакивает" с первого на 200-ый кадр по завершении изменения проперти, аналогично с 201 на 400 и обратно. И вообще все анимации перестали понимать эту строчку с playAction.
Сначала я грешил на анимацию, созданную в 2.75, однако, созданный мною ради эксперимента файл с анимациями "чисто" в 2.77 показал тот же самый результат. А еще один прикол заключается в том, что если я задействую актуатор Action и в нем проставлю анимацию изменением проперти, то все работает!
Можно, конечно, придать всем объектам этот самый актуатор, но для этого им надо еще добавить проперти и логику. Объектов не сказать, чтобы много, но сама мысль о том, что придется вводить логику там, где без логических кирпичей можно прекрасно обойтись (было, скажем так, возможно обойтись) восторга у меня не вызывает. Если кто-нибудь читает эти строчки и хорошо знает английский, то пусть попробует на своем компе проделать этот фокус с анимацией - логическим блоком и скриптом. И если у вас получится такой же облом с командой playAction, отпишите багрепорт на сайт разработчиков. У меня сейчас запарка и просто нет времени.
А времени у меня нет еще по той причине, что польстившись на 2.77а и прочитав, что поддержка Виндовс ХР более не работает, поставил Виндовс 7. Хотя отношение у меня к этой и более поздним версиям Винды неоднозначное. Кроме того, думаю все-таки поставить рядом с виндой и Линукс. Сначала, правда, придется затвердить правила установки рядом с Виндовс - есть несколько хорших статей на эту тему, а потом еще надо выяснить, сколько трафика у меня осталось на Мегафоне, потому как Линукс с Билайном не дружат. Плюс проверить версию Линукса в работе, потому что версия 12.04 люто била по глазам - вроде бы и работала, но монитор "мигал" каждые 10 секунд. Тогда-то меня и остановило это обстоятельство. В прошлом году я на всякий случай скачал 14.04 и проверил ее, не устанавливая, запуском с DVD - экран не мигал, Мегафон работал, что порадовало. Однако тогда еще вовсю работала ХР, да и рассчитывал я на установку нового винчестера. Однако грянувший могучий ремонт дворовых объектов и самого дома несколько поумерил аппетиты, да еще впереди еще кое-какие дела, так что пока неясно с этим винчестером. Но учиненный мною погром с установкой "семерки" привел к тому, что откладывать установку Линукса вроде как уже неудобно - диск порядком очищен от старых файлов, места полно, вирусня еще набежать не успела - надо решаться. что плохо - не удается пока восстановить джаббер.
Тем временем, несмотря на столь резкий поворот событий, проект все же продолжает свое движение вперед. Был сделан скриншотер экрана. Вообще-то он был и в первой версии, но этот - совершеннее. Его новшество в том, что теперь сохраняются скрины старых сеансов игры, раньше каждый новоый запуск игры и фотографирование процесса на мониторе приводило у ничтожению старых скринов. Это не есть хорошо, и эту проблему, немного повозившись, я решил.
Кусок кода:
#Скриншот экрана
if key == bge.events.F12KEY:
#Открываем текстовый файл и смотрим номер последнего снимка
screenNull = open(bge.logic.expandPath('////Screenshot/screen.txt'),'r')
kadrNull = screenNull.read()
#Увеличиваем номер на 1 и закрываем файл
kadrNew = int(kadrNull) + 1
screenNull.close()
#составляем новое имя для нового снимка
indexScreen = 'BlendSim' + str(kadrNew)
#Делаем снимок и отправляем в папку
bge.render.makeScreenshot("//ScreenShot/" + indexScreen)
#А теперь опять открываем текстовый файл с номером снимка и пишем туда уже номер нового скрина
kadrWrite = open(bge.logic.expandPath('//Screenshot/screen.txt'),'w')
kadrWrite.write(str(kadrNew))
#Опять закрываем файл
kadrWrite.close()
В папке со скриншотами находится текстовый файл. в нем записано число. Это число предыдущего снимка - если угодно - число последнего срабатывания скриншотера. В коде есть пояснения и вы разберетесь, как открывается, читается и закрывается файл, как формируется имя нового снимка, а затем файл с номером открывается и в него записывается новое значение. Главное, чтобы строчка со словом close - "закрыть", присутствовала там, где должна быть...
Параллельно с этим начал работу по добавлению объектов-декораций на игровую сцену. Первым (и пока единственным) стал аэродром. Собственно, это не один объект. Это группа объектов - ангаров, бункеров и зданий, припаренченных к взлетной полосе. Прикол в том, что здесь я опять применил замену мешей. В "первозданном" виде все эти объекты представляют собой параллелепипеды разных размеров, имеющие названия типа BunkerGreen_01 или AirbaseBuild_12. "Изюминка" заключается в том, что размеры этих объектов подогнаны под размеры "исходников" - которые существуют в виде маленьких блендов, содержащих объекты с теи же названиями, что и выше показанные, только без цифр. И меши этих многочисленных декораций меняются на подгруженные из блендов нужных мешей. Просто имя объекта "режется" по символу "_". В игре новые меши появляются только тогда, когда камера находится вблизи них, все остальное время меши заменяются на плейн, независимо от названия. Функция "декоратор":
#Эта функция отвечает за работу замены мешей в декорациях - города, растительность, аэродромы и прочее и прочее
def dekorator():
#Объект - подгружаемые из других блендов объекты, сцена - Scene, слой 1
cont = bge.logic.getCurrentController()
scene = bge.logic.getCurrentScene()
own = cont.owner
#камера внешнего обзора
cameraWorld = scene.objects["CameraWorld"]
#Камера в кокпите юнита игрока
cameraPilot = scene.objects["CameraPilot"]
sens = cont.sensors[0]
#идет просчет уровня требуемой детализации
if sens.positive:
#Перехват клаиватуры
keyboard = bge.logic.keyboard
JUST_ACTIVATED = bge.logic.KX_INPUT_JUST_ACTIVATED
#Перехват команды на переключение камер - сброс таймера ЛОД-уровня объекта
if keyboard.events[bge.events.F1KEY] == JUST_ACTIVATED or keyboard.events[bge.events.F2KEY] == JUST_ACTIVATED or keyboard.events[bge.events.F3KEY] == JUST_ACTIVATED:
own['timerLOD'] = 2.0
if keyboard.events[bge.events.F4KEY] == JUST_ACTIVATED or keyboard.events[bge.events.F5KEY] == JUST_ACTIVATED or keyboard.events[bge.events.F6KEY] == JUST_ACTIVATED:
own['timerLOD'] = 2.0
if keyboard.events[bge.events.F7KEY] == JUST_ACTIVATED or keyboard.events[bge.events.F8KEY] == JUST_ACTIVATED or keyboard.events[bge.events.F9KEY] == JUST_ACTIVATED:
own['timerLOD'] = 2.0
if keyboard.events[bge.events.F10KEY] == JUST_ACTIVATED or keyboard.events[bge.events.F11KEY] == JUST_ACTIVATED or keyboard.events[bge.events.F12KEY] == JUST_ACTIVATED:
own['timerLOD'] = 2.0
#Таймер - идет проверка
if own['timerLOD'] > 1.5:
#Если хотя бы одна из камер находится на расстоянии меньше 20 км, то уровень детализации - высокий
if own.getDistanceTo(cameraPilot) < 20000 or own.getDistanceTo(cameraWorld) < 20000:
#При этом еще и уровень детализации ранее - низкий, то идет его изменение
if own['lodOwn'] == 0:
for obj in own.childrenRecursive:
obj.replaceMesh(obj.name.split('_')[0], True, False)
own['lodOwn'] = 1
#Иначе - просто сброс значения проперти и замна всех мешей-потомков на плейны
elif own.getDistanceTo(cameraPilot) > 20000 and own.getDistanceTo(cameraWorld) > 20000:
if own['lodOwn'] == 1:
for obj in own.childrenRecursive:
obj.replaceMesh("UniversalMesh", True, False)
own['lodOwn'] = 0
own['timerLOD'] = 0.0
Ну, здесь еще и таймер есть, чтобы не "проспать" приближение камеры к объекту. А висит эта функция на родителе группы потомков. Это в данном случае - взлетная полоса, но может быть центр города, завода, базф, группы деревьев...
И, кроме всего этого, сегодня я сделал еще одну "революцию". Посмотрев свой кокпит МиГ-23БН и пробежавшись по названиям объектов, я вдруг понял (надо было раньше быть сообразительным), что можно радикально переделать скрипт кокпита, уничтожив если не всю, то практически всю логику. Поскольку сейчас кокпиты у меня изолированы, то есть возможность каждый скрипт кокпита, который находится в бленде со всеми приборами, стеклами, панелями, подогнать под конкретный случай. Все дело в том, что имена объектов в сцене кокпитов уникальны и совершенно не фиг постоянно писать own.childrenRecursive, достаточно просто написать scene.objects[название] и все. Также совершенно необязательно на все стрелочки вешать логику с функцией анимации - анимацию можно прописать наряду с работой лампочек и индикаторов в одной функции. Поскольку анимированных объектов у меня не так-то много, а индикаторы с их состоянием виден-не виден и раньше-то много не кушали, я решил рискнуть. Заодно индикация стала более продвинутой - особенно это касается работы топливной системы - теперь работает индикация расходования топлива из баков - как внутренних, так и подвесных. Пока до конца скрипт еще не дописан - мне осталось прописать ориентацию (не анимацию!) указателей крена-тангажа-рыска, и подключить стрелки перегрузки и угла атаки, плюс вариометр. Тем не менее, после устранения тройки опечаток, кокпит заработал. К моему удивлению, он стал кушать еще меньше, точнее, почти перестал кушать. По всему выходит, что сейчас он потребляет где-то 1% против двух ранее (в первой версии - все 25-30). Так что кокпиты для других машин будут делаться по этому образцу.
Кокпит Миг-23БН.
Прикол заключается в новом толковании строчки obj.playAnimation(spisok). Длинный список аргументов этой функции я приводить не буду, скажу только, что строчки я переделывал в соответствии с новыми правилами, аргументов там стало 12, а 1, как написано в новом API 2.77. Но анимации не работают, как положено. Они отражают лишь начальный и конечный кадр. А у меня эти кадры задаются значением проперти. Хоть ты тресни - крыло 2перескакивает" с первого на 200-ый кадр по завершении изменения проперти, аналогично с 201 на 400 и обратно. И вообще все анимации перестали понимать эту строчку с playAction.
Сначала я грешил на анимацию, созданную в 2.75, однако, созданный мною ради эксперимента файл с анимациями "чисто" в 2.77 показал тот же самый результат. А еще один прикол заключается в том, что если я задействую актуатор Action и в нем проставлю анимацию изменением проперти, то все работает!
Можно, конечно, придать всем объектам этот самый актуатор, но для этого им надо еще добавить проперти и логику. Объектов не сказать, чтобы много, но сама мысль о том, что придется вводить логику там, где без логических кирпичей можно прекрасно обойтись (было, скажем так, возможно обойтись) восторга у меня не вызывает. Если кто-нибудь читает эти строчки и хорошо знает английский, то пусть попробует на своем компе проделать этот фокус с анимацией - логическим блоком и скриптом. И если у вас получится такой же облом с командой playAction, отпишите багрепорт на сайт разработчиков. У меня сейчас запарка и просто нет времени.
А времени у меня нет еще по той причине, что польстившись на 2.77а и прочитав, что поддержка Виндовс ХР более не работает, поставил Виндовс 7. Хотя отношение у меня к этой и более поздним версиям Винды неоднозначное. Кроме того, думаю все-таки поставить рядом с виндой и Линукс. Сначала, правда, придется затвердить правила установки рядом с Виндовс - есть несколько хорших статей на эту тему, а потом еще надо выяснить, сколько трафика у меня осталось на Мегафоне, потому как Линукс с Билайном не дружат. Плюс проверить версию Линукса в работе, потому что версия 12.04 люто била по глазам - вроде бы и работала, но монитор "мигал" каждые 10 секунд. Тогда-то меня и остановило это обстоятельство. В прошлом году я на всякий случай скачал 14.04 и проверил ее, не устанавливая, запуском с DVD - экран не мигал, Мегафон работал, что порадовало. Однако тогда еще вовсю работала ХР, да и рассчитывал я на установку нового винчестера. Однако грянувший могучий ремонт дворовых объектов и самого дома несколько поумерил аппетиты, да еще впереди еще кое-какие дела, так что пока неясно с этим винчестером. Но учиненный мною погром с установкой "семерки" привел к тому, что откладывать установку Линукса вроде как уже неудобно - диск порядком очищен от старых файлов, места полно, вирусня еще набежать не успела - надо решаться. что плохо - не удается пока восстановить джаббер.
Тем временем, несмотря на столь резкий поворот событий, проект все же продолжает свое движение вперед. Был сделан скриншотер экрана. Вообще-то он был и в первой версии, но этот - совершеннее. Его новшество в том, что теперь сохраняются скрины старых сеансов игры, раньше каждый новоый запуск игры и фотографирование процесса на мониторе приводило у ничтожению старых скринов. Это не есть хорошо, и эту проблему, немного повозившись, я решил.
Кусок кода:
#Скриншот экрана
if key == bge.events.F12KEY:
#Открываем текстовый файл и смотрим номер последнего снимка
screenNull = open(bge.logic.expandPath('////Screenshot/screen.txt'),'r')
kadrNull = screenNull.read()
#Увеличиваем номер на 1 и закрываем файл
kadrNew = int(kadrNull) + 1
screenNull.close()
#составляем новое имя для нового снимка
indexScreen = 'BlendSim' + str(kadrNew)
#Делаем снимок и отправляем в папку
bge.render.makeScreenshot("//ScreenShot/" + indexScreen)
#А теперь опять открываем текстовый файл с номером снимка и пишем туда уже номер нового скрина
kadrWrite = open(bge.logic.expandPath('//Screenshot/screen.txt'),'w')
kadrWrite.write(str(kadrNew))
#Опять закрываем файл
kadrWrite.close()
В папке со скриншотами находится текстовый файл. в нем записано число. Это число предыдущего снимка - если угодно - число последнего срабатывания скриншотера. В коде есть пояснения и вы разберетесь, как открывается, читается и закрывается файл, как формируется имя нового снимка, а затем файл с номером открывается и в него записывается новое значение. Главное, чтобы строчка со словом close - "закрыть", присутствовала там, где должна быть...
Параллельно с этим начал работу по добавлению объектов-декораций на игровую сцену. Первым (и пока единственным) стал аэродром. Собственно, это не один объект. Это группа объектов - ангаров, бункеров и зданий, припаренченных к взлетной полосе. Прикол в том, что здесь я опять применил замену мешей. В "первозданном" виде все эти объекты представляют собой параллелепипеды разных размеров, имеющие названия типа BunkerGreen_01 или AirbaseBuild_12. "Изюминка" заключается в том, что размеры этих объектов подогнаны под размеры "исходников" - которые существуют в виде маленьких блендов, содержащих объекты с теи же названиями, что и выше показанные, только без цифр. И меши этих многочисленных декораций меняются на подгруженные из блендов нужных мешей. Просто имя объекта "режется" по символу "_". В игре новые меши появляются только тогда, когда камера находится вблизи них, все остальное время меши заменяются на плейн, независимо от названия. Функция "декоратор":
#Эта функция отвечает за работу замены мешей в декорациях - города, растительность, аэродромы и прочее и прочее
def dekorator():
#Объект - подгружаемые из других блендов объекты, сцена - Scene, слой 1
cont = bge.logic.getCurrentController()
scene = bge.logic.getCurrentScene()
own = cont.owner
#камера внешнего обзора
cameraWorld = scene.objects["CameraWorld"]
#Камера в кокпите юнита игрока
cameraPilot = scene.objects["CameraPilot"]
sens = cont.sensors[0]
#идет просчет уровня требуемой детализации
if sens.positive:
#Перехват клаиватуры
keyboard = bge.logic.keyboard
JUST_ACTIVATED = bge.logic.KX_INPUT_JUST_ACTIVATED
#Перехват команды на переключение камер - сброс таймера ЛОД-уровня объекта
if keyboard.events[bge.events.F1KEY] == JUST_ACTIVATED or keyboard.events[bge.events.F2KEY] == JUST_ACTIVATED or keyboard.events[bge.events.F3KEY] == JUST_ACTIVATED:
own['timerLOD'] = 2.0
if keyboard.events[bge.events.F4KEY] == JUST_ACTIVATED or keyboard.events[bge.events.F5KEY] == JUST_ACTIVATED or keyboard.events[bge.events.F6KEY] == JUST_ACTIVATED:
own['timerLOD'] = 2.0
if keyboard.events[bge.events.F7KEY] == JUST_ACTIVATED or keyboard.events[bge.events.F8KEY] == JUST_ACTIVATED or keyboard.events[bge.events.F9KEY] == JUST_ACTIVATED:
own['timerLOD'] = 2.0
if keyboard.events[bge.events.F10KEY] == JUST_ACTIVATED or keyboard.events[bge.events.F11KEY] == JUST_ACTIVATED or keyboard.events[bge.events.F12KEY] == JUST_ACTIVATED:
own['timerLOD'] = 2.0
#Таймер - идет проверка
if own['timerLOD'] > 1.5:
#Если хотя бы одна из камер находится на расстоянии меньше 20 км, то уровень детализации - высокий
if own.getDistanceTo(cameraPilot) < 20000 or own.getDistanceTo(cameraWorld) < 20000:
#При этом еще и уровень детализации ранее - низкий, то идет его изменение
if own['lodOwn'] == 0:
for obj in own.childrenRecursive:
obj.replaceMesh(obj.name.split('_')[0], True, False)
own['lodOwn'] = 1
#Иначе - просто сброс значения проперти и замна всех мешей-потомков на плейны
elif own.getDistanceTo(cameraPilot) > 20000 and own.getDistanceTo(cameraWorld) > 20000:
if own['lodOwn'] == 1:
for obj in own.childrenRecursive:
obj.replaceMesh("UniversalMesh", True, False)
own['lodOwn'] = 0
own['timerLOD'] = 0.0
Ну, здесь еще и таймер есть, чтобы не "проспать" приближение камеры к объекту. А висит эта функция на родителе группы потомков. Это в данном случае - взлетная полоса, но может быть центр города, завода, базф, группы деревьев...
И, кроме всего этого, сегодня я сделал еще одну "революцию". Посмотрев свой кокпит МиГ-23БН и пробежавшись по названиям объектов, я вдруг понял (надо было раньше быть сообразительным), что можно радикально переделать скрипт кокпита, уничтожив если не всю, то практически всю логику. Поскольку сейчас кокпиты у меня изолированы, то есть возможность каждый скрипт кокпита, который находится в бленде со всеми приборами, стеклами, панелями, подогнать под конкретный случай. Все дело в том, что имена объектов в сцене кокпитов уникальны и совершенно не фиг постоянно писать own.childrenRecursive, достаточно просто написать scene.objects[название] и все. Также совершенно необязательно на все стрелочки вешать логику с функцией анимации - анимацию можно прописать наряду с работой лампочек и индикаторов в одной функции. Поскольку анимированных объектов у меня не так-то много, а индикаторы с их состоянием виден-не виден и раньше-то много не кушали, я решил рискнуть. Заодно индикация стала более продвинутой - особенно это касается работы топливной системы - теперь работает индикация расходования топлива из баков - как внутренних, так и подвесных. Пока до конца скрипт еще не дописан - мне осталось прописать ориентацию (не анимацию!) указателей крена-тангажа-рыска, и подключить стрелки перегрузки и угла атаки, плюс вариометр. Тем не менее, после устранения тройки опечаток, кокпит заработал. К моему удивлению, он стал кушать еще меньше, точнее, почти перестал кушать. По всему выходит, что сейчас он потребляет где-то 1% против двух ранее (в первой версии - все 25-30). Так что кокпиты для других машин будут делаться по этому образцу.
Кокпит Миг-23БН.
вот почему тебя в джаббере не видно
ОтветитьУдалитьНу да. Сама смена операционки - потрясение основ, а тут их стало две...
Удалить