Перейти к содержимому
eu_tomat

Гайд. Как убрать чёрные полосы по краям экрана OpenComputers.

Рекомендуемые сообщения

На днях в чате прозвучал вопрос, как убрать чёрные полосы по краям экрана. На форуме есть замечательная библиотека от @ECS, которая хорошо решает поставленную задачу: http://computercraft.ru/topic/1130-avtomaticheskii-mssahtab-monitora-izbavliaemsia/

Но есть два нюанса:

1) Код библиотеки явно избыточен.

2) При чтении кода библиотеки создаётся впечатление, что она работает на неведомой магии тёмных сил, что демотивирует новичков, изучающих OpenComputers.

Я намерен восполнить данный недостаток.

 

Прочтение этого гайда поможет любому желающему написать кусочек кода под нужды конкретной программы, не подтягивая библиотечный код.

 

Благодарю @Totoro за предоставленную информацию:

1) Текстура блока имеет размер 16 px, а ширина рамки монитора – 2 px;

2) Высота символа на экране в два раза больше его ширины.

Данной информации достаточно для получения всех необходимых формул. Приступим:

 

Первый шаг: получить соотношение сторон экрана, выраженное в символах

 

В мире Майнкрафта текстура блока имеет размер в 16 пикселей. На рамку с каждой стороны тратится по 2 пикселя независимо от размера монитора.

Pdqexqc.png

 

Очевидно, что размер монитора в пикселях кратен 16 и пропорционален количеству использованных блоков, а размер полезной части экрана всегда меньше размера монитора на 4 пикселя как по вертикали, так и по горизонтали. Поэтому разрешение нескольких мониторов, выставленных в ряд, всегда составит 16*n-4 пикселей по соответствующей координатной оси.

 

Это подтверждает и формула от @ECS, реализованная в функции calculateAspect(screens), но имеющая более сложный вид. Я предлагаю и вовсе отказаться от отдельной функции, т. к. в текущих условиях это будет напрасной тратой ресурсов.

 

Немного поясняющего кода:

-- размер монитора в блоках
sw,sh = component.screen.getAspectRatio()
-- размер экрана монитора с учётом затрат на рамку:
sw_ = sw*16-4
sh_ = sh*16-4
-- соотношение сторон экрана, выраженное в пикселях текстуры блока
sa = sw_/sh_
-- соотношение сторон экрана, выраженное в символах
sa = 2*sw_/sh_
-- оно же без промежуточных присваиваний:
sa = 2*(sw*16-4)/(sh*16-4)
-- оно же после упрощения формулы и сокращения количества операций
sa = (sw*2-0.5)/(sh-0.25)
Второй шаг: скорректировать разрешение графической карты под соотношение сторон экрана

 

Теперь требуется получить максимально доступное разрешение GPU и соответствующее ему соотношение сторон:

-- максимально возможное разрешение графической карты в символах
gw, gh = gpu.maxResolution()
-- соотношение сторон при максимальном разрешении в символах
ga = gw/gh
-- формулы, полученные из предыдущей, и которые пригодятся чуть позже
gw = gh*ga
gh = gw/ga
Для определения дальнейших действий следует вспомнить о физическом смысле соотношения сторон. Исходя из приведённых выше формул, sa и ga можно назвать коэффициентами горизонтальности. Сравнивая их, можно определить, что по горизонтали более вытянуто разрешение либо видеокарты, либо монитора. Понятно, что если монитор имеет больший коэффициент горизонтальности, то для приведения к нему коэффициента горизонтальности видеокарты следует уменьшить её разрешение по вертикали. В ином случае следует уменьшать разрешение GPU по горизонтали:

-- код в понятной форме, использованы формулы из предыдущего фрагмента
if sa>ga then -- недостаточная горизонтальность GPU
  ga=sa -- привести горизонтальность в соответствии с экраном
  gh = gw/ga -- за счёт уменьшения высоты
else -- избыточная горизонтальность GPU
  ga=sa -- привести горизонтальность в соответствии с экраном
  gw = gh*ga -- за счёт уменьшения ширины
end
-- код после сокращения лишних операций
if sa > gw/gh then
  gh = gw/sa
else
  gw = gh*sa
end
Третий шаг: скорректировать разрешение графической карты под нужны программы

 

