Страница Ивана Рощина > Статьи >

© Иван Рощин, Москва

ZXNet: 500:95/462.53
E-mail: bestview@mtu-net.ru
WWW: http://www.ivr.da.ru

Графический эффект «цветные полосы»

(«ZX-Ревю» 7—10/1997)
Дата последнего редактирования: 30.11.2002.

    Предлагаю вашему вниманию написанную мной программу, реализующую красивый графический эффект: по экрану движутся цветные полосы, плавно переходящие друг в друга. Этот полноэкранный real-time эффект занимает всего лишь около 60% времени процессора. Порядок следования полос и плавность перехода между ними можно изменять.

;****************************************************

CLR0    EQU     0     ;Цвета полос
CLR1    EQU     1     ;(сверху вниз).
CLR2    EQU     2
CLR3    EQU     3
CLR4    EQU     4
CLR5    EQU     5
CLR6    EQU     6

;****************************************************

DEMO    LD      C,0        ;Смещение по вертикали.

;Полосы поднимаются:

LOOP1   CALL    SHOW       ;Рисуем полосы.
        CALL    KEY        ;Что-нибудь нажато?
        RET     NZ         ;Если да, выходим.
        INC     C          ;Увеличили смещение.
        LD      A,C        ;Достигли максимального?
        CP      TABMAXA-23
        JP      NZ,LOOP1   ;Если нет, продолжаем.

;Полосы опускаются:

        DEC     C          ;Уменьшили
        DEC     C          ;смещение.
LOOP2   CALL    SHOW       ;Рисуем полосы.
        CALL    KEY        ;Что-нибудь нажато?
        RET     NZ         ;Если да, выходим.
        DEC     C          ;Уменьшили смещение.
        LD      A,C        ;Достигли минимального?
        CP      #FF
        JP      NZ,LOOP2   ;Если нет, продолжаем.

        LD      C,1        ;Иначе переходим
        JP      LOOP1      ;на начало программы.

;***************************************
;Процедура SHOW.
;
;Вход: C - смещение полос по вертикали
;          (в знакоместах).
;Выход: изображена соотв. картинка.

SHOW ;Сначала изображаем атрибуты:

        LD      DE,TABL_A ;Адрес таблицы атрибутов.
        LD      H,0       ;HL = смещение.
        LD      L,C
        ADD     HL,DE     ;Прибавляем смещение.
        LD      DE,#5800  ;Начало файла атрибутов.

        HALT    ;Ждем начала кадра.
        DI      ;Запрещаем прерывания, т.к.
                ;будем манипулировать со стеком.

NEXT_A  LD      A,(DE)    ;Какой атрибут изображен?
        CP      (HL)      ;То, что надо?
        JP      Z,RETU    ;Если да, не пересылаем.

        PUSH    HL        ;Сохранили адрес источника.

        LD      A,(HL)    ;Байт из источника.
        LD      (M1+1),SP ;Сохранили SP (обратите внимание,
                          ;куда).
        LD      HL,#20    ;Формируем новый
        ADD     HL,DE     ;адрес стека.
        LD      SP,HL
        LD      D,A       ;Чем заполнять
        LD      E,A       ;строку.

        PUSH    DE       ;Формируем одну
        PUSH    DE       ;строку.
        PUSH    DE
        PUSH    DE
        PUSH    DE
        PUSH    DE
        PUSH    DE
        PUSH    DE
        PUSH    DE
        PUSH    DE
        PUSH    DE
        PUSH    DE
        PUSH    DE
        PUSH    DE
        PUSH    DE
        PUSH    DE

        EX      DE,HL    ;В DE - новый адрес приемника.

M1      LD      SP,0     ;Восстановили SP.
                         ;Эта команда загрузки SP
                         ;выполняется вдвое быстрее,
                         ;чем команда LD SP,(NN).
        POP     HL       ;Восстановили HL.
        JP      NE_RETU  ;Кстати, команда JP
                         ;выполняется быстрее,
                         ;чем команда JR.

;Если строку не пришлось заполнять,
;увеличиваем DE (адрес приемника) на #20:

RETU    LD      A,#20    ;Выглядит это
        ADD     A,E      ;непривычно, но
        LD      E,A      ;работает
        LD      A,0      ;быстрее.
        ADC     A,D
        LD      D,A

;Иначе адрес приемника уже увеличен.

NE_RETU INC     HL      ;Адрес источника.
        LD      A,D
        CP      #5B
        JP      NZ,NEXT_A

;Теперь рисуем картинку:

        LD      L,C      ;Смещение в знакоместах.
        SLA     L        ;Умножаем на 8.
        SLA     L
        SLA     L
        RES     7,L
        LD      B,L      ;Получили смещение в таблице.

        LD      H,0      ;HL = смещение в таблице.
        LD      DE,TABL  ;Адрес таблицы.
        ADD     HL,DE
        EX      DE,HL
        LD      HL,#4000 ;Начало дисплейного файла.

;Здесь, наоборот, HL - адрес приемника, а
;DE - адрес источника.

