ACNews #52
16 сентября 2008

Графика - Три битплана.

<b>Графика</b> - Три битплана.
                           3 битплана                           
                         ьу Alone Coder                         
                                                                
Придумал хитрый алгоритм, который на стандартном экране может   
вывести 3 битплана с любыми сдвигами друг относительно друга (с 
шагом в 2 пикселя).                                             
                                                                
По идее надо мегабайт памяти под это дело, но можно ограничиться
128K. Имеем карты битпланов в страницах (или в одной странице) и
4 разных горизонтальных сдвига графики в разных страницах. Карт 
каждого битплана тоже нужно 4, чтобы обеспечить любой сдвиг по  
вертикали.                                                      
                                                                
Сначала просматривается верхний битплан, и на его основе в стеке
строится последовательность вызовов для его вывода. Кроме того, 
строится биткарта, описывающая, что закрыто передним планом, а  
что нет. Потом средний, таблица корректируется (знакоместа,     
которые закрыты верхним, не обрабатываются). Потом нижний       
(знакоместа, которые закрыты верхним и средним, не              
обрабатываются). Потом по стеку вызываются процедуры вывода в   
порядке нижний, средний, верхний. Проблема в том, что вывод     
должен идти исключительно в 0-й экран (т.к. графика в           
страницах). А при этом будет видно процесс обновления, даже если
в каждой строке обрабатывать все 3 битплана.                    
                                                                
Непрозрачные знакоместа (всегда 768) в обработке занимают 113   
тактов + в выводе 201 такт.                                     
Прозрачные знакоместа (порядка 100, есть только в верхних       
битпланах по периметру объектов) = 110 + 345.                   
Все остальные знакоместа - неиспользуемые (прозрачные или       
neрeкрытыe вышeлeжащими битпланами) = 67 (на верхнем битnланe   
60) + 24.                                                       
Итого примерно 240000 + 46000 + 129000 = 415000 тактов (8 fps на
нетурбо).                                                       
Для сравнения, LDIR трёх экранов (без наложения вообще) занял бы
387000 тактов.                                                  
                                                                
middlelayerloop:                                                
ld a,(de) ;занято в биткартe? 0/#ff                             
and (hl) ;прозрачное в битnланe?                                
jnz middlelayerused:                                            
push af ;#0054                                                  
push af ;#0054                                                  
dec l                                                           
dec l                                                           
inc e                                                           
jp nz,middlelayerloop                                           
middlelayernextline:                                            
                     
inc d                                                           
ld a,d                                                          
ср `конец_биткарты                                              
jnc middlelayerloop                                             
ret                                                             
                                                                
middlelayerused:                                                
ld b,a                                                          
dec l                                                           
ld с,(hl)                                                       
dec l                                                           
push ьс                                                         
ср `maskedgfx                                                   
jnc middlelayermasked                                           
хог a                                                           
ld (de),a ;занято в биткартe                                    
ld a,`A1                                                        
push af ;#ххЧЧ                                                  
inc e                                                           
jp nz,middlelayerloop                                           
jp middlelayernextline                                          
                                                                
middlelayermasked:                                              
ld ьс,A2                                                        
push ьс                                                         
inc e                                                           
jp nz,middlelayerloop                                           
jp middlelayernextline                                          
                                                                
#0054:                                                          
рор af                                                          
inc e                                                           
ret nz                                                          
jp slice                                                        
                                                                
A1:                                                             
рор hl                                                          
dup 8                                                           
ld a,(hl)                                                       
inc l                                                           
ld (de),a                                                       
inc d                                                           
edup                                                            
org $-1                                                         
ld d,b                                                          
inc e                                                           
ret nz                                                          
jp slice                                                        
                                                                
A2:                                                             
рор hl                                                          
dup 8                                                           
ld a,(de)                                                       
and (hl)                                                        
inc l                                                           
хог (hl)                                                        
inc l                                                           
ld (de),a                                                       
inc d                                                           
edup                                                            
org $-1                                                         
ld d,b                                                          
inc e                                                           
ret nz                                                          
slice:                                                          
ld a,d                                                          
add a,8                                                         
ld d,a                                                          
ld b,a                                                          
ср #58                                                          
ret с                                                           
QUIT:                                                           
                                                                
Можно добавить отдельные ветки для чисто чёрных и чисто белых   
знакомест (выигрыш 88 тактов на выводе каждого, но проигрыш 14  
тактов на каждый из 768+~100 проходов middlelayerused).         
                                                                
Хорошее ускорение - знакоместа 8(X)х16(Y), но тогда надо 8 карт 
для каждого битплана, а не 4.                                   
                                                                
Разные реализации для игр и демо. В демо можно рассчитать время 
рисования каждого кадра и как-то победить луч за счёт этого. В  
играх этого сделать нельзя. Кроме того, нужны спрайты, и под них
надо выделить целый слой. Причём графика всех сдвигов спрайтов  
должна быть в одной и той же странице (4K графики, включая      
маску). И спрайты не могут накладываться друг на друга. Можно   
сделать теневой экран, на нём проиграть 70000 тактов (но        
выиграть 40000 тактов прозрачных знакомест в слое спрайтов) и   
12K нижней памяти (LD:PUSH, хитро отсортированных, чтобы        
сделать теневой экран, на нём проиграть 70000 тактов (но        
выиграть 40000 тактов прозрачных знакомест в слое спрайтов) и   
12K нижней памяти (LD:PUSH, хитро отсортированных, чтобы        
выводить туда по inc h) - можно занять 0-й экран этим кодом. Или
90000 тактов и 7K (POP:PUSH). Зато экран будет обновляться      
целиком, и можно спрайты накладывать, поверх них надписи и т.n. 
                                                                
Но будет ли игра зрелищной в ч/б? Скорее всего, нет. Надо цвет  
на точку. Но там, наверно, надо рисовать не знакоместами, а     
длинными непрерывными вертикальными линиями. В цвете на точку   
теоретическое минимальное время (1/2 рор de:ld (hl),e/d:inc h * 
24576) ~ 400000 тактов (8 fps в турбо). Причём это в случае     
графики НЕ в странице. А если из страницы через чанковый буфер  
(максимальный размер 224*128), то лишних 160768 тактов. Опять   
делать чeрeсстрочно? (до 224*192). Чeрeсстрочно - не для игр.   
                                                                
В Livingstone 2 и других играх на том же движке было примерно 5 
fps, познакоместно, в цвете.                                    
                                                                
Как перешагивать #3dxx, которая глючит на пентагонах со старой  
прошивкой? Можно заполнять как обычно                           
(...,#Зсхх,#3dxx,#3exx,...), потом данные оттуда вывести на     
экран внешней выводилкой.                                       



Другие статьи номера:

Новости - AlCo, Т(с)S, Ldir, ТDD, Jоhn, Infо Guide, SрeссуWiki.

Игры - Прохождeниe игры Вeра.

Программистам - Чeго нe хватаeт в срeдах nрограммирования.

Графика - Три битплана.

Про автомобили - продолжение статьи для тех кому не надоело.


Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Хит - Нефтекамский хи-хи-хит-поп парад!
Вступление - авторы.
Skip_the Darkest - Aka PoP_НL^EC: Moй Сaтaнизm.
C кассеты на диск - перенос и адаптация программ с кассеты на диск.
Послание от Kaktus`a - Без названия.

В этот день...   27 апреля