четверг, 12 января 2017 г.

Возвращаясь к напечатанному. Работа с blf - текстовые маркеры.

В конце прошлого года с помощью dron-fя ввел текстовый маркер цели на эуране. Об этом я подробно писал в посте о работе с blf и приводил срипт с кодом. Прошло время и я вновь был вынужден заняться этой темой. Как известно, во многих играх существуют текстовые подсказки, которые, как правило, сопровождают юниты или предметы, показывают боекомплект, направление движения и так далее.
В том варианте скрипта текстовый маркер был один и касался он только одной - захваченной цели. Однако хотелось получить более полную информацию об обстановке вокруг и иметь возможность включения-выключения текстовых маркеров. Практически с первой попытки удалось добиться маркировки всех целей в поле зрения камеры, плюс маркировка выбранной цели. Однако скрипт вышел усложненным и корявым. dron указал на некоторые мои промахи (в частности совершенно ненужный повторный вызов функций), после чего я вновь переработал скрипт. Пришлось вводить функцию "затирания" текста, иначе маркеры не выключались. Дополнительно пришлось переводить индекс выбранной цели в глобальный словарь,дописать строчки кода для выбора режима отображения информации - но это так - по мелочам. Теперь скрипт имеет измененный вид, но изменения еще произойдут, поскольку Андрей в своих подсказках применил мною ранее не употреблявшиеся способы форматирования текста и их требуется осмыслить  и принять на вооружение.Итак, код (надо еще разобраться с подсветкой кода в Блоггере - первая попытка окончилась провалом - но программист в html из меня не очень пока что):

import bge
import bgl
import blf

#МЕТКИ ЦЕЛИ НА КОЛЛИМАТОРЕ - ОБЕСПЕЧИВАЕТСЯ ЕЕ ПЛАВНОЕ ПЕРЕМЕЩЕНИЕ ВСЛЕД ЗА ЦЕЛЬЮ  
#Чтение экранных координат    
def readCoord():
    cont = bge.logic.getCurrentController()
    scene = bge.logic.getCurrentScene()
    own = cont.owner
    camera = scene.active_camera
   
    targetLabel = scene.objects['targetMarka']
   
    camera = scene.active_camera
   
    #Метка цели работает только при включенном радаре и выставленной дальности
    try:
        #
        marka = own.getScreenPosition(targetLabel)
       
        if abs(marka[0] - bge.logic.globalDict['targetCoord'][0]) > 0.001:
            targetLabel.worldPosition[0] -= (marka[0] - bge.logic.globalDict['targetCoord'][0])/5
        if abs(marka[1] - bge.logic.globalDict['targetCoord'][1]) > 0.001:
            targetLabel.worldPosition[2] += (marka[1] - bge.logic.globalDict['targetCoord'][1])/5
       
        plusX = targetLabel['limXplus'] #collimatorRight.worldPosition[0]
        minusX = targetLabel['limXminus'] #collimatorLeft.worldPosition[0]
        plusY = targetLabel['limYplus'] #collimatorRight.worldPosition[2]
        minusY = targetLabel['limYminus'] #collimatorLeft.worldPosition[2]
         
        if targetLabel.worldPosition[0] < minusX:
            targetLabel.worldPosition[0] = minusX
        elif targetLabel.worldPosition[0] > plusX:
            targetLabel.worldPosition[0] = plusX
        if targetLabel.worldPosition[2] < minusY:
            targetLabel.worldPosition[2] = minusY
        elif targetLabel.worldPosition[2] > plusY:
            targetLabel.worldPosition[2] = plusY
       
       
           
    except:
        centerX = (targetLabel['limXminus'] + targetLabel['limXplus'])/2
        centerY = (-targetLabel['limYminus'] + targetLabel['limYplus'])/2
        targetLabel.worldPosition[0] = centerX
        targetLabel.worldPosition[2] = centerY

def writeCoord():
    cont = bge.logic.getCurrentController()
    scene = bge.logic.getCurrentScene()
    own = cont.owner
    bge.logic.font_id = 0 #blf.load(font_path)
   
    if 'localDict' not in own:
        own['localDict'] = {'typeWriteCoord':own['typeWriteCoord']}
    else:
        if own['localDict']['typeWriteCoord'] != own['typeWriteCoord']:
            #Однократный прогон функции стирания текста при выкоючении маркеров
            if own['typeWriteCoord'] == 0:
                scene.post_draw = [resetWrite]
            own['localDict']['typeWriteCoord'] = own['typeWriteCoord']
       
        #Маркеры текстовой информации включены
        if own['typeWriteCoord'] == 1:
            scene.post_draw = [write]
        #Если макеры выключены, работает  упрощенная функция слежения только за одной целью  
        else:
            targetWrite()
   
   

