Info Guide
#11
05 июля 2015 |
|
Code - О мерцающем бордере: использование мерцание для повышения разрешения на бордере.
О мерцающем бордере Alone Coder Использовать мерцание для повышения разрешения на бордере я решил в конце 1996 года, ещё когда пользовался услугами по─ стоянно глючащего агрегата под названием Pentagon 48и потому "кодил" в основном на бумажках (только в декабре 1996 я стал переходить на Pentagon 128). Возможно, именно эти бумажки помогли пронести идею сквозь годы - результатом было интро KOT на DiHalt 2012. * * * На Pentagon, а также на некоторых дру─ гих русских клонах Спектрума (ATM Turbo, Profi) бордер не квантуется по 4 такта,как на фирменном Speccy (впрочем, фирменная развёртка в те времена была загадкой - ка─ ждый писал под то, что у него было). А раз квантования нет,то горизонтальное разреше─ ние по идее составляет 2 экранных пикселя, 1 такт процессора.Но это разрешение невоз─ можно полноценно использовать. И вот эта мысль о мерцании у меня воз─ никла во время написания бегущей строчки на бордере (в 48K demo ),где символы полу─ чались слишком широкими и некрасивыми, не─ смотря на то,что я смещал некоторые цвето─ переходы на 6 тактов вместо 12, то есть на половину типичного бордерного "пикселя" ("бокселя"? "борделя"? :)). Бегущую строчку было переделывать позд─ но, тем более что она по обыкновению была написана на бумаге и долго вбивалась в GENS - так же, как предшествовавшие ей крупные проекты Font Editor и Sapper'96. Но можно было использовать метод где-то ещё. Мерцание само по себе не было открыти─ ем, правда,использовалось только в области экрана. Я тогда видел не так много софта (а был ли в то время такой софт?), но идея мерцания была очевидной.Вообще я хотел де─ лать мерцающие спрайты в играх, чтобы они выглядели в цвете, как на Денди/NES. При этом у меня не было цветного монитора,но я всё равно рисовал отдельные фазы такого мерцания в тетрадках. Ещё я использовал мерцание для повыше─ ния горизонтального разрешения экрана - мой монитор сдвигал строку на полпикселя, если перед ней в начале обратного хода лу─ ча (или в конце - не помню) бордер был яр─ кий. Но цветные мерцающие спрайты занимали меня настолько, что я много раз к ним воз─ вращался, пытался рисовать в разных реда─ кторах,но так и не дошёл до написания игры с ними. Забросил я эту тему только тогда, когда собрал на своём Пентагоне (тогда уже типичном по тем временам Pentagon 1024 + Turbo ) схему "цвет на точку". На бордере главная проблема была не с числом цветов (я делал и дополнительные мерцанием и чередованием строк - см.плагин Raduga для ACEdit, написанный в 1998 го─ ду), а с тем, что углы, смотрящие вверх или вниз, просто невозможно отрисовать. Можно отрисовать подобие скругления (см. шарик в интро Sinclair Club #5, написанный в 1997 году). Но настоящий угол требует единицы тактов на цветопереходе - это при том, что меньше 11 тактов, то есть 22 пик─ селей, между соседними цветопереходами быть не может. (А вы знаете, что на фир─ менном Speccy можно и 16 пикселей?) Конеч─ но, я делал генератор перспективной шахма─ тной сетки из рисунка на экране, варьируя паузы между цветопереходами, и эксперимен─ тировал с другими изображениями. Но огра─ ничения всё равно были жестокими - нельзя было вывести даже простейшие звёздочки. В общем, для примера я взял рисунок стрелки, направленной влево-вверх (как в Art Studio) и нарисовал в тетрадке,что бу─ дет, если вывести на одном кадре левую половину фона под стрелкой - допустим, бе─ лым цветом, - а на другом правую половину. Фон будет мерцать, но чёрная стрелочка на этом фоне будет видна. Чтобы стрелочка была белой, надо на одном кадре вывести левую половину фона вплоть до правой границы стрелочки, а на другом - правую половину фона до левой границы стрелочки. То есть область стрело─ чки будет закрашена на обоих кадрах. На немерцающем фоне стрелочку выве─ сти нельзя, потому что это потребовало бы сплошного фона на обоих кадрах и как мини─ мум на одном из кадров вырезанную стрелоч─ ку. С острым углом, смотрящим вверх, что невозможно. Если вернуться к стрелочке на мерцающем фоне, то так можно реализовать и звёзды. Звезда с её фоном - одна строка такой стрелочки (в белом варианте). Но что произойдёт, если звезда будет двигаться - уследит ли за ней глаз или же изображение полностью развалится? А как будет выглядеть рисунок мерцания, если звёздочек или других элементов будет мно─ го? Как снизить мерцание? Где это вообще можно использовать? Было множество вопро─ сов и материала для экспериментов. Но в тот момент я поступал в институт, и време─ ни для таких экспериментов не было, хвати─ ло времени только на упомянутый шарик. К тому же, мне виделось другое решение проблемы - аппаратное выключение бордера, для которого, как оказалось, не требуется ничего, кроме проводов и рубильника (см. ZX-Guide #1 и #2 ). Кстати, ранние мои эксперименты под Pentagon 128 делались с интом,сдвинутым на 2 знакоместа (как на ATM Turbo ), потом и саму плату, и эти программы я подгонял под один из наиболее распространённых вариан─ тов - их два, отличающихся на один такт: один поддержан в первой части PSG-Wins, другой во второй; я выбрал тот,который со─ ответствовал деме Rage, хотя она, конечно, писалась на переделанном "Скорпионе". А что за "Пентагоны" поддерживались в наст─ ройщике INT от E2 Soft и в деме Condommed - неизвестно. * * * Шли годы,в течение которых тему бордера дальше поддерживал VNN/KCS (светлая ему память! Пусть горит в аду тот моральный урод, который над ним издевался в послед─ ние его дни, и позор тем, кто до сих пор угодливо заискивает перед этим уродом! Ду─ майте, кого вы поддерживаете!) И однажды, в 2012 году, на DiHalt объя─ вили конкурс бордерного интро, как раз за─ точенный под Pentagon. Такой формат подходил как нельзя лучше, поскольку в тот год я был явно не в форме для написания полноценной демы (делал му─ льтфильмы с учениками на киностудии РГРТУ- Фильм). К тому же,идея мерцания на бордере всё ещё оставалась неиспользованной, так что был смысл её красиво засветить. Общая концепция интры была понятна сра─ зу - звёзды, надпись,рисунок,бегущая стро─ чка (о полноценных эффектах речь не шла - говорили про картинки на бордере). Вопросы стояли такие: 1.Что будет на рисунке? 2.Как уменьшить мерцание? 3.Какой ширины надпись уместится на бо─ рдере? 4.Чем играть музыку? 5.Как будут двигаться звёзды? 1. Рисунок должен был быть силуэтным. По крайней мере,картинка в голове представля─ лась именно такой. Я посмотрел в интерне─ те, что есть на тему силуэтов,и нашёл того самого кота. Конечно,я не мог использовать картинки в том виде, как они есть,хоть они и анонимные. Но кота можно было анимиро─ вать! Ведь я как раз занимался мультфиль─ мами... Кандидаты в фоновые рисунки от аноним─ ных интернет-художников можно найти в ар─ хивеhttp://alonecoder.nedopc.com/zx/ MKBORDER.rar (там же лежит надпись на бор─ дере и генератор кода и скриптов,о которых ниже). Сравните. Думаю,я сделал правильный выбор :) 2. Мерцание обычно уменьшают чередованием строк. Но для этого нужно, чтобы цвет фона менялся регулярно,независимо от расположе─ ния на нём звёздочек. Рассуждения были та─ кие (цитирую исторический документ.Ох ско─ лько у меня накопилось таких исторических документов в папке с материалами для Info Guide #11... ): ┌────────────────────────────────────────┐ А) Звезда - место, где меняется фаза заливки (на одном экране на 2 пикс дальше, чем на другом). Такие звёзды нельзя пропускать! Тогда справа от них на соседних кадрах бу─ дет одинаковый цвет! Невозможные звёзды надо заменять на смену фазы в кратчайшее время. Фаза начала строки по умолчанию в противо─ фазе с прошлым экраном. Проблема,если сле─ дить глазами за звездой, там фазы уже дру─ гие!!! Нужно назначить фазу каждой звезде и в случае необходимости использовать инверсию на пустом месте. Но будет ли тогда общий фон экрана правильно колебаться? 1.фаза, задаваемая статичным экраном. 2.фаза, задаваемая крупными звёздами. 3.фаза, задаваемая мелкими звёздами (задний план, другая скорость). Нереально соблюсти все три. Б) Каждую звезду сразу давать с инверсией на конце (или в начале): кадр1: 000001111111111110000 (out (c),r) кадр2: 111110000000000111111 (out (#fe),a) Чтобы всё сильно не мигало, чередовать че─ рез строку. Слои звёзд разделить по чёт─ ным/нечётным строкам. Минимальное расстояние между звёздами = 33 такта (66 пикс), дальше 37,38...: └────────────────────────────────────────┘ Причём обновлять экран можно (опять ци─ тирую): ┌────────────────────────────────────────┐ а) отставая от луча (верхний бордюр не использовать, обратный ход как продолжение прошлого кадра) б) опережая луч (нижний бордюр как нача─ ло нового кадра) в) на другом экране (можно использовать гигаскрин в основной картинке) └────────────────────────────────────────┘ Я выбрал вариант Б (см.выше) с двумя эк─ ранами, рассуждая так: ┌────────────────────────────────────────┐ Как рисовать пиксели на экране? а) заливать вообще всё,в фазе с бордером (большая площадь!) б) два экрана мигают. Для А граница бор─ дера видна, для Б не видна. в) на одном экране переключаем атрибуты. Для А граница бордюра видна, для Б не вид─ на. г) только для А: в зависимости от цвета большей части строки включаем нужный экран на данной строке. Время на экране = 24576 тактов Время на обратном ходе = 3584 тактов (16 строк) Время на нижнем бордюре = 10752 тактов (48 строк) итого макс. 38912 тактов /11 t = макс. 3.5K активной площади. Для Б заливка не нужна, времени хватит да─ же на весь экран. └────────────────────────────────────────┘ 3.5K - это не считая времени между звё─ здами,которым можно,в принципе,пренебречь. Его трудно использовать, не генерируя для звёзд непосредственно код. А я хотел гене─ рировать для них скрипт. Код я хотел гене─ рировать только для надписи, ибо в надписи код нужен только один раз, а звёзды движу─ тся. 3. По надписи рассуждения были такие: ┌────────────────────────────────────────┐ Расстояние между буквами 12 тактов. (Т.к. фаза может меняться в строке,а акку─ мулятор один - теоретически можно успеть exa...) Ширина линий 4 такта, потому что бывают стыки вертикалей, а бывает вертикаль одной буквы, срез верхушки другой буквы. Все типы строк (min 9): 00000000 01110000 (A)(C)(G)(J)(O)(Q)(S)(U) 10001000 10000000 00001000 11111000 11110000 B D(E)(F)K N P R V 01111000 (G)(Q)(Y) 00100000 (T)(Y)(I) 1000 I(!)(.)(,) 100010001000 M,W ?1111111?000 M,W Итого ширина буквы (кроме M,W) 32 такта (ср. 48 без гигаскрина) I . ! , можно 16 тактов Можно мигать буквами (или чересстрочно) через одну: H (O) W 2+11+2+(1+15+1)+2+11+2+12+2 1 1 0 1 1 1 0 1 1 1 0 (+2)11 21 11 16 (+2) out (c),b ;0 out (#fe),a ;(11)1 nop ret c out (c),b ;(21)0 out (#fe),a ;(11)1 nop out (c),b ;(16)0 0 1 1 1 0 1 1 1 0 1 1 15 17 15 12(+2) out (c),b ;1 nop out (#fe),a ;(15)0 ret c out (c),b ;(17)1 nop out (#fe),a ;(15)0 out (c),b ;(12)1 (+2) 1 1 1 1 1 1 0 1 1 1 0 (+34) 11 16 out (c),b ;0 nop nop nop ret c ret c out (c),b ;(+34)0 out (#fe),a ;(11)1 nop out (c),b ;(16)0 0 1 1 1 0 1 1 1 0 1 1 15 17 15 12(+2) (как выше) 1 1 0 1 1 1 1 1 1 1 0 (+2)11 48 (+2) out (c),b ;0 out (#fe),a ;(11)1 ds 36/4 out (c),b ;(48)0 0 1 1 1 0 1 1 1 1 1 1 15 17 (+29) out (c),b ;1 nop out (#fe),a ;(15)0 ret c out (c),b ;(17)1 (+29) <дальше был рисунок всех букв единичками и ноликами при таком методе> Минимальная ширина буквы (с пробелами по краям) = 11 = 1+9+1 H O W I T W O R 15+1+15+1+29+8?+2+1+14+8?+29+1+15+1+15+1+ K S ? 15+1+15+1+15 = 193 такта В среднем 16 тактов на букву (без гигаск─ рина было 48) Можно чересстрочно (или мигать) отдельные столбики букв. └────────────────────────────────────────┘ Ширина 193 такта (больше экрана) улыба─ лась мало, поэтому я решил разместить на разных строках не целые буквы, а отдельные столбики букв.Описать это в текстовом фай─ ле ноликами и единичками уже было пробле─ матично, поэтому я нарисовал надпись в bmp тремя цветами:чёрный (фон),белый и зелёный (белый и зелёный - чётные и нечётные стро─ ки экрана для разных палочек) и написал генератор кода из неё. Картинку и все её промежуточные версии (в финальной версии ширина получилась 160 тактов) вы можете увидеть в упомянутом ар─ хиве в файлеhowitworks.bmp. 4. У меня была своя процедура для настрой─ ки на конкретный такт (ZX-Guide #3), но не было своего приличного плейера регистровой музыки. То, что было в Sinclair Club #5, не упаковано совсем. А то, что я писал для проекта TFM Music Maker, так и не было от─ лажено, тем более не заточено под фиксиро─ ванное число тактов. Поэтому я решил не тратить времени и откомпилировал музыку в утилите AY-ZIP-Player-Compiler Ver_1.2 by TmK/deMarche. Она имеет простой формат, основанный на разрезании музыки на фрагменты фиксирован─ ной длины и попытках найти однобайтный способ кодирования определённых групп ре─ гистров. Там всего пара проблем - что из коробки не поддерживается компиляция в несколько страниц (это я творчески преодолевал в Nedodemo 2 ) и что скомпилированную музыку надо перед использованием инициализиро─ вать. Но программа распространяется с от─ крытыми исходниками, и есть надежда на ис─ правление всех проблем в будущем. 5. Предполагалось двигать звёздочки по обеим осям в стиле последней части Shock Megademo, с коварными последствиями для расстояний между звёздами и для фазы мер─ цания. Поэтому генератор должен был делать скрипт и для звёздочек. Такой скрипт дол─ жен состоять из адресов процедур типа<па─ уза>: out (c),b и/или out (#fe),a:ret и (для вывода на экран 2-байтными записями в страничку): pop hl pop de exx out (c),d ;scrpg exx ld (hl),e inc l ld (hl),d exx out (c),e ;curpg exx ret :88 t В страничку - потому что надо два экра─ на (картинка очень сильно меняется между экранами - отрисовывать изменения долго),а сам скрипт тоже должен лежать в страничке, если мы хотим сделать много кадров. Я хо─ тел сделать побольше кадров - только для анимации картинки нужно было 12, а ведь эти фазы меняются не каждый кадр. (В итоге получилось 48 кадров, а подгонка под раз─ мер памяти шла по числу звёздочек.) Сначала я предполагал сделать другой набор процедур: ┌────────────────────────────────────────┐ - пауза N тактов, out 0 (out (c),r), out 1 (out (#fe),a) - пауза N тактов, out 1 (out (#fe),a), out 0 (out (c),r) - сдвинуть указатель в экране на NN(de?) - записать определённый байт (можно сделать для Б запись 4 байт сразу по опр. адресу) - [залить N байт нулями (11 t/b) - только для А] - [залить N байт #ff (11 t/b) - только для А] └────────────────────────────────────────┘ Но с универсальной процедурой отрисов─ ки,без всяких сдвигов указателей,было удо─ бнее,особенно когда было решено переходить по стеку. Сравните: а) в стеке по 2 байта на звезду (пауза 10 тактов). б) в hl по 1 байту на звезду (пауза минимум 19 тактов: ld a,(de):inc e:ld l,a:jp (hl) ). Генератор скрипта писался на Delphi по следующему ТЗ: ┌────────────────────────────────────────┐ Генератор звёзд должен знать: 1. Координаты звёзд. 2. Маску статичной картинки. Генератор скрипта должен знать: 1. Картинку, к которой надо стремиться. 2. Текущую картинку на одном экране (реально полученную). 3. Текущую картинку на втором экране (реально полученную). Обновлять только изменённое! └────────────────────────────────────────┘ Генератор звёзд строит картинку,к кото─ рой надо стремиться, а генератор скрипта исходит из разницы между ней и текущей ка─ ртинкой на текущем экране. Поскольку у звёзд в варианте Б есть за─ дний фронт, то надо быть осторожным на ле─ вой и правой границе экрана. Оказывается, что 32 такта "слепой зоны" между строками - это не так много,как кажется,и надо под─ гонять такт в такт: ┌────────────────────────────────────────┐ На обр.ходе включить нужный цвет как можно раньше по входе в слепую зону (32 такта). Но задержка = 11+10(ret)+12(out) = 33[+10 (ret)] - уже выход за слепую зону!!! Для звёзд на границе просто цветопереход (мы в начале слепой зоны -1..-12) Для звёзд рядом с границей пауза 10+4+12 (мы в начале слепой зоны +0..25) До следующей звезды мин.пауза 10+4+11 = 25 (25+25 = реальная зона без звёзд, так по 25 тактов с боков) При кодогенерации нерелевантны задние фро─ нты звёзд в слепой зоне и цветопереход ме─ жду строками. Начала звёзд в слепой зоне релевантны. Цветопереход между строками кодируется то─ лько при отсутствии звезды на границе.При─ чём кодируется в начале слепой зоны +25. └────────────────────────────────────────┘ Конфликты между звездой в конце одной строки и звездой в начале следующей исклю─ чаются, если, например, все звёзды распо─ ложены на чётных строках. И вот,отладив все эти генераторы (щедро снабжённые логами), я сгенерировал скрипт, написал код, запустил его, и увидел ЖУТКУЮ КАШУ НА ЭКРАНЕ. Оказывается, если звёзды двигаются по обеим осям, даже если только по чётным строкам (т.е.в постоянной фазе), глаз не может отследить мерцание правиль─ но. Это был удар. Я потратил месяц на этот проект,поэтому не мог просто так всё бросить. Поэтому во─ левым решением выключил движение звёзд по Y и собрал как есть. Получилось не так плохо, на самом де─ ле...
Другие статьи номера:
Похожие статьи:
В этот день... 21 ноября