В конце прошлого года с помощью 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МФ был сбит и камера "отсоединилась", то я увидел и красную строчку с указанием моего юнита и дистанцией с нацпринадлежностью (когда сбитый самолет пошел вперед и вниз). Клавиша М(лат) срабатывает - можно включать и отключать текст.
В том варианте скрипта текстовый маркер был один и касался он только одной - захваченной цели. Однако хотелось получить более полную информацию об обстановке вокруг и иметь возможность включения-выключения текстовых маркеров. Практически с первой попытки удалось добиться маркировки всех целей в поле зрения камеры, плюс маркировка выбранной цели. Однако скрипт вышел усложненным и корявым. 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МФ был сбит и камера "отсоединилась", то я увидел и красную строчку с указанием моего юнита и дистанцией с нацпринадлежностью (когда сбитый самолет пошел вперед и вниз). Клавиша М(лат) срабатывает - можно включать и отключать текст.
Комментариев нет:
Отправить комментарий