Вычисленное на предыдущем шаге разрешение может оказаться дробным, и перед использованием его следует округлить. Возможно, что перед этим разрешение должно быть приведено к желаемому масштабу, как это сделано в библиотеке @ECS. Эта часть, скорее всего, не требует пояснений, и готовый код будет, например, таким:

-- код для автоматической подстройки разрешения графической карты под размер монитора
--  почти не оставляет чёрных полос по краям экрана
--  полное исключение полос возможно только при отсутствии округления разрешения

local component = require"component"
local gpu, screen = component.gpu, component.screen

function set_proportional_resolution( scale )
  -- коррекция допустимых пределов масштаба
  if not scale or scale > 1 then
    scale = 1
  elseif scale < 0.1 then
    scale = 0.1
  end
  -- соотношение сторон монитора в символах:
  local sw,sh = screen.getAspectRatio()
  local sa = (sw*2-0.5)/(sh-0.25)
  -- запрос и коррекция максимального разрешения GPU
  local gw, gh = gpu.maxResolution()
  if sa > gw/gh then
    gh = gw/sa
  else
    gw = gh*sa
  end
  -- установка нового разрешения GPU с учётом заданного масштаба
  gpu.setResolution( math.floor(gw*scale), math.floor(gh*scale) )
end

-- тест работоспособности на нескольких вариантах масштаба
-- в процессе можно видеть, что на некоторых масштабах чёрные полосы имеют больший размер, чем на других
local w,h
local unicode = require"unicode"

for i=0.1, 1, 0.1 do
  set_proportional_resolution(i)
  w,h = gpu.getResolution()
  gpu.fill(1,1,w,h, unicode.char(0x2592))
  os.sleep(2)
end
Приведённый код можно сократить ещё сильнее, например, избавившись от масштабирования, которое может отвлекать читателя от подгонки соотношения сторон.

 

Полное исключение чёрных полос

 

При выполнении этого кода можно видеть, что чёрные полосы не исчезают полностью, и на одних масштабах проявляются сильнее, чем на других. Предположим, требуется полностью избавиться от чёрных полос. Можно было бы написать код и для этого случая, но эта задача не всегда решаема. Кроме того, количество решений сильно ограничено, и не любой интерфейс можно будет подогнать под найденные решения.

 

Пример №1:

Монитор максимального допустимого размера 8x6; GPU Tier3 обеспечивает максимальное разрешение 160x50.

Условное разрешение монитора в целых символах:

sw = 8*8-2 = 62

sh = 6*4-1 = 23

Допустимые разрешения GPU, которые обеспечат отсутствие полос: 62x23 и 124x46.

 

Пример №2:

Монитор 6x5; GPU Tier1 обеспечивает максимальное разрешение 50x16.

Условное разрешение монитора в целых символах:

sw = 6*8-2 = 46

sh = 5*4-1 = 19

Нет разрешений GPU, обеспечивающих полное отсутствие полос.

 

Пример №3:

Монитор 5x5; GPU Tier1 обеспечивает максимальное разрешение 50x16.

Условное разрешение монитора в целых символах:

sw = 5*8-2 = 38

sh = 5*4-1 = 19

Разрешения GPU 50x16 недостаточно для размещения поля символов 38x19. Но если присмотреться внимательно, и вспомнить, что нам важно соотношение, то поле символов можно сократить до 2x1, избавившись от общего делителя 19. В этом случае допустимых разрешений GPU предостаточно, начиная от 2x1 и заканчивая 32x16. Во всех этих случаях пустых чёрных полос на мониторе не будет.

 

Автоматизация этих вычислений вряд ли целесообразна. Скорее всего, имеет смысл примерно прикинуть необходимое разрешение для конкретного интерфейса, выбрать желаемый размер экрана, графическую плату, и выполнив приведённые выше вычисления, уже окончательно определить рабочее разрешение и затем подогнать интерфейс под него.

 

 

Вот, и вся магия. То, что выглядит сложным, не всегда является таковым на самом деле.

Изменено пользователем eu_tomat
опечатки

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  -- соотношение сторон монитора в символах:
  local sw,sh = screen.getsapectRatio()
  local sa = (sw*2-0.5)/(sh-0.25)

Ошибочка маленькая, забыл большую "A" и "s"

UPD: А за гайд - отдельное спасибо от лица всех программ с чёрными полосами.

Изменено пользователем BrightYC

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ошибочка маленькая, забыл большую "A" и "s"

Исправил.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в тему...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


×
×
  • Создать...