def write():
    scene = bge.logic.getCurrentScene()
    camera = scene.active_camera
   
    width = bge.render.getWindowWidth()
    height = bge.render.getWindowHeight()
 
    textInfo = ''
    distance = 0
   
    targetInScene = 0
   
    bgl.glDisable(bgl.GL_DEPTH_TEST)
    bgl.glMatrixMode(bgl.GL_PROJECTION)
    bgl.glLoadIdentity()
    bgl.gluOrtho2D(0, width, 0, height)
    bgl.glMatrixMode(bgl.GL_MODELVIEW)
    bgl.glLoadIdentity()
    font_id = bge.logic.font_id
   
   
    if len(bge.logic.globalDict['listAllObject']) > 0:
       for target in bge.logic.globalDict['listAllObject']:
           #Отрисовке информации подлежат только объекты в поле зрения камеры
           if -0.6 < camera.getVectTo(target)[2][0] < 0.6 or str(id(target)) == bge.logic.globalDict['idTarget']:
               #Несколько коряво с повтором условия
               if -0.32 < camera.getVectTo(target)[2][1] < 0.32 or str(id(target)) == bge.logic.globalDict['idTarget']:
                   if camera.getDistanceTo(target) > 30:
                     
                       ScreenPositionTarget = camera.getScreenPosition(target)
                     
                       winXcoord = bge.render.getWindowWidth(target) * ScreenPositionTarget[0]
                       winYcoord = bge.render.getWindowHeight(target) *(1-ScreenPositionTarget[1])
                 
                       distance = int(camera.getDistanceTo(target)/1000)
                       #Формируем текстовый блок
                       textInfo = target['unitName'] + target['unitNation'] + str(distance)
                     
                       blf.position(font_id, winXcoord, winYcoord, 0)
                       blf.size(font_id, 25, 36)
                       if target['target'] == 0:
                           bgl.glColor3f(1.0,0.0,0.0)
                       if target['target'] == 1:
                           bgl.glColor3f(0.0,0.0,1.0)
                       #bgl.glColor4f
                       bgl.glDisable(bgl.GL_LIGHTING)
                       blf.draw(font_id, textInfo)
                       blf.draw(font_id, textInfo)
                     
                       #Для захваченной цели
                       if str(id(target)) == bge.logic.globalDict['idTarget']:
                           targetInScene = 1
                           bge.logic.globalDict['targetCoord'] = ScreenPositionTarget
                           targetDistance = camera.getDistanceTo(target)
                           targetSpeed = target.localLinearVelocity[1]
                           targetHeight = target.worldPosition[2]
                           bge.logic.globalDict['targetData'] = [targetDistance, targetSpeed, targetHeight]
                 
    #Последнее уточнение -  если после прохождения цикла цели в сцене не имеется
    if targetInScene == 0:
        bge.logic.globalDict['targetCoord'] = [0, 0]
        bge.logic.globalDict['targetData'] = [0, 0, 0]
   
    bgl.glEnable(bgl.GL_DEPTH_TEST)
               

#Упрощенная функция чтения экранных координат целм
def targetWrite():
    cont = bge.logic.getCurrentController()
    scene = bge.logic.getCurrentScene()
    own = cont.owner
   
    try:
        target = scene.objects.from_id(int(own['idTarget']))
        camera = scene.active_camera
        bge.logic.globalDict['targetCoord'] = camera.getScreenPosition(target)
        targetDistance = own.getDistanceTo(target)
        targetSpeed = target.localLinearVelocity[1]
        targetHeight = target.worldPosition[2]
        bge.logic.globalDict['targetData'] = [targetDistance, targetSpeed, targetHeight]
    except:
        bge.logic.globalDict['targetCoord'] = [0, 0]
        bge.logic.globalDict['targetData'] = [0, 0, 0]
       
#Функция сброса экранных маркеров  
def resetWrite():
    scene = bge.logic.getCurrentScene()
    camera = scene.active_camera
    width = bge.render.getWindowWidth()
    height = bge.render.getWindowHeight()
    #bgl.glDisable(bgl.GL_DEPTH_TEST)
    bgl.glMatrixMode(bgl.GL_PROJECTION)
    bgl.glLoadIdentity()
    bgl.gluOrtho2D(0, width, 0, height)
    bgl.glMatrixMode(bgl.GL_MODELVIEW)
    bgl.glLoadIdentity()
    font_id = bge.logic.font_id
    blf.position(font_id, 0, 0, 0)
    blf.size(font_id, 25, 36)
    bgl.glDisable(bgl.GL_LIGHTING)
    blf.draw(font_id, '')
    blf.draw(font_id, '')
    #bgl.glEnable(bgl.GL_DEPTH_TEST)
               

Ну и, как это выглядит на экране. Пара Ф-16 с национальной принадлежностью и дистанцией в км. Кстати, при тестировании, когда мой МиГ-23МФ был сбит и камера "отсоединилась", то я увидел и красную строчку с указанием моего юнита и дистанцией с нацпринадлежностью (когда сбитый самолет пошел вперед и вниз). Клавиша М(лат) срабатывает - можно включать и отключать текст.

Комментариев нет:

Отправить комментарий