понедельник, 11 апреля 2016 г.

Пейзаж после погрома.

Лучшее - враг хорошего. Иногда это утверждение верно, иногда - нет. Вышедший недавно 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БН.



2 комментария:

  1. вот почему тебя в джаббере не видно

    ОтветитьУдалить
    Ответы
    1. Ну да. Сама смена операционки - потрясение основ, а тут их стало две...

      Удалить