© Иван Рощин, Москва
| ZXNet | : 500:95/462.53 |
| : bestview@mtu-net.ru | |
| WWW | : http://www.ivr.da.ru |
Дата последнего редактирования: 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
|
Другие мои статьи о программировании графических эффектов:
|