Spectrofon
#19
31 марта 1996 |
|
Система - "Быстрая графика" для начинающих программистов.
(C) Bob Skath Б Ы C Т Р А Я Г Р А Ф И К А ══════════════════════════════════════ У любого программиста бывают такие си- туации, когда он уже вроде бы и знает ас- семблер, и все равно не может написать ни- чего путного и только с завистью смотрит на шесть ПЛАВНО бегущих по бордюру и тро- туару скроллеров у какого нибудь новояв- ленного MAX IWAMOTO и сравнивает со своей убогой бегушкой размером 3*3 пиксела, ко- торая судорожно передергивается при каж- дом в муках появляющимся новым символом. А все дело в том, что программирование тако- го рода эффектов (как и почти всех динами- ческих игрушек) построено на принципе так называемой "быстрой" графики. Вот как, например, выглядит программа программиста (боже ты мой, что я пишу), ко- торый только-только освоил работу со спрайтами, и голова которого занята струк- турным программированием : DI ; Пока все понятно LD HL,#4000 ; Это тоже ясно LD DE,SPRITE ; DE - адрес спрайта в памяти LD BC,#0504 ; В - размер Х, С - размер Y LOOP1 PUSH BC ; сохраняем BC PUSH HL ; сохраняем текущий адрес в экране LOOP2 LD A,(DE) ; берем байт спрайта LD (HL),A ; помещаем его на экран INC HL ; увеличиваем адрес на экране INC DE ; увеличиваем адрес на спрайт DJNZ LOOP2 ; пока Х<>0 POP HL ; восстанавливаем адрес в экране POP BC ; восстанавливаем счетчик размера CALL NXTLIN ; определяем следующую линию в экране DEC C ; размер Y закончен ? JR NZ,LOOP1 ; если нет то повторить цикл. .... NXTLIN INC H ; подпрограмма определения последу- LD A,H ; ющей линии в видеопамяти. На входе AND 7 ; в HL - адрес в экране. На выходе RET NZ ; нужный адрес опять в HL. LD A,L ADD A,#20 LD L,A RET C LD A,H SUB 8 LD H,A RET Ну что ж... Вполне приличная программа для вывода на экран статических картинок, но вся беда начинается, когда этот самый программист, окрыленный предыдущим успе- хом, пытается переделать сию программку для вывода ДВИЖУЩИХСЯ спрайтов да еще и большего размера, оперируя регистровой па- рой HL на входе, что бы выводить изображе- ния в различные части экрана. Тут то и на- чинается самое интересное... Изображение начинает передергиваться, мерцать и делать все, что бы заставить го- ре-программиста кусать локти от ярости. Так вот я и решил немного помочь сим людям, дабы облегчить их страдания своим циклом статей на эту тему. Весь принцип быстрой графики состоит в том, что изобра- жение строится не непосредственно на экра- не компьютера, а в так называемом вир- туальном экране, то есть где-то в глубинах памяти машины. Картинка сначала строится вся - спрайт за спрайтом накладываются в нужной последовательности подпрограммой, похожей на вышеприведенную, с тем отли- чием, что в виртуальном буфере строки растра идут последовательно одна за дру- гой, и лишь затем как один гигантских раз- меров спрайт выводится на экран. Тут, как я вижу, половина читателей этой статьи с криком : "Wooooow, я поооо- няяял !!!!" лихо сбрасывают машину и пос- пешно загружают TASM и SPRITE EDITOR. Ну ничего, через пару минут они убедят- ся, что все не так просто и понятно, как кажется на первый раз. Все дело в том что картинку нужно успеть перестроить не бо- лее чем за один промежуток между прерыва- ниями, иначе будет борода, и вся работа пойдет насмарку. А это не так то просто, что доказывает простой расчет времени вы- полнения вышеприведенной программы. Навер- ное, кое кто из читателей уже повесили но- сы и подумали о бренности всего сущего, но ничего - вспомните просто ROBOCOP'a или там WEC LE MAN. Там ведь ничего не дер- гается ??? Значит можно ??? Конечно можно !!! Только нужно учесть несколько момен- тов : 1. Обычно не требуется перестраивать весь экран, хватает перерисовки какой то его части а остальное - статичная информация ( как количество жизней, название MEGADEMO и т.д. ) 2. Нужно для перестроения отбросить вся- кие глупые мысли о структурном подходе и вложенных циклах ( это вам не сортировка базы данных по 172627373 полям ) 3. Необходимо немного подумать. И все !!! В качестве примера я приведу процедуру, которая строит картинку размером 26 знако- мест *128 пикселов в верхней части экрана. DI ; Прерывания обязательно DI !!! LD C,#48 ; Маркер перехода в другую треть экрана LD HL,SCR+28+1 ; Адрес вывода в экран с учетом вывода справа-налево LD (ADDR1+1),HL ; Установка экранного адреса LD IX,PICT+#11 ; Адрес виртуального экрана в памяти с учетом чтения из се- редины CALL ROUT1 ; Рисование первой трети экрана LD C,#50 ; Маркер перехода в третью треть экрана LD HL,SCR1+28+1 ; Адрес вывода в экран во второй трети LD (ADDR1+1),HL ; Установка экранного адреса ROUT1 LD B,64 ; Количество линий рисуемых за один проход процедуры LOOP2 LD (SPSAVE),SP ; Сохраняем SP для корректного выхода LD SP,IX ; Текущий адрес для чтения POP AF ; Чи POP DE ; та POP HL ; ем EXX ; POP BC ; кар POP DE ; тин POP HL ; ку ADDR1 LD SP,0000 ; Здесь был установлен адрес для записи картинки в экран PUSH HL ; Запи PUSH DE ; сы PUSH BC ; ваем EXX ; PUSH HL ; кар PUSH DE ; тин PUSH AF ; ку LD (ADDR2+1),SP ; Сохраняем текущий адрес записи LD SP,#FFF2 ; Устанавливаем регистровую ADD IX,SP ; пару IX на следующие байты LD SP,IX ; виртуального экрана POP AF ; Чи POP DE ; та POP HL ; ем EXX ; EX AF,AF' ; POP AF ; кар POP BC ; тин POP DE ; ку POP HL ; ADDR2 LD SP,0000 ; Здесь был установлен адрес для записи в экран PUSH HL ; За PUSH DE ; пи PUSH BC ; сы PUSH AF ; ва EXX ; ем EX AF,AF' ; PUSH HL ; кар PUSH DE ; тин PUSH AF ; ку LD HL,#011A ; Вычисляем адрес последующей ADD HL,SP ; линии в этой же трети экрана LD A,H ; Проверяем не вышли ли CP C ; мы в другую треть экрана JR C,LOOP1 ; или в другое знакоместо LD DE,#F820 ; Если да, то производим ADD HL,DE ; коррекцию LOOP1 LD (ADDR1+1),HL ; Сохраняем текущий адрес для записи в экран LD SP,46 ; Следующая линия виртуального ADD IX,SP ; буфера LD SP,IX ; DJNZ LOOP2 ; Если цикл не исчерпан-повто- рить SAVESP LD SP,000 ; Восстановить стек RET ; Возврат Ну как ??? На первый взгляд громоздко, но работает прекрасно. Да, кстати, ясно почему такая скорость работы ?? Правильно, потому что за один раз читается и пишется по два байта. Следует обpатить внимание на то, что для ускоpения pаботы здесь отсутствует подпpогpамма опpеделения последующей стpо- ки, а вывод в каждую тpеть пpоисходит от- дельно. Таким образом можно выводить на экран буфера любого размера (но только кратного по Х двум, интересно почему ??) с до- вольно приличной скоростью для анимации или оживления ваших игрушек. Ну ладно... На сегодня хватит... В сле- дующий раз я расскажу о том как быстро впечатывать спрайты в виртуальный буфер с маской и без. И еще... Но об этом в сле- дующий раз. Bob Skath. 1996. Latvia. Daugavpils. ─════─
Другие статьи номера:
Похожие статьи:
В этот день... 13 ноября