NEXT    LD      A,(DE)    ;Изображаемый байт.
        CP      (HL)      ;Сравниваем с изображенным.
        JP      Z,RET3    ;Если равны, не пересылаем.

        PUSH    HL        ;Сохранили адрес приемника.

;Увеличиваем HL (адрес приемника) на #20:

        LD      A,#20    ;Выглядит это
        ADD     A,L      ;непривычно, но
        LD      L,A      ;работает
        LD      A,0      ;быстрее.
        ADC     A,H
        LD      H,A

        LD      (M2+1),SP ;Сохранили SP.
        LD      SP,HL     ;SP указывает на конец строки.

        LD      A,(DE)
        LD      H,A      ;Чем заполнять
        LD      L,A      ;строку.

        PUSH    HL       ;Формируем одну
        PUSH    HL       ;строку.
        PUSH    HL
        PUSH    HL
        PUSH    HL
        PUSH    HL
        PUSH    HL
        PUSH    HL
        PUSH    HL
        PUSH    HL
        PUSH    HL
        PUSH    HL
        PUSH    HL
        PUSH    HL
        PUSH    HL
        PUSH    HL

M2      LD      SP,0  ;Восстановили SP.
        POP     HL    ;Восстановили адрес приемника.

RET3    INC     DE    ;Увеличили адрес источника.
        INC     B     ;Увеличили счетчик.
        LD      A,B
        CP      TABMAX    ;Достигнут max. адрес?
        JP      NZ,TAB_OK
        LD      B,0       ;Если да, обнуляем счетчик
        LD      DE,TABL   ;и переходим к началу таблицы.

TAB_OK  INC     H         ;Определяем
        LD      A,H       ;адрес новой
        AND     7         ;строки на
        LD      A,H       ;экране
        JP      NZ,NEW_OK ;по адресу
        LD      A,L       ;предыдущей
        ADD     A,32      ;строки.
        LD      L,A
        LD      A,H
        JP      C,NEW_OK
        LD      A,H
        SUB     8
        LD      H,A

NEW_OK  CP      #58
        JP      NZ,NEXT

        EI
        RET

;***************************************

TABMAX  EQU     16*8   ;Размер массива данных (см. ниже).

TABL    DB      %00000000  ;Данные для формирования
        DB      %00000000  ;плавного перехода между
        DB      %00000000  ;цветными полосами.
        DB      %00000000  ;Кстати, от этих данных
        DB      %00000000  ;зависит быстродействие
        DB      %00000000  ;процедуры SHOW.
        DB      %00000000
        DB      %00000000
        DB      %00000000
        DB      %00000000
        DB      %00000000
        DB      %00000000
        DB      %00000000
        DB      %00000000
        DB      %00000000
        DB      %00000000

        DB      %00001000
        DB      %00000000
        DB      %10000000
        DB      %00000000
        DB      %00001000
        DB      %10000000
        DB      %00001000
        DB      %10000000

        DB      %00100010
        DB      %10001000
        DB      %00100010
        DB      %10001000
        DB      %00100010
        DB      %10001000
        DB      %00100010
        DB      %10001000
        DB      %00100010
        DB      %10001000
        DB      %00100010
        DB      %10001000
        DB      %00100010
        DB      %10001000
        DB      %00100010
        DB      %10001000

        DB      %00100010
        DB      %01010101
        DB      %10001000
        DB      %01010101
        DB      %00100010
        DB      %01010101
        DB      %10001000
        DB      %01010101
        DB      %00100010
        DB      %01010101
        DB      %00100010
        DB      %01010101
        DB      %10001000
        DB      %01010101
        DB      %00100010
        DB      %01010101
        DB      %10001000
        DB      %01010101
        DB      %00100010
        DB      %01010101

        DB      %10101010
        DB      %01010101
        DB      %10101010
        DB      %01010101
        DB      %10101010
        DB      %01010101
        DB      %10101010
        DB      %01010101
        DB      %10101010
        DB      %01010101
        DB      %10101010
        DB      %01010101
        DB      %10101010
        DB      %01010101
        DB      %10101010
        DB      %01010101
        DB      %10101010
        DB      %01010101
        DB      %10101010
        DB      %01010101
        DB      %10101010
        DB      %01010101
        DB      %10101010
        DB      %01010101

        DB      %10101010
        DB      %01110111
        DB      %10101010
        DB      %11011101
        DB      %10101010
        DB      %01110111
        DB      %10101010
        DB      %11011101
        DB      %10101010
        DB      %01110111
        DB      %10101010
        DB      %11011101
        DB      %10101010
        DB      %01110111
        DB      %10101010
        DB      %11011101
        DB      %10101010
        DB      %01110111
        DB      %10101010
        DB      %11011101

        DB      %11011101
        DB      %01110111
        DB      %11011101
        DB      %01110111
        DB      %11011101
        DB      %01110111
        DB      %11011101
        DB      %01110111
        DB      %11011101
        DB      %01110111
        DB      %11011101
        DB      %01110111
        DB      %11011101
        DB      %01110111
        DB      %11011101
        DB      %01110111

        DB      %01111111
        DB      %11110111
        DB      %01111111
        DB      %11110111
        DB      %11111111
        DB      %01111111
        DB      %11111111
        DB      %11110111

;********************************************************

TABMAXA EQU     6*16+2 ;Размер массива данных (см. ниже).

TABL_A  DB      CLR0*8+CLR1   ;От этих данных зависит
        DB      CLR0*8+CLR1   ;цвет каждой полосы.
        DB      CLR0*8+CLR1
        DB      CLR0*8+CLR1
        DB      CLR0*8+CLR1
        DB      CLR0*8+CLR1
        DB      CLR0*8+CLR1
        DB      CLR0*8+CLR1
        DB      CLR0*8+CLR1
        DB      CLR0*8+CLR1
        DB      CLR0*8+CLR1
        DB      CLR0*8+CLR1
        DB      CLR0*8+CLR1
        DB      CLR0*8+CLR1
        DB      CLR0*8+CLR1
        DB      CLR0*8+CLR1

        DB      CLR1*8+CLR2
        DB      CLR1*8+CLR2
        DB      CLR1*8+CLR2
        DB      CLR1*8+CLR2
        DB      CLR1*8+CLR2
        DB      CLR1*8+CLR2
        DB      CLR1*8+CLR2
        DB      CLR1*8+CLR2
        DB      CLR1*8+CLR2
        DB      CLR1*8+CLR2
        DB      CLR1*8+CLR2
        DB      CLR1*8+CLR2
        DB      CLR1*8+CLR2
        DB      CLR1*8+CLR2
        DB      CLR1*8+CLR2
        DB      CLR1*8+CLR2

        DB      CLR2*8+CLR3
        DB      CLR2*8+CLR3
        DB      CLR2*8+CLR3
        DB      CLR2*8+CLR3
        DB      CLR2*8+CLR3
        DB      CLR2*8+CLR3
        DB      CLR2*8+CLR3
        DB      CLR2*8+CLR3
        DB      CLR2*8+CLR3
        DB      CLR2*8+CLR3
        DB      CLR2*8+CLR3
        DB      CLR2*8+CLR3
        DB      CLR2*8+CLR3
        DB      CLR2*8+CLR3
        DB      CLR2*8+CLR3
        DB      CLR2*8+CLR3

        DB      CLR3*8+CLR4
        DB      CLR3*8+CLR4
        DB      CLR3*8+CLR4
        DB      CLR3*8+CLR4
        DB      CLR3*8+CLR4
        DB      CLR3*8+CLR4
        DB      CLR3*8+CLR4
        DB      CLR3*8+CLR4
        DB      CLR3*8+CLR4
        DB      CLR3*8+CLR4
        DB      CLR3*8+CLR4
        DB      CLR3*8+CLR4
        DB      CLR3*8+CLR4
        DB      CLR3*8+CLR4
        DB      CLR3*8+CLR4
        DB      CLR3*8+CLR4

        DB      CLR4*8+CLR5
        DB      CLR4*8+CLR5
        DB      CLR4*8+CLR5
        DB      CLR4*8+CLR5
        DB      CLR4*8+CLR5
        DB      CLR4*8+CLR5
        DB      CLR4*8+CLR5
        DB      CLR4*8+CLR5
        DB      CLR4*8+CLR5
        DB      CLR4*8+CLR5
        DB      CLR4*8+CLR5
        DB      CLR4*8+CLR5
        DB      CLR4*8+CLR5
        DB      CLR4*8+CLR5
        DB      CLR4*8+CLR5
        DB      CLR4*8+CLR5

        DB      CLR5*8+CLR6
        DB      CLR5*8+CLR6
        DB      CLR5*8+CLR6
        DB      CLR5*8+CLR6
        DB      CLR5*8+CLR6
        DB      CLR5*8+CLR6
        DB      CLR5*8+CLR6
        DB      CLR5*8+CLR6
        DB      CLR5*8+CLR6
        DB      CLR5*8+CLR6
        DB      CLR5*8+CLR6
        DB      CLR5*8+CLR6
        DB      CLR5*8+CLR6
        DB      CLR5*8+CLR6
        DB      CLR5*8+CLR6
        DB      CLR5*8+CLR6

        DB      CLR6*8+CLR6
        DB      CLR6*8+CLR6

;**************************************
;Процедура KEY возвращает флаг Z=0,
;если на клавиатуре что-нибудь нажато.

KEY     XOR     A
        IN      A,(254)
        AND     %00011111
        CP      %00011111
        RET

Другие мои статьи о программировании графических эффектов:

1. 

«Драйвер экрана для компьютера „Пентагон-128“». «ZX-Ревю» 3—4/1997.

2. 

«Два графических эффекта». «ZX-Ревю» 3—4/1997.

3. 

«Несколько графических эффектов». «ZX-Ревю» 11—12/1997.

4. 

«Графический эффект „iris“». ZX Format #8, Adventurer #8.

5. 

«Улучшенный эффект из demo „Art Vision“». Adventurer #8.

6. 

«Оптимизация на примере intro „Start“». «Радиомир. Ваш компьютер» 7—10/2001.

Страница Ивана Рощина > Статьи >