О туннелях и небоскребах
Alone Coder
Прямоугольный туннель появился ещё в
волосатом году в сеговской игре Galaxy
Force II. На Спектруме мы его впервые на─
блюдали в демо Yes (1997).
Разумеется, для отрисовки такого тун─
неля не нужно рисовать прямоугольники. Он
строится по строчкам. Обычно в одной стро─
чке добавляется проекция не более чем од─
ного прямоугольника. Но если и больше - не
страшно. Главное - во всём кадре видно не
более N разных строчек, где N - общее чис─
ло прямоугольников в туннеле (включая вне─
шний, который во весь экран).
Эффект с небоскрёбами при виде сверху
тоже рисуется ограниченным числом строчек
(в данном случае 2*N,где N - число слоёв).
Туда же зуминг шахматных сеток, бегущих
строчек и т.п.
Итак.
1. Nedotunnel
В деме Yes туннель был чёрно-белым, но
ничто не мешает его раскрасить. Например,
в мультиколоре 8x2 (всего лишь стек пере─
ставлять между строчками). Но мне такой
туннель понадобился в Nedodemo 2, а дема
эта под ATM-Turbo 2+ (рекомендуется ZX Evo
baseconf ),так что я строил этот туннель в
аппаратном мультиколоре объёмом аж 32000
байт.
Задача разбивается на следующие шаги:
- нагенерировать координаты N прямоуго─
льников;
- нагенерировать N строчек с последова─
тельным добавлением прямоугольников;
- составить массив,где для каждой строки
экрана указано,какую графику использовать;
- вывести экран по этому массиву (в слу─
чае мультиколора - тривиально, а в случае
жирного АТМного экрана надо подумать).
Поскольку строчки содержат много одина─
ковых байтов подряд, можно генерировать не
графику строчек, а код для их вывода. Но
все 32000 байт мы выводить не будем, выво─
дить будем только атрибуты, как и для про─
граммного мультиколора.
Также отметим, что в аппаратном мульти─
колоре ATM-Turbo есть два чередующихся
слоя экрана.
Можно оба слоя вывести в рамках одной
процедуры:
dup 20
[ld de/d/e,...]
push de
edup
ld sp,ix
dup 20
[ld de/d/e,...]
push de
edup
jp (iy)
Чтобы сгенерировать такую оптимизиро─
ванную процедуру (а всего их, напомню, N),
удобно иметь сначала графику строки в ли─
нейном виде.
Вызывалка может выглядеть так (можно
совместить с вычислением массива строк,так
что массив будет и не нужен):
<логика>
ld sp,scr+#2000
ld ix,scr
ld iy,$+ /ld ly,$+
jp (hl)
и так для каждой строки.
Логика просто следит, пересекли ли мы
верхнюю (или нижнюю) границу очередного
прямоугольника,если да,то пересекли ли для
следующего и т. д., с каждым разом меняя
номер рисуемой графики строчки.
Расчёт координат тоже ничего особенного
не представляет - опишу его в двух словах,
подробности можете посмотреть в исходниках
Nedodemo 2.
У каждого прямоугольника есть виртуаль─
ные X,Y,Z и виртуальные размеры (в данном
случае у всех одинаковые).
По идее размеры слоёв убывают как 1/N.
Но при плавном зуме N будет дробным.
Так что лучше иметь массив всех видимых
размеров прямоугольников и шагать по этому
массиву большими шагами.
Прямоугольники не только приближаются,
но и колеблются по X и Y (например, по си─
нусам). Сдвиги прямоугольников по X и Y в
проекции экрана должны быть сообразны их
масштабу.
Вот и весь эффект.
2. Skyscrappers
Эффект с небоскрёбами с высоты птичьего
полёта я писал для The Board II (эта дема
написана раньше предыдущей). Там тоже ап─
паратный мультиколор ATM-Turbo и тоже было
два варианта:
А) заранее готовим все строки и юзаем их
Б) строку апдейтим по ходу отрисовки.
Прикинул и решил сгенерировать все воз─
можные строки, и их оптимизировать в ld:
push. Все возможные строки для случая 4
слоёв (в деме их столько,а не больше,пото─
му что иначе не получался красивый цвето─
переход):
пусто
0
01
012
0123
123
23
3
итого 8 строк.
Можно представить себе промежуточный
формат строки как байт на точку,каждый бит
- наличие определённого слоя небоскрёба.
Чтобы сгенерировать эти битпланы, нужно
запустить зумер для каждого из 4 битпланов
и каждый байт либо не трогать, либо пропи─
сать нужный бит в каждый из битпланов. Из
такого байта с битпланами можно вычислить
видимый цвет по таблице, а заодно пересчи─
тать в два пикселя в байте и в два череду─
ющихся слоя.
Удалось реализовать это без промежуточ─
ного буфера, сразу в два пикселя в байте.
Слои накладывает сама палитра, а зумер од─
ного битплана состоит из цикла пропуска и
цикла рисования залитой части.
Цикл пропуска (b=ширина пропуска):
ZOOMSKIP
_=0
dup wid/2
_=_+42
djnz $+26 ;обходим запись и jp
;кончился пропуск
ld h,c
ld d,ly
dup 4
ld a,(hl)
or d
ld (hl),a ;правый пиксель
inc h
edup
org $-1
inc l
ld b,hx ;ширина залитой части-1
jp ZOOMWRITE+_ ;идём на рисование
;+26 - это сюда
inc l
djnz $+7
;кончился пропуск
ld b,lx ;ширина залитой части
jp ZOOMWRITE+_
edup
Цикл рисования (b=ширина залитой части):
ZOOMWRITE
_=0
dup wid/2
_=_+34
djnz $+26 ;обходим запись и jp
ld h,c
ld d,hy
dup 4
ld a,(hl)
or d
ld (hl),a ;левый пиксель
inc h
edup
org $-1
inc l
ld b,hx ;ширина пропуска-1
jp ZOOMSKIP+_
;+26 - это сюда
ld h,c
dup 4
ld (hl),e ;левый+правый пиксель
inc h
edup
org $-1
inc l
djnz $+7
ld b,lx ;ширина пропуска
jp ZOOMSKIP+_
edup
В любом случае, надо будет пересчитать
сгенерированные строки (кроме пустой) в
ld:push.
Вот таким кодом (для упрощения считаем,
что d и e одновременно не меняются):
pop af ;два пикселя от зумера
;(второй слой пропускаем)
cp b
jr z,$+10
exd
ld (hl),#16 ;"ld d,"
exd
inc e
ld (de),a
inc e
ld b,a
pop af ;два пикселя от зумера
;(второй слой пропускаем)
cp c
jr z,$+10
exd
ld (hl),#1e ;"ld e,"
exd
inc e
ld (de),a
inc e
ld c,a
ld a,#d5 ;"push de"
ld (de),a
inc e
Вызывалка ld:push'ей (она сама вычисля─
ет, какие слои активны в данной строке -
код похож на 4-канальный плейер на бипере
:))
exx
dec h
jr nz,$+5
xor 8
ld h,l
dec d
jr nz,$+5
xor 4
ld d,e
djnz $+5
xor 2
ld b,c
exx
djnz $+5
xor 1
ld b,c
ld h,a ;%1111EDCB
ld h,(hl)
ld sp,первыйслой
ld ix,второйслой
ld iy/ly,следующаявызывалка
jp (hl)
...
ld:push *20
ld sp,ix
ld:push *20
jp (iy) ;на следующую вызывалку
В The Board II строки повторяются (всё
равно атрибутные "пиксели" широкие, а так
получатся квадратные), так что на каждой
второй строке расчёта нет, а стоит опять:
ld sp,первыйслой
ld ix,второйслой
ld iy/ly,следующаявызывалка
jp (hl)
В таком духе можно писать и вызывалки
для зума, скролла или ещё чего-нибудь, но
обычно я так не делаю. Главное,что работа─
ет! :)
Other articles: