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

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

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

Два графических эффекта

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

Предлагаю вашему вниманию две процедуры на ассемблере, реализующие красивые и необычные эффекты (по крайней мере, мне таких видеть не приходилось).

Перед запуском первой процедуры на экране должна быть какая-нибудь картинка. Вы увидите, как эта картинка постепенно изменяется. Для выхода достаточно нажать любую клавишу.

Этот эффект вы можете применить в своей программе, например, так: если пользователь продолжительное время не нажимает на клавиши, сохраняем содержимое экранной области и запускаем процедуру. Как только какая-нибудь клавиша будет нажата, восстанавливаем картинку на экране (кстати, в этом может помочь вторая процедура).

Кстати, процедуру нетрудно изменить. Попробуйте в указанных местах поставить команды CALL SET_0 или CALL SET_1, посмотрите, что получится.

EFFECT  LD      HL,0         ;адрес в ROM
        LD      (ADR_ROM),HL

;Получаем в DE случайные координаты
;очередной точки и сохраняем в памяти:

NEXT_X  LD      HL,(ADR_ROM)
        LD      B,(HL)  ;координата x
        INC     HL
        LD      A,R
        XOR     B
        LD      R,A
        LD      D,A

NEXT_Y  LD      B,(HL)  ;координата y
        INC     HL
        LD      A,R
        XOR     B
        CP      191
        JR      NC,NEXT_Y
        LD      E,A
        LD      (KRDS),DE
        LD      (ADR_ROM),HL
        LD      A,(HL)
        PUSH    AF

        CALL    GET_P    ;узнали цвет этой точки (0..1)
        LD      (COL),A

;Выбираем направление, в котором
;находится вторая точка, и узнаем ее
;координаты:

        POP     AF
        AND     3        ;число 0..3 - номер направления
        LD      HL,TABLE
        LD      B,0
        LD      C,A
        ADD     HL,BC
        LD      A,(HL)   ;на сколько изменять y
        PUSH    AF
        LD      BC,4
        ADD     HL,BC
        LD      A,(HL)   ;на сколько x

        ADD     A,D
        LD      D,A
        POP     AF       ;на сколько y
        ADD     A,E
        LD      E,A
        CP      192
        JR      NZ,NE_192
        LD      E,190
NE_192  CP      #FF
        JR      NZ,X_OK
        LD      E,1

X_OK    CALL    GET_P  ;Узнали цвет второй точки.
        LD      IX,COL ;Сравниваем его с цветом первой точки.
        CP      (IX)   ;Если они одинаковы,
        JR      Z,H_OK ;менять точки местами не надо.

        PUSH    DE        ;Сохр. коорд. второй точки
        LD      DE,(KRDS) ;Рисуем этим цветом первую точку.

        CP      0        ;Эти 5 команд можно заменить на
        PUSH    AF       ;команду CALL SET_0 или
        CALL    Z,SET_0  ;CALL SET_1, при этом наблюдаемый
        POP     AF       ;эффект изменится.
        CALL    NZ,SET_1

        POP     DE     ;Восст. координаты второй точки.

        LD      A,(COL)  ;Эти 6 команд можно заменить на
        CP      0        ;команду CALL SET_0 или
        PUSH    AF       ;CALL SET_1, при этом наблюдаемый
        CALL    Z,SET_0  ;эффект изменится.
        POP     AF
        CALL    NZ,SET_1

        LD      A,(ADR_ROM+1) ;Проверяем, не достигнут ли
        AND     #1F           ;предельный допустимый адрес
        LD      (ADR_ROM+1),A ;в ROM Спектрума.

H_OK    XOR     A          ;Проверяем, не нажато ли
        IN      A,(#FE)    ;что-нибудь на клавиатуре.
        CPL
        AND     %00011111
        JP      Z,NEXT_X
        RET                ;Если да, выходим.

SET_1   CALL    BYTE
        LD      B,(HL)
        OR      B
        LD      (HL),A
        RET

SET_0   CALL    BYTE
        CPL
        LD      B,(HL)
        AND     B
        LD      (HL),A
        RET

GET_P   CALL    BYTE
        LD      B,(HL)
        AND     B
        RET     Z
        LD      A,1
        RET

BYTE    PUSH    DE
        LD      A,E
        AND     A
        RRA
        SCF
        RRA
        AND     A
        RRA
        XOR     E
        AND     #F8
        XOR     E
        LD      H,A
        LD      A,D
        RLCA
        RLCA
        RLCA
        XOR     E
        AND     #C7
        XOR     E
        RLCA
        RLCA
        LD      L,A
        LD      A,D
        AND     7
        LD      B,A
        INC     B
        LD      A,1
LOOP    RRCA
        DJNZ    LOOP
        POP     DE
        RET

KRDS    DW      0  ;координаты точки
COL     DB      0  ;цвет точки
TABLE   DB      0,#FF,0,1
        DB      1,0,#FF,0
ADR_ROM DW      0

Вторая процедура предназначена для вывода картинки на экран. Перед её запуском в регистровой паре HL нужно указать адрес картинки.

DEMO    LD      HL,#C000    ;адрес выводимой картинки
        CALL    EFFECT
        RET

;***************************************
;Процедура EFFECT осуществляет вывод
;картинки на экран.
;Вход: HL - адрес выводимой картинки.
;При вызове прерывания должны быть
;разрешены!

Q       EQU     7       ;Q можно менять в
Q_2     EQU     Q*Q     ;пределах [1..8], от его
                        ;значения зависит эффект.

EFFECT  LD      DE,#C000     ;Настройка адреса
        ADD     HL,DE        ;внутри процедуры.
        LD      (ADR1+1),HL
        LD      D,#58        ;Переносим файл
        ADD     HL,DE        ;атрибутов.
        LD      BC,#300
        LDIR            ;После этого E=0.
        LD      D,-Q_2  ;D - номер текущей строки.

;В регистре E - сколько строк обработано (пока 0).

LOOP1   HALT                    ;задержка
        LD      BC,Q+1*256+Q_2  ;B - счетчик, C - смещение

LOOP2   LD      A,D     ;Номер текущей строки.
        ADD     A,C     ;Прибавляем смещение.
        CP      192     ;Если номер строки больше 192,
        JR      NC,NEXT ;пропускаем ее.

        EXX
        CALL    ADR_STR ;Иначе узнаем адрес строки.
ADR1    LD      BC,0
        ADD     HL,BC   ;В HL - адрес в буфере.
        LD      BC,#20  ;Длина одной строки.
        LDIR            ;Вывели на экран.
        EXX             ;Увеличиваем количество
        INC     E       ;обработанных строк.

NEXT    LD      A,C     ;Уменьшили смещение.
        SUB     Q
        LD      C,A
        DJNZ    LOOP2   ;Повторяем цикл.

        INC     D       ;Увеличили номер тек. строки.

;Если он делится на (Q+1), увеличиваем его на Q.

        LD      B,0       ;Счетчик (256 повторений).
        LD      A,D       ;Проверяемое число.
LOOP3   SUB     Q+1       ;Вычитаем делитель.
        JR      Z,DEL     ;Если получилось 0, т.е. делится нацело.
        DJNZ    LOOP3     ;Продолжаем...
        JR      M12       ;Если число не делится нацело.

DEL     LD      A,D       ;Увеличиваем номер
        ADD     A,Q       ;текущей строки
        LD      D,A       ;на Q.

M12     LD      A,E       ;Сколько строк вывели?
        CP      192       ;Уже 192 строки?
        JR      NZ,LOOP1  ;Если нет, продолжаем вывод.
        RET

;***************************************
;Процедура ADR_STR
;Вход:  A - номер строки (0..191)
;Выход: HL,DE - адрес в дисплейном файле.

ADR_STR LD      E,A
        AND     A
        RRA
        SCF
        RRA
        AND     A
        RRA
        XOR     E
        AND     #F8
        XOR     E
        LD      H,A
        XOR     A
        XOR     E
        AND     #C7
        XOR     E
        RLCA
        RLCA
        LD      L,A
        LD      E,A
        LD      D,H
        RET

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

1. 

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

2. 

«Графический эффект „цветные полосы“». «ZX-Ревю» 7—10/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.

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