Info Guide
#13
01 апреля 2021 |
|
Code - эффекты ротаторов и ротозумеров
О ротаторах Alone Coder Наверно, каждый помнит вращающегося Соника в демо Illusion (1996). Он строится пикселями 2x2, совершенно честным кодом типа такого: ld a,(hl) [inc/dec h/l] add a,a add a,a add a,(hl) [inc/dec h/l] add a,a add a,a add a,(hl) [inc/dec h/l] add a,a add a,a add a,(hl) [inc/dec h/l] ld (de),a inc e ;~83t/byte (260K/экран + 40K копирование) Инкременты/декременты патчатся. Это ограничивает возможности зума,но небольшой зум там есть. Похожая техника вращения используется в Eye Ache, но уже в мульти─ колоре 4x4. А что можно сделать в пиксельном разре─ шении? Можно переписать эту процедуру на пик─ сели, но тогда будет 6 fps, да и адресного пространства не хватит на картинку во весь экран. Можно натягивать текстуру через расста─ новку точек, EOR-fill и сдвиг строк, как в кубике из Mission Highly Improbable, но это тоже работает не быстро. Можно негенерировать повёрнутые байты от каждого пикселя, как в The Link, но для этого даже с небольшой картинкой понадоби─ тся больше,чем 128K ОЗУ ( The Link требует NeoGS ). Можно,наконец,сделать ротатор с пропус─ ком знакомест. Сначала рендер пропусков по отдельной карте, оттуда же берём цвет и номера тайлов. Заранее повёрнутые тайлы можно просто сдвигать, чтобы не вертеть их каждый раз. Отдельный тип тайла - прямой цветопереход, его можно рендерить... Но такой эффект ещё никто не писал. По─ этому расскажу про более простые эффекты - rotating chessfield и ротатор цветной кар─ тинки из клеточек такого же размера, как в rotating chessfield. 1. Rotating chessfield Этот эффект появился где-то в дебрях C-64, а на Speccy был реализован в деме The Board (2011). Идея его в том, что для каждого конкретного угла поворота есть всего 8*8 рисунков знакоместа (при разре─ шении U, V в 8 субтекселей), плюс столько же инверсных копий. Соответственно,задача делится на подго─ товку знакомест,ротатор и вывод знакомест. После некоторого перебора вариантов оказалось,что со знакоместами 8x4 работать проще (вывод чанков по методу Monster'а, т. е. цепочкой ret ; U и V кодируются как младший и старший байты адреса процедуры вывода чанка).Был ещё вариант 8x2, который можно было выводить прямо в ротаторе, но что-то мне в нём не понравилось. Был сделан простой ротатор 37 t/chunk: ;B,C=#X0, где X=dU,dU+1 ;D,E=#X0, где Y=dV,dV+1 ;A=U0, A'=V0 ;SP=endline MAPPERLINE dup 16 push hl add a,b ;или c (патч) ld l,a ex af,af' add a,d ;или e (патч) or chout/256 ;там выводилки чанков ld h,a push hl __=$ ;последний проход кончается здесь add a,d ;или e (патч) or chout/256 ;там выводилки чанков ld h,a ex af,af' add a,b ;или c (патч) ld l,a edup org __ jp MAPPERLQ Патч add a,b/c и add a,d/e для такого ротатора: ;H0=U0 ;D0=dU ;B=#80 ;"add a,b" ;C=0 PATCHLINEU _=MAPPERLINE dup 16 add hl,de ld a,b adc a,c ;0 ld (_+1),a __=$ ;последний проход кончается здесь add hl,de ld a,b adc a,c ;0 ld (_+14),a _=_+16 edup org __ ret Вывод чанков 8x4: ld h,a ld (hl),N inc h ld (hl),N inc h ld (hl),N inc h ld (hl),N inc l ret Чанки,конечно,можно сгенерировать зара─ нее, но в The Board они считались на лету. Сначала генерировались все нужные скосы по U и V для текущего угла, а потом они на─ кладывались по XOR во всех 16 комбинациях (точность U,V - 8 субтекселей): XORUV ;all upics XOR current vpic ld bc,upics _=2 dup 8 ;8 чанков, 8 инверсных копий dup 4 ;4 строки в чанке ld a,(bc) ;можно ускорить стеком xor (hl) ld e,_ ld (de),a cpl ld e,_+#80 ;там инверсная копия ld (de),a ;чанка inc c inc l _=_+3 ;т.к. чанк - это ld (hl),N:inc h... edup _=_+4 ;следующий чанк org $-1 dec l dec l dec l edup Генератор скосов был такой: ;U0=(256*upic/16)=upic*16=L*4 ;или V0=(256*vpic/16)=vpic*16=L*4 ld a,l add a,a add a,a xor hx ;0/#7f dup 4 ld b,a add a,a ;CY=U[7] ;A=U*2 ;или V*2 ;C=dU*2 ;или dV*2 ;D=teorfrom0/256 ;HL=upic ;или vpic FILLU ;строим рисунок байта ld a,b add a,lx ;U0=U0+dV ;или V0=V0-dU edup Рисунок байта строится записью перепол─ нений при сложении и потом "горизонтальным EOR-fill" (который - просто таблица): ;A=U*2 ;или V*2 ;C=dU*2 ;или dV*2 ;D=teorfrom0/256 ;HL=upic ;или vpic ;CY=U[7] ;или V[7] macro FILLU dup 8 rl e add a,c edup org $-1 ld a,(de) ;d=teorfrom0/256 ld (hl),a inc l endm 2. И как на этом вертеть картинку? Возьмём за образец дему Mekanix с C-64: А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Клетки 2x2,2 цвета. В клетках заполнена только каждая вторая строчка и каждый вто─ рой пиксель. Текстура 8(7?)x64. С таким размером текстуры повторы гарантированы - можно за─ ниматься копипастой кусков экрана, только они это не делают. В каждом знакоместе видно максимум 4 текселя,а это всего 16 вариантов. 4 сдвига по U, 4 по V в 16 вариантах - получается 256 чанков 8x8. Значит, надо сначала сгенерить 4 знако─ места сдвигов по U, 4 по V, потом 256 чан─ ков по or, xor, and. Вместо половины ри─ сунков можно делать инверсию атрибутов. Чтобы использовать в этих условиях обы─ чный ротатор,надо хранить в карте клетку с тремя соседями,итого 4 бита. А значит,надо 4 карты в зависимости от знаков направле─ ния,иначе содержимое клеточек не будет со─ ответствовать.Можно,конечно,менять порядок клеточек внутри этих четырёх бит за счёт смены порядка нумерации чанков. Проблема - от какой из них брать атрибуты. На C-64 чанки 8x8 аппаратные, а на Speccy их вывод (даже через строчку) зай─ мёт 62976 тактов: ld h,a dup 4 ld (hl),N inc h inc h edup org $-2 inc l ret ;17 b ;8 шт.в сегменте (U), 4(texture)*8(V)*256b :82*768=62976 Однако при выводе чанков можно заливать пустые знакоместа атрибутом (и не генерить их графику). Поэтому весь эффект лучше сразу делать в цвете, а заодно можно и в 1x1, а не через пиксель. Вывод чанков 8x8 в цвете: ld (hl),b/c/e/#30 ;attr ld h,a dup 8 ld (hl),N inc h edup org $-1 ld h,d inc l ret ;28(29) b, 137(140) t Вывод пустого чанка: ld (hl),0/#3f ;attr inc l ret Ротатор текстуры: ;addr=%11UUUuu0 VVVVVVvv ld h,a ld e,(hl) inc h ld d,(hl) push de add a,b/c ;du (патч) or #c0 ld h,a exa add a,... ;dv (патч) --- ld l,a ld e,(hl) inc h ld d,(hl) push de add a,... ;dv (патч) ld l,a exa add a,b/c ;du (патч) or #c0 ;59 t/chunk Этот вариант использован в New Wave 48K - в этой деме скосы уже не генерировались на каждом кадре,а брались готовые (загото─ влено 32 поворота). Получилось грубовато, но зато весь экран за 2 фрейма на 3,5 МГц. Статистика на картинке "-=rotate" при 32x24: пустых клеток (с учётом соседей) = 67% muz = 4000..6000 out = 45000..55000 (вывод чанков и пустых клеток) math = 500 xor = 27606 (генерация чанков из готовых скосов) patchuv = 2500 (патч add a,N в ротаторе) ротатор = 47500 итого 133000 +- 6000 Думаю,на основе этой техники можно сде─ лать и другие эффекты, как считаете?
Другие статьи номера:
Похожие статьи:
В этот день... 21 ноября