Элементарная графика 1993 г.

Практикум по графике в машинных кодах - печать точек на экране. Рисование линий. Изображение прямоугольников. Изображение треугольников.


                        3.7. Печать точек на экране.

              До сих пор мы манипулировали с экранными образами, коорди-
         наты которых были заданы в  знакоместах, но как Вы знаете,  это
         не единственный способ.  Для графики высокого  разрешения более
         естественен способ  задания координат  - в  пикселах. При  этом
         считаем, что экран имеет 256  пикселов по горизонтали (от 0  до
         255) и 176  пикселов по вертикали  (от 0 до  175). И начинается
         графика высокого разрешения с привязкой изображения по пикселам
         - именно с печати на экране обычной точки.

              Конечно, в ПЗУ компьютера есть процедура для печати  точек
         в заданных координатах  (см. стр. 85)  и можно было  бы на этом
         вопросе и  не останавливаться,  но поскольку  построение многих
         и многих  изображений имеет  в своей  основе печать  точек и на
         этом основана вся векторная графика, в учебных целях необходимо
         рассмотреть алгоритм  работы такой  процедуры и  дать несколько
         примеров ее применения.
              Мы  назовем  предлагаемую  процедуру  FN  f(x,y).  Здесь x
         (0...255) - координата пиксела по горизонтали, а y (0...175)  -
         по вертикали. Нам надо помнить, что эти координаты отсчитывают-
         ся не так, как координаты в знакоместах. Начальной  координатой
         (0,0) является левый  нижний угол экрана  (а не левый  верхний,
         как  было  ранее).  Соответственно,  правый верхний угол экрана
         имеет  координату  (255,175).  Кроме  того,  надо также иметь в
         виду, что когда мы говорим о левом нижнем угле экрана (0,0), то
         мы не затрагиваем две самые нижние системные строки компьютера,
         которые лежат  еще ниже,  чем нижняя  строка основного  экрана.
         Фактически координата (0,0) находится над ними.

                    10 REM *** Загрузчик машинного кода
                    20 LET adr=61500: LET long=60: LET z=0
                    30 FOR i=0 TO long-1: READ a
                    40 POKE (adr+i),a: LET z=z+a
                    50 NEXT i
                    60 LET z=INT (((z/long)-INT (z/long))*long)
                    70 READ a
                    80 IF a<>z THEN PRINT "??": STOP
                    500 REM ***Данные для машинного кода
                    510 DATA  42,  11,  92,   1,   4
                    520 DATA   0,   9,  86,  14,   8
                    530 DATA   9,  94,  62, 175, 147
                    540 DATA 216,  95, 167,  31,  55
                    550 DATA  31, 167,  31, 171, 230
                    560 DATA 248, 171, 103, 122,   7
                    570 DATA   7,   7, 171, 230, 199
                    580 DATA 171,   7,   7, 111, 122
                    590 DATA 230,   7,  71,   4,  62
                    600 DATA 254,  15,  16, 253,   6
                    610 DATA 255, 168,  71, 126, 176
                    620 DATA 119, 201,   0,   0,   0
                    630 DATA  24,   0,   0,   0,   0

                          Дисассемблер программы:

         61500   2A0B5C        LD HL,(5C0BH)  ;См. с.109...111.
         61503   010400        LD BC,0004     ;Сдвиг от DEFADD на 4 бай-
         61506       09        ADD HL,BC      ;та (см. c.109...111).
         61507       56        LD D,(HL)      ;Координата x.
         61508     0E08        LD C,08        ;Сдвиг на
         61510       09        ADD HL,BC      ;восемь байтов.
         61511       5E        LD E,(HL)      ¦
         61512     3EAF        LD A,0AFH      ¦  Расчет адреса по
         61514       93        SUB E          ¦  координатам.
         61515       D8        RET C          ¦
         61516       5F        LD E,A         ¦
         61517       A7        AND A          ¦
         61518       1F        RRA            ¦
         61519       37        SCF            ¦
         61520       1F        RRA            ¦
         61521       A7        AND A          ¦
         61522       1F        RRA            ¦
         61523       AB        XOR E          ¦
         61524     E6F8        AND 0F8H       ¦
         61526       AB        XOR E          ¦
         61527       67        LD H,A         ¦
         61528       7A        LD A,D         ¦
         61529       07        RLCA           ¦
         61530       07        RLCA           ¦
         61531       07        RLCA           ¦
         61532       AB        XOR E          ¦
         61533     E6C7        AND C7         ¦
         61534       AB        XOR E          ¦
         61536       07        RLCA           ¦
         61537       07        RLCA           ¦
         61538       6F        LD L,A         ¦

              Теперь мы знаем номер сегмента, ряда, столбца и линии. Все
         эти  данные  хранятся  в  регистре  HL. Последнее, что осталось
         сделать - это  вспомнить, что данная  линия в своем  знакоместе
         имеет  8  пикселов,  а  включить  нужно  только  один  из них -
         необходимый.  Фактически  его  номер  определяется  остатком от
         деления координаты x на 8,  а вычисляется этот остаток -  путем
         маскирования пяти старших битов, но есть еще один нюанс. Дело в
         том, что координата x изменяется слева направо 0,1,2... 175, а
         номера битов в байте, соответствующем найденной нами линии идут
         наоборот 7,6,5.....0. Поэтому нужно сделать преобразование. В
         аккумулятор вводится число FE (11111110), имеющее 0 в крайней
         правой позиции, после чего делается вращение этого байта N+1
         раз, где N -остаток от деления x на 8.

         61539       7A        LD A,D         ;Координата x.
         61540     E607        AND 07         ;Маскирование.
         61542       47        LD B,A         ;Остаток от деления x на 8
         61543       04        INC B          ; + 1
         61544     3EFE        LD A,FE        ;Ввели байт 1111 1110
         61546       0F LOOP   RRCA           ;Вращение вправо столько
         61547     10FD        DJNZ,LOOP      ;раз, сколько установлено
                                              ;в регистре B.
         61549     06FF        LD B,0FFH      ;Инверсия, чтобы печать
         61551       A8        XOR B          ;точки была черным по бе-
                                              ;лому, а не наоборот.
         61552       47        LD B,A         ;Запомнили в B.
         61553       7E        LD A,(HL)      ;В аккумулятор приняли то,
                                              ;что уже содержится на эк-
                                              ;ране в нужной линии.
         61554       B0        OR B           ;Включаем требуемый бит
         61555       77        LD (HL),A      ;Включаем требуемый пик-
                                              ;сел.
         61556       C9        RET            ;Выход из процедуры.

                      Примеры использования процедуры.
                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
              Продемонстрируем  работу  приведенной  выше  процедуры  на
         некоторых  примерах.   Эти  примеры   написаны  на   БЕЙСИКе  и
         вставляются в приведенную  выше БЕЙСИК-программу (стр.145, 146)
         между строками  80 и 500.

              "Экспонента".
              ~~~~~~~~~~~~~~~
                      100  DEF FN f(x,y) = USR 61500
                      110  BORDER 6: PAPER 6: INK 0: CLS
                      120  FOR n=1.19 TO 1.80 STEP 0.01
                      130  FOR x= 0 TO 22 STEP 0.5
                      140  LET z= INT(x^n)
                      150  LET y= INT (x*8)
                      160  RANDOMIZE FN f(z,y)
                      170  RANDOMIZE FN f(255-z, 168-y)
                      180  NEXT x
                      190  NEXT n

              "Планета"
              ~~~~~~~~~
                      100  DEF FN f(x,y) = USR 61500
                      110  BORDER 0: PAPER 0: INK 4: CLS
                      120  LET r=60: LET xc=127: LET yc=88
                      130  GO SUB 400
                      140  LET r=20: LET xc=75: LET yc=100
                      150  GO SUB 400
                      160  STOP
                      400  FOR y=-r TO r
                      410  FOR x1 = INT (SQR (r*r-y*y)
                      420  FOR x=-x1 TO x1
                      430  LET n=INT (RND*(1)*x1*2)+1
                      440  IF n
             170  POKE k+i,13
             175  REM ***** Печать звезд в 74-х верхних линиях экрана
             180  FOR i=0 TO 298 STEP 2
             190  LET x1=INT (255*RND)
             200  LET y1=174-(INT(74*RND))
             210  RESTORE FN f(x1,y1)
             220  NEXT i
             230  RANDOMUZE FN c(0,14,25,15,1,0,0)
             235  REM ***** Изображение зданий заднего плана
             240  FOR i=1 TO 50
             250  RANDOMIZE
             260  LET h1=2+INT (RND*4)
             270  LET y1=10+INT(RND*15)
             280  LET v1=25-y1
             290  LET x1=INT(RND*27)
             300  LET c1=2+INT (RND*6)
             310  RANDOMIZE FN c(x1,y1,h1,v1,c1,0,0)
             320  NEXT i
             325  REM ***** Изображение зданий переднего плана
             330  RANDOMIZE FN c(16,9,1,15,4,1,0)
             340  RANDOMIZE FN c(17,6,2,18,4,1,1)
             350  RANDOMIZE FN c(19,10,1,14,4,1,0)
             360  RANDOMIZE FN b(17,6,2,18,1,0,1)
             370  RANDOMIZE FN e(17,6)
             380  RANDOMIZE FN c(1,11,5,14,2,0,0)
             385  REM ****** Изображение окон в зданиях
             390  FOR i=12 TO 22 STEP 2
             400  RANDOMIZE FN c(2,i,1,1,7,1,0)
             410  RANDOMIZE FN c(4,i,1,1,6,1,0)
             420  NEXT i
             430  RANDOMIZE FN c(23,18,9,7,3,0,0)
             440  FOR i=24 TO 30 STEP 2
             450  RANDOMIZE FN c(i,19,1,1,4,1,0)
             460  RANDOMIZE FN c(i,21,1,1,4,1,0)
             470  NEXT i
             475  REM ***** Изображение метеора
             480  INK 6: BRIGHT 1
             490  FOR i=-6 TO 6 STEP 2
             500  PLOT 250,165-i
             510  DRAW -70,i-40: NEXT i
             520  INK 7
             525  REM ****** Изображение полумесяца
             530  FOR i= 0 TO 7
             540  PLOT 20+i,150
             550  DRAW 0,-50,0.8*PI
             560  NEXT i
             570  PAUSE 0

                           3.8. Изображение линий.

              Известный оператор БЕЙСИКа  DRAW служит для  рисования от-
         резков прямых и  дуг окружностей. Вам  известно, что для  того,
         чтобы был нарисован нужный отрезок, предварительно должна  быть
         задана (PLOT) исходная точка и указаны относительные координаты
         конца отрезка. Задание  относительных координат (приращений  по
         горизонтали и  вертикали) во  многих случаях  является не очень
         удобным, а порой и просто трудоемкой операций, т.к. программис-
         ту требуется сначала рассчитать эти приращения. Гораздо удобнее
         было бы вводить  абсолютные экранные координаты  конца отрезка,
         что  и  позволяет  сделать  предлагаемая  здесь  процедура FN g
         (x,y,p,q).

              x,y - координаты начала отрезка (x<256, y<176);
              p,q - координаты конца отрезка (p<256, q<176)

              Эта  процедура  работает  много  быстрее, чем традиционная
         команда DRAW и быстрее, чем машиннокодовая процедура,  содержа-
         щаяся в ПЗУ  для этой цели  (т.к. последняя в  своей работе ис-
         пользует операции со встроенным калькулятором, а он ведет  свои
         расчеты тоже при поддержке процедур ПЗУ). Приведенная процедура
         выполняет некоторые проверки, исключающие ввод координат, выхо-
         дящих за пределы экрана, что позволяет практиковать при исполь-
         зовании процедуры  метод проб  и ошибок  без угрозы  потерять и
         БЕЙСИК-программу и  процедуру вследствие  зависания компьютера.
         Тем не менее,  если введенная Вами  координата будет не  только
         выходить за пределы экрана, но  при этом еще и выходить  более,
         чем на 255 пикселов, есть вероятность того, что программа может
         зависнуть.

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

              Построение линии осуществляется  точка за точкой,  начиная
         от исходной координаты. Каждый шаг выполняется со смещением  не
         более, чем на один пиксел как по горизонтали, так и по вертика-
         ли до тех пор, пока не будет достигнута конечная точка.

              1.  Сначала  вычисляются  вектора  от  начальной  точки до
         конечной. Если  и по  x и  по y  приращения положительные, то в
         специальной переменной SIGN выставляются +1  для x и +1 для  y.
         Если же какое-то  из этих смещений  отрицательное, то для  него
         выставляется -1 (то есть FF).

              2. Проблемой является тот факт, что если одно из  прираще-
         ний больше другого, то его координата должна изменяться на каж-
         дом шаге, а для  меньшего - не на  каждом. Чтобы это было  так,
         кроме SIGN вводится еще контрольная пара BC. В ней тому  прира-
         щению, которое больше  по абсолютной величине, соответствует 01
         или FF, а меньшему - 0. И теперь при построении новой точки шаг
         по координатам  берется то  из SIGN,  то из  BC. Чем сильнее по
         абсолютной величине отличаются  приращения по x  и y, тем  чаще
         построение новой точки  делается с шагом,  взятым из BC,  когда
         отрабатывается  только  одна  координата,  а  вторая   остается
         неизменной. Эта логика организована в адресах 60782 - 60789.

              3. В остальном логика работы процедуры достаточно  обычна.
         Отметим только, что сама  печать точек по координатам,  находя-
         щимся в DE выполняется процедурой PLOT (60851), которая  анало-
         гична разобранной в предыдущем разделе.

                    10 REM *** Загрузчик машинного кода
                    20 LET adr=60700: LET long=210: LET z=0
                    30 FOR i=0 TO long-1: READ a
                    40 POKE (adr+i),a: LET z=z+a
                    50 NEXT i
                    60 LET z=INT (((z/long)-INT (z/long))*long)
                    70 READ a
                    80 IF a<>z THEN PRINT "??": STOP
                    500 REM ***Данные для машинного кода
                    510 DATA  42,  11,  92,   1,   4
                    520 DATA   0,   9,  86,  14,   8
                    530 DATA   9,  94, 237,  83,  26
                    540 DATA 237, 205, 226, 237,  94
                    550 DATA  42,  26, 237, 217, 229
                    560 DATA 217, 237, 115, 175, 237
                    570 DATA   1,   1,   1, 122, 148
                    580 DATA 210,  70, 237,   6, 255
                    590 DATA 237,  68,  87, 123, 149
                    600 DATA 210,  80, 237,  14, 255
                    610 DATA 237,  68,  95, 122, 187
                    620 DATA  48,  10, 106, 237,  67
                    630 DATA 177, 237, 175,  71, 195
                    640 DATA 107, 237, 178, 202, 167
                    650 DATA 237, 107,  90, 237,  67
                    660 DATA 177, 237,  14,   0,  99
                    670 DATA 123,  31, 133, 218, 118
                    680 DATA 237, 188, 218, 128, 237
                    690 DATA 148,  87, 217, 237,  91
                    700 DATA 177, 237, 195, 132, 237
                    710 DATA  87, 197, 217, 209,  42
                    720 DATA  26, 237, 123, 133,  95
                    730 DATA 122,  60, 132, 218, 164
                    740 DATA 237, 202, 167, 237,  61
                    750 DATA  87, 237,  83,  26, 237
                    760 DATA 205, 179, 237, 217, 122
                    770 DATA  29,  32, 205, 195, 167
                    780 DATA 237, 202, 147, 237, 237
                    790 DATA 123, 175, 237, 217, 225
                    800 DATA 217, 201, 181, 214,   1
                    810 DATA   1,  62, 175, 147, 218
                    820 DATA 249,  36,  95, 167,  31
                    830 DATA  55,  31, 167,  31, 171
                    840 DATA 230, 248, 171, 103, 122
                    850 DATA   7,   7,   7, 171, 230
                    860 DATA 199, 171,   7,   7, 111
                    870 DATA 122, 230,   7,  71,   4
                    880 DATA  62, 254,  15,  16, 253
                    890 DATA   6, 255, 168,  71, 126
                    900 DATA 176, 119, 201, 229, 197
                    910 DATA 205, 179, 237, 193, 225
                    920 DATA   9,  86,   9, 201,   0
                    930 DATA 192,   0,   0,   0,   0

                          Дисассемблер программы:

         60698           COORD DEFW           ;Здесь создается програм-
                                              ;мная переменная, хранящая
                                              ;координаты исходной точки
         60700   2A0B5C        LD HL,(5C0BH)  ;См. с.109...111.
         60703   010400        LD BC,0004     ;Сдвиг от DEFADD на 4 бай-
         60706       09        ADD HL,BC      ;та (см. c.109...111).
         60707       56        LD D,(HL)      ;Координата x.
         60708     0E08        LD C,08        ;Сдвиг на
         60710       09        ADD HL,BC      ;восемь байтов.
         60711       5E        LD E,(HL)      ;Координата y.
         60712 ED531AED        LD(COORD),DE   ;Запомнили x,y
         60716   CDE2ED        CALL BEGIN     ;Вызов подпрограммы BEGIN
                                              ;(60898), которая выполнит
                                              ;печать исходной точки.
         60719       5E        LD E,(HL)      ;Ввод координаты q.
         60720   2A1AED        LD HL,(ED1A)   ;Приняли координаты x и y.
         60723       D9        EXX            ;Сохранение на стеке сос-
         60724       E5        PUSH HL        ;тояния альтернативной па-
         60725       D9        EXX            ;ры HL, поскольку при
                                              ;работе программы она мо-
                                              ;жет быть коррумпирована.
         60726 ED73AFED        LD(STK_P),SP   ;Запомнили состояние ука-
                                              ;зателя стека в соответс-
                                              ;твующей переменной.
         60730   010101        LD BC,0101     ;Исходная установка для
                                              ;инициализации переменной
                                              ;SIGN (60849).
         60733       7A        LD A,D         ;Параметр p.
         60734       94        SUB H          ;Вычли из него параметр x.
         60735   D246ED        JP NC,CONT_1   ;Если p>x, то регистр B
                                              ;менять не надо и перехо-
                                              ;дим на метку CONT_1.
         60738     06FF        LD B,0FFH      ;В противном случае в B
                                              ;выставляем FF (минус еди-
                                              ;ницу).
         60740     ED44        NEG            ;Изменение знака содержи-
                                              ;мого аккумулятора, теперь
                                              ;в нем абсолютная величина
                                              ;приращения по x, а знак -
                                              ;в регистре B.
         60742       57 CONT_1 LD D,A         ;Запомнили в D абс.велич.
                                              ;приращения по x.
         60743       7B        LD A,E         ;Параметр q.
         60744       95        SUB L          ;Вычли из него параметр y.
         60745   D250ED        JP NC,CONT_2   ;Если q>y, то регистр C
                                              ;менять не надо и перехо-
                                              ;дим на метку CONT_2.
         60748     0EFF        LD C,0FFH      ;В противном случае в C
                                              ;выставляем FF (минус еди-
                                              ;ницу).
         60750     ED44        NEG            ;Изменение знака содержи-
                                              ;мого аккумулятора, теперь
                                              ;в нем абсолютная величина
                                              ;приращения по y, а знак -
                                              ;в регистре C.
         60752       5F CONT_2 LD E,A         ;Запомнили в E абс.велич.
                                              ;приращения по y.
         60753       7A        LD A,D         ;Сравниваем по абсолютной
         60754       BB        CP E           ;величине приращения x и
                                              ;y.
         60755     300A        JR NC,CONT_3   ;Если приращение по x
                                              ;больше, то переход на
                                              ;метку CONT_3.
         60757       6A        LD L,D         ;Запомнили меньшее.
         60758 ED43B1ED        LD (SIGN),BC   ;Запомнили знаки прира-
                                              ;щений в переменной SIGN.
         60762       AF        XOR A          ;Обнуление аккумулятора.
         60763       47        LD B,A         ;Обнуление B (раз прираще-
                                              ;ние по x - меньшее, то
                                              ;первый шаг по нему будет
                                              ;нулевым.
         60764   C36BED        JP CONT_4      ;Переход на CONT_4 для
                                              ;продолжения работы.

              Сюда мы попадаем только в том случае, если абсолютная ве-
         личина приращения по x больше, чем приращения по y.

         60767       B2 CONT_3 OR D           ;Поскольку и в аккумуля-
                                              ;торе и в регистре D на-
                                              ;ходится приращение по x,
                                              ;то эта операция фактиче-
                                              ;ски является проверкой
                                              ;флагов.
         60768   CAA7ED        JP Z,FINISH    ;Если приращение уже рав-
                                              ;но нулю, то конец рабо-
                                              ;ты и переход на FINISH.
         60771       6B        LD L,E         ;Приращение по y.
         60772       5A        LD E,D         ;Приращение по x.
         60773 ED43B1ED        LD (SIGN),BC   ;Запомнили знаки прира-
                                              ;щений в переменной SIGN.
         60777     OE00        LD C,00        ;Переинициализация C. (Раз
                                              ;приращение по y меньше,
                                              ;то первый шаг по нему
                                              ;будет нулевым.

              В итоге манипуляций, проведенных в строках 60753 - 60777
         мы имеем в регистре E то приращение (из x и y), которое имеет
         большую абсолютную величину, назовем ее - max а в регистре L -
         то, которое имеет меньшую величину, назовем ее min.

         60779       63 CONT_4 LD H,E         ;Большее из приращений.
         60780       7B        LD A,E         ;Большее из приращений.
         60781       1F        RRA            ;Деление пополам.
         60782       85 REPEAT ADD A,L        ;0.5max+min
         60783   DA76ED        JP C,CONT_5    ;Здесь переполнение воз-
                                              ;можно только если
                                              ;min>0.5max.
         60786       BC        CP H           ;Здесь переполнение воз-
         60787   DA80ED        JP C,CONT_6    ;можно только если
                                              ;min<0.5max.
         60790       94 CONT_5 SUB H          ;Получили min-0.5max
         60791       57        LD D,A         ;Запомнили в D
         60792       D9        EXX            ;Переход на альтернативный
                                              ;набор регистров, чтобы не
                                              ;портить DE.
         60793 ED5BB1ED        LD DE,(SIGN)   ;В DE - знаки приращений
                                              ;по x и y.
         60797   C384ED        JP CONT_7
         60800       57 CONT_6 LD D,A         ;Запомнили в D min+0.5 max
         60801       C5        PUSH BC        ;Переброска через стек
         60802       D9        EXX            ;знака приращений из BC в
         60803       D1        POP DE         ;альтернативную пару DE.
         60804   2A1AED CONT_7 LD HL,(COORD)  ;Текущие координаты пози-
                                              ;ции печати очередной
                                              ;точки.
         60807       7B        LD A,E         ;Знак приращения по y.
         60808       85        ADD A,L        ;Переход к новой точке по
                                              ;вертикали.
         60809       5F        LD E,A         ;Запомнили ее.
         60810       7A        LD A,D         ;Знак приращения по x.
         60811       3C        INC A          ;Проверка на возможность
         60812       84        ADD A,H        ;выхода за пределы экра-
         60813   DAA4ED        JP C,CONT_8    ;на.
         60816   CAA7ED        JP Z,FINISH    ;Подготовка к выходу.
         60819       3D CONT_9 DEC A          ;Восстановили A после
                                              ;вышеуказанной проверки
         60820       57        LD D,A         ;и запомнили в D.
         60821 ED531AED        LD (COORD),DE  ;Запомнили новую текущую
                                              ;координату позиции пе-
                                              ;чати точки.
         60825   CDB3ED        CALL PLOT      ;Печать точки
         60828       D9        EXX            ;Возврат к основному на-
                                              ;бору регистров.
         60829       7A        LD A,D
         60830       1D        DEC E          ;Уменьшение того прираще-
                                              ;ния, которое было макси-
                                              ;мальным.
         60831     20CD        JR NZ,REPEAT   ;Если оно не 0, то нужно
                                              ;работать дальше.
         60833   C3A7ED        JP FINISH      ;В противном случае рабо-
                                              ;та завершается.
         60836   CA93ED CONT_8 JP Z,CONT_9    ;Предел по x - близок, но
                                              ;еще одну точку напечатать
                                              ;можно - переход на CONT_9
         60839 ED7BAFED FINISH LD SP,(EDAF)   ;Восстановление указателя
                                              ;стека.
         60843       D9        EXX            ;Восстановление состояния
         60844       E1        POP HL         ;альтернативной пары HL
         60845       D9        EXX            ;перед выходом.
         60846       C9        RET            ;Генеральный выход.
         60847          STK_P  DEFW           ;В этой программной пере-
                                              ;менной организуется хра-
                                              ;нение значения указателя
                                              ;машинного стека - SP.
         60849          SIGN   DEFW           ;Два байта этой переменной
                                              ;выполняют роль знаков
                                              ;приращения координаты.
                                              ;Если xp, то он равен FF
                                              ;или -1. Второй байт уста-
                                              ;навливается в +1 или в FF
                                              ;в зависимости от соотно-
                                              ;шения q и y.

              Процедура PLOT служит для  печати на экране тех  точек, из
         которых состоит наш отрезок. Поскольку она практически соответ-
         ствует рассмотренной  ранее процедуре  FN f(x,y),  мы не  будем
         подробно рассматривать логику ее работы.
              При вызове этой процедуры в регистре D выставлена  коорди-
         ната x предполагаемой позиции печати, а в регистре E -  коорди-
         ната y.

         60851     3EAF PLOT   LD A,0AFH      ;AF=175
         60853       93        SUB E          ;Проверка не выходит ли за
                                              ;пределы допуска (175) ко-
                                              ;ордината y.
         60854   DAF924        JP C,24F9      ;Если так, то переход в
                                              ;ПЗУ на адрес 9465, где
                                              ;записан вызов процедуры
                                              ;обработки ошибок RST 08
                                              ;с кодом перехвата 0A, что
                                              ;дает ошибку "Integer out
                                              ;of range".
         60857       5F        LD E,A         ;Дополнение y до 175.
         60858       A7        AND A          ;Сброс флага переноса.
         60859       1F        RRA            ;Ротация вправо.
         60860       37        SCF            ;Установка флага переноса
         60861       1F        RRA            ;Ротация вправо.
         60862       A7        AND A          ;Сброс флага переноса.
         60863       1F        RRA            ;Ротация вправо.
         60864       AB        XOR E          ;Комплексная
         60865     E6F8        AND F8         ;операция замещения
         60867       AB        XOR E          ;битов 0,1 и 2.
         60868       67        LD H,A         ;Сформировали старший байт
                                              ;адреса в дисплейном файле
         60869       7A        LD A,D         ;Координата x
         60870       07        RLCA           ;Вращение влево.
         60871       07        RLCA           ;Вращение влево.
         60872       07        RLCA           ;Вращение влево.
         60873       AB        XOR E          ;Операция замещения
         60874     E6C7        AND C7         ;для битов 3,4,5.
         60876       AB        XOR E          ;
         60877       07        RLCA           ;Вращение влево.
         60878       07        RLCA           ;Вращение влево.
         60879       6F        LD L,A         ;Сформировали младший байт
                                              ;адреса в дисплейном файле
         60880       7A        LD A,D         ;Координата x.
         60881     E607        AND 07H        ;Маскирование.
         60883       47        LD B,A         ;Инициализация счетчика
         60884       04        INC B          ;оборотов в регистре B.
         60885     3EFE        LD A,0FEH      ;Байт FE=254 интересен
                                              ;тем, что все биты, кро-
                                              ;ме одного равны едини-
                                              ;це. Вот эту "дырку" мы
                                              ;и вращаем, пока она не
                                              ;встанет на свое место.
         60887       0F AGAIN  RRCA           ;Вращение вправо.
         60888     10FD        DJNZ AGAIN     ;Повтор вращения.
         60890     06FF        LD B,0FFH      ;Инверсия, чтобы печать
         60892       A8        XOR B          ;точки была черным по бе-
                                              ;лому, а не наоборот.
         60893       47        LD B,A         ;Запомнили в B.
         60894       7E        LD A,(HL)      ;В аккумулятор приняли то,
                                              ;что уже содержится на эк-
                                              ;ране в нужной линии.
         60895       B0        OR B           ;Включаем требуемый бит
         60896       77        LD (HL),A      ;Включаем требуемый пик-
                                              ;сел.
         60897       C9        RET            ;Выход из процедуры.
         60898       E5 BEGIN  PUSH HL        ;Сохранение на стеке
         60899       C5        PUSH BC        ;регистров HL и BC.
         60900   CDB3ED        CALL PLOT      ;Вызов процедуры PLOT
                                              ; (60851)
         60903       C1        POP BC         ;Восстановление со стека
         60904       E1        POP HL         ;регистров HL и BC.
         60905       09        ADD HL,BC      ;Сдвиг от DEFADD на 8 бай-
                                              ;тов.
         60906       56        LD D(HL)       ;Ввод координаты p.
         60907       09        ADD HL,BC      ;Сдвиг от DEFADD на 8 бай-
                                              ;тов.
         60910       C9        RET            ;Возврат в вызывающую про-
                                              ;грамму.

                      Примеры использования процедуры.
                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
              Продемонстрируем  работу  приведенной  выше  процедуры  на
         некоторых  примерах.   Эти  примеры   написаны  на   БЕЙСИКе  и
         вставляются в приведенную  выше БЕЙСИК-программу (стр. 154)
         между строками  80 и 500.

              "Куб".
              ~~~~~~~
              100  DEF FN g(x,y,p,q) = USR 60700
              110  BORDER 1: PAPER 1: INK 6
              120  CLS
              130  FOR j=0 TO 116 STEP 8
              140  RANDOMIZE FN g(56,24+j,168,24+j)
              150  RANDOMIZE FN g(56+j,24,56+j,136)
              160  RANDOMIZE FN g(56+j,136,96+j,160)
              170  RANDOMIZE FN g(168,24+j,208,48+j)
              180  NEXT j
              190  RANDOMIZE FN g(96,160,208,160)
              200  RANDOMIZE FN g(208,160,208,48)

              "Закат".
              ~~~~~~~~~
                   Эта  программа  использует  также  процедуру  FN c(),
         служащую для окраски части  экрана цветом PAPER. Машинный  код,
         соответствующий  этой  процедуре  предварительно  должен   быть
         подгружен в отведенную для него область памяти.

              100  DEF FN c(x,y,h,v,c,b,f)=USR 62600
              110  DEF FN g(x,y,p,q) = USR 60700
              120  BORDER 0: PAPER 1: INK 6
              130  CLS
              140  RANDOMIZE FN c(0,0,32,17,2,0,0)
              150  FOR j=40 TO 174 STEP 12
              160  RANDOMIZE FN g(0,j,128,40)
              170  RANDOMIZE FN g(255,j,128,40)
              180  NEXT j
              190  FOR j=6 TO 255 STEP 12
              200  RANDOMIZE FN g(j,175,128,40)
              210  NEXT j
              220  FOR j=36 TO 0 STEP -3
              230  RANDOMIZE FN g((10+j*3),j,(248-j*3),j)
              240  NEXT j

              "Пирамиды".
              ~~~~~~~~~~~
                   Процедура, изображающая отрезки прямых, очень  хорошо
         подходит для изображения интерференционных узоров. Они  образу-
         ются, когда смещения семейства  отрезков настолько малы, что  в
         результате не образуются ни отдельные линии, ни сплошная  окра-
         шенная поверхность.  Приведенная программа показывает, как  это
         происходит и демонстрирует возможность получения очаровательно-
         го пейзажа в восточном стиле. Каждая пирамида рисуется  вызовом
         подпрограммы из строки 400. Интерференционная картина  наблюда-
         ется на гранях пирамид, что создает эффект трехмерной графики.

              100  DEF FN b(x,y,h,v,c,b,f)=USR 62800
              110  DEF FN c(x,y,h,v,c,b,f)=USR 62600
              120  DEF FN g(x,y,p,q) = USR 60700
              130  BORDER 0: PAPER 1: INK 2
              140  CLS
              150  RANDOMIZE FN c(0,8,31,14,6,0,0)
              160  LET tx=80: LET ty=136: LET by=24: LET a=16: LET b=128
              170  GO SUB 400
              180  LET tx=156: LET by=60: LET a=102: LET b=182
              190  GO SUB 400: STOP

              400  FOR x=a TO b STEP 2
              410  RANDOMIZE  FN g(tx,ty,x,by)
              420  NEXT x
              430  FOR x=b TO b+16
              440  RANDOMIZE  FN g(tx,ty,x,by)
              450  LET by=by+1
              460  NEXT x: RETURN

              "Плетенка".
              ~~~~~~~~~~~
                   Еще один интересный  и до некоторой  степени парадок-
         сальный эффект можно  получить изображением семейства  прямых с
         малым смещением от линии к  линии. Так, при движении одного  из
         концов отрезков нескольких прямых в точках пересечения  образу-
         ются довольно сложные кривые линии, а штриховой характер  изоб-
         ражения придает им сходство со сложными трехмерными  поверхнос-
         тями.

              100  DEF FN g(x,y,p,q) = USR 60700
              110  BORDER 0: PAPER 6: INK 0
              120  CLS
              130  FOR i=14 TO 2 STEP -1
              140  FOR j=0 TO 150 STEP i
              150  RANDOMIZE  FN g(50+j,0,j,175)
              160  RANDOMIZE  FN g(255,j,j,0)
              170  RANDOMIZE  FN g(50+j,150,255,150-j)
              180  RANDOMIZE  FN g(50+j,150,j,0)
              190  NEXT j
              200  PAUSE 0: CLS
              210  NEXT i

              "Интерференция".
              ~~~~~~~~~~~~~~~~
                   Интересные интерференционные картины на экране могут
         быть получены простым увеличением количества печатаемых отрез-
         ков прямых. Попробуйте поэкспериментировать с приведенной ниже
         программой, меняя параметр цикла 255 в строке 140.

              100  DEF FN g(x,y,p,q) = USR 60700
              110  BORDER 0: PAPER 1: INK 6
              120  CLS
              130  FOR i=16 TO 6 STEP -1
              140  FOR j=0 TO 255 STEP i
              150  RANDOMIZE  FN g(0,0,j,175)
              160  RANDOMIZE  FN g(255,175,j,0)
              170  RANDOMIZE  FN g(255,0,j,175)
              180  RANDOMIZE  FN g(0,175,j,0)
              190  NEXT j
              200  PAUSE 0: CLS
              210  NEXT i

                      3.9. Изображение прямоугольников.

              Изображение  прямоугольника  в  БЕЙСИКе  выполняется одной
         командой PLOT и четырьмя командами DRAW. Например:

                             10 PLOT 100,100
                             20 DRAW 50,0
                             30 DRAW 0,50
                             40 DRAW -50,0
                             50 DRAW 0,50

              Точно так же изображением четырех линий мы можем  получить
         прямоугольник из машинного кода. В общем блоке  рассматриваемых
         нами процедур эта процедура (назовем ее FN h(x,y,h,v)) имеет ту
         отличительную особенность, что не является абсолютно автономной
         и  при  работе  вызывает  процедуру изображения отрезков прямых
         FN  g(x,y,p,q).  Эта  процедура  вызывается  по адресу 60723, и
         это предполагает, что  координаты исходной точки  установлены в
         HL, а координаты точки назначения (абсолютные) - в DE.

              Параметры:  x,y - координаты левого верхнего угла;
                            h - ширина
                            v - высота прямоугольника.

                    10 REM *** Загрузчик машинного кода
                    20 LET adr=60400: LET long=105: LET z=0
                    30 FOR i=0 TO long-1: READ a
                    40 POKE (adr+i),a: LET z=z+a
                    50 NEXT i
                    60 LET z=INT (((z/long)-INT (z/long))*long)
                    70 READ a
                    80 IF a<>z THEN PRINT "??": STOP
                    500 REM ***Данные для машинного кода
                    510 DATA  42,  11,  92,   1,   4
                    520 DATA   0,   9,  86,  14,   8
                    530 DATA   9,  94, 237,  83,  82
                    540 DATA 236,   9,  86,   9,  94
                    550 DATA 237,  83,  84, 236, 237
                    560 DATA  91,  82, 236,  58,  85
                    570 DATA 236, 130, 103,  50,  87
                    580 DATA 236, 107,  34,  26, 237
                    590 DATA 205,  51, 237, 237,  91
                    600 DATA  82, 236,  58,  84, 236
                    610 DATA 131,  50,  86, 236, 111
                    620 DATA  98,  34,  26, 237, 205
                    630 DATA  51, 237,  42,  86, 236
                    640 DATA  58,  83, 236,  87,  58
                    650 DATA  86, 236,  95,  34,  26
                    660 DATA 237, 205,  51, 237,  42
                    670 DATA  86, 236,  58,  82, 236
                    680 DATA  95,  44,  58,  87, 236
                    690 DATA  87,  34,  26, 237, 205
                    700 DATA  51, 237, 201,  30,   3
                    710 DATA  60,  60,  90,  63,   0
                    720 DATA  86,   0,   0,   0,   0

                          Дисассемблер программы:

         60400   2A0B5C        LD HL,(5C0BH)  ;См. с. 109...111
         60403   010400        LD BC,0004     ;Сдвиг от DEFADD на 4 бай-
         60406       09        ADD HL,BC      ;та (см. c.109...111).
         60407       56        LD D,(HL)      ;Координата x.
         60408     0E08        LD C,08        ;Сдвиг на
         60410       09        ADD HL,BC      ;восемь байтов.
         60411       5E        LD E,(HL)      ;Координата y.
         60412 ED5352EC        LD(Y_UP),DE    ;Запомнили x,y.
         60416       09        ADD HL,BC      ;Сдвиг на 8 байтов.
         60417       56        LD D,(HL)      ;Параметр h.
         60418       09        ADD HL,BC      ;Сдвиг на 8 байтов.
         60419       5E        LD E,(HL)      ;Параметр v.
         60420 ED5354EC        LD(HIGHT),DE   ;Запомнили h,v.
         60424 ED5B52EC        LD DE,(Y_UP)   ;Параметры x,y
         60428   3A55EC        LD A,(WIDTH)   ;Приняли ширину пр-ка.
         60431       82        ADD A,D        ;Вычисляем x+h и
         60432       67        LD H,A         ;запоминаем в регистре H
         60433   3257EC        LD (X_RGHT),A  ;и в переменной 60503.
         60436       6B        LD L,E         ;Параметр y.
         60437   221AED        LD (COORD),HL  ;Запоминаем координаты
                                              ;левого верхего угла в
                                              ;ячейке 60698, откуда они
                                              ;могут быть использованы
                                              ;процедурой FN g() для
                                              ;рисования верхней сторо-
                                              ;ны прямоугольника.
         60440   CD33ED        CALL ED33      ;Вызов процедуры FN g()
                                              ;осуществляется по
                                              ;адресу 60723. Рисуем вер-
                                              ;хнюю сторону.
         60443 ED5B52EC        LD DE,(Y_UP)   ;Параметры x,y.
         60447   3A54EC        LD A,(HIGHT)   ;Высота пр-ка.
         60450       83        ADD A,E        ;Определяем y+v и запоми-
         60451   3256EC        LD (Y_DOWN),A  ;наем в переменной 60502
         60454       6F        LD L,A         ;и в регистре L.
         60455       62        LD H,D         ;Параметр x.
         60456   221AED        LD (COORD),HL  ;Запоминаем координаты
                                              ;левого нижнего угла в
                                              ;ячейке 60698.
         60459   CD33ED        CALL ED33      ;Рисуем левую сторону.
         60462   2A56EC        LD HL,(Y_DOWN) ;Координаты правого ниж-
                                              ;него угла.
         60465   3A53EC        LD A,(X_LEFT)  ;Коорд. x левая.
         60468       57        LD D,A
         60469   3A56EC        LD A,(Y_DOWN)  ;Коорд. y нижняя
         60472       5F        LD E,A
         60473   221AED        LD (COORD),HL  ;Правый нижний угол.
         60476   CD33ED        CALL ED33      ;Рисуем нижнюю сторону.
         60479   2A56EC        LD HL,(Y_DOWN) ;Координаты правого ниж-
                                              ;него угла.
         60482   3A52EC        LD A,(Y_UP)    ;Коорд. y верхней стороны.
         60485       5F        LD E,A
         60486       2C        INC L
         60487   3A57EC        LD A,(X_RGHT)  ;Коорд. x правой стороны.
         60490       57        LD D,A
         60491   221AED        LD (COORD),HL  ;Правый нижний угол.
         60494   CD33ED        CALL ED33      ;Рисуем правую сторону.
         60497       C9        RET            ;Выход.
         60498          Y_UP   DEFB           ;Координата y верхней
                                              ;стороны.
         60499          X_LEFT DEFB           ;Координата x левой
                                              ;стороны.
         60500          HIGHT  DEFB           ;Высота прямоугольника.
         60501          WIDTH  DEFB           ;Ширина прямоугольника.
         60502          Y_DOWN DEFB           ;Координата y нижней
                                              ;стороны.
         60503          X_RGHT DEFB           ;Координата x правой
                                              ;стороны.
         60698          COORD  DEFW           ;Переменная, служащая для
                                              ;связи с процедурой печа-
                                              ;ти прямых линий.

                      Примеры использования процедуры.
                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
              Продемонстрируем  работу  приведенной  выше  процедуры  на
         некоторых  примерах.   Эти  примеры   написаны  на   БЕЙСИКе  и
         вставляются в приведенную   выше БЕЙСИК-программу (стр. 166  )
         между строками  80 и 500.

              "Каменный цветок"
              ~~~~~~~~~~~~~~~~~
                   100  DEF FN h(x,y,h,v) = USR 60400
                   110  BORDER 3: PAPER 3: INK 6: CLS
                   120  FOR j=1 TO 43
                   130  RANDOMIZE FN h(j*2,j*3,j,j)
                   140  RANDOMIZE FN h(j*4,j*3,j,j)
                   150  RANDOMIZE FN h(j*4,j,j,j)
                   160  RANDOMIZE FN h(j*2,j,j,j)
                   170  NEXT j

              Еще  одну  разновидность  геометрических  построений можно
         получить применением следующей программы:

                   100  DEF FN h(x,y,h,v) = USR 60400
                   110  BORDER 0: PAPER 2: INK 6 :CLS
                   120  FOR j=5 TO 38 STEP 2
                   130  RANDOMIZE FN h(j*2,j,50,50)
                   140  RANDOMIZE FN h(j*2,130-j,50,50)
                   150  RANDOMIZE FN h(206-j*2,130-j,50,50)
                   160  RANDOMIZE FN h(206-j*2,j,50,50)
                   170  NEXT j

                      3.10. Изображение треугольников.

              В предыдущей программе мы использовали при вычислении  ко-
         координат прямоугольника тот факт, что его стороны параллельны.
         Очередной шаг вперед для изображения произвольных многоугольни-
         ков мы сделаем, если рассмотрим прием построения  треугольника.
         Для этого служит приводимая здесь процедура FN i(x,y,p,q,r,s).

                      x,y - координаты первой вершины;
                      p,g - координаты второй вершины;
                      r,s - координаты третей вершины треугольника.

              Как Вы  увидите, для  работы этой  процедуры создаются три
         программных  переменных  PLOT_1...PLOT_3,  хранящие  координаты
         вершин треугольника.  Несложно развить  этот прием  и для любых
         других многоугольных геометрических  форм. Как и  программа по-
         строения  прямоугольников,  эта   процедура  использует   вызов
         процедуры FN g(), строящей отрезки прямых. Этот вызов  происхо-
         дит по адресу 60723, для чего координаты исходной точки  должны
         быть установлены в HL, а координаты точки назначения  (абсолют-
         ные) -  в DE.  Для обмена  между процедурами  FN i()  и FN  g()
         служит переменная COORD, расположенная по адресу 60698.

                    10 REM *** Загрузчик машинного кода
                    20 LET adr=60300: LET long=75: LET z=0
                    30 FOR i=0 TO long-1: READ a
                    40 POKE (adr+i),a: LET z=z+a
                    50 NEXT i
                    60 LET z=INT (((z/long)-INT (z/long))*long)
                    70 READ a
                    80 IF a<>z THEN PRINT "??": STOP
                    500 REM ***Данные для машинного кода
                    510 DATA  42,  11,  92,   1,   4
                    520 DATA   0,   9,  86,  14,   8
                    530 DATA   9,  94, 237,  83, 208
                    540 DATA 235,   9,  86,   9,  94
                    550 DATA 237,  83, 210, 235,   9
                    560 DATA  86,   9,  94, 237,  83
                    570 DATA 212, 235,  42, 210, 235
                    580 DATA  34,  26, 237, 205,  51
                    590 DATA 237, 237,  91, 208, 235
                    600 DATA  42, 212, 235,  34,  26
                    610 DATA 237, 205,  51, 237, 237
                    620 DATA  91, 210, 235,  42, 208
                    630 DATA 235,  34,  26, 237, 205
                    640 DATA  51, 237, 201,  40,   6
                    650 DATA  40, 143,  80, 123,   0
                    660 DATA  68,   0,   0,   0,   0

                          Дисассемблер программы:

         60300   2A0B5C        LD HL,(5C0BH)  ;См. с. 109...111
         60303   010400        LD BC,0004     ;Сдвиг от DEFADD на 4 бай-
         60306       09        ADD HL,BC      ;та (см. c.109...111).
         60307       56        LD D,(HL)      ;Координата x.
         60308     0E08        LD C,08        ;Сдвиг на
         60310       09        ADD HL,BC      ;восемь байтов.
         60311       5E        LD E,(HL)      ;Координата y.
         60312 ED53D0EB        LD(PLOT_1),DE  ;Запомнили x,y.
         60316       09        ADD HL,BC      ;Сдвиг на 8 байтов.
         60317       56        LD D,(HL)      ;Параметр p.
         60318       09        ADD HL,BC      ;Сдвиг на 8 байтов.
         60319       5E        LD E,(HL)      ;Параметр q.
         60320 ED53D2EB        LD(PLOT_2),DE  ;Запомнили p,q.
         60324       09        ADD HL,BC      ;Сдвиг на 8 байтов.
         60325       56        LD D,(HL)      ;Параметр r.
         60326       09        ADD HL,BC      ;Сдвиг на 8 байтов.
         60327       5E        LD E,(HL)      ;Параметр s.
         60328 ED53D4EB        LD(PLOT_3),DE  ;Запомнили r,s.
         60332   2AD2EB        LD HL,(PLOT_2) ;Коорд. 2-ой вершины.
         60335   221AED        LD (COORD),HL  ;Запоминаем координаты
                                              ;угла в ячейке 60698.
         60338   CD33ED        CALL ED33      ;Вызов процедуры FN g().
                                              ;Рисуем сторону 2-3.
         60341 ED5BD0EB        LD DE,(PLOT_1) ;Координаты 1-ой вершины.
         60345   2AD4EB        LD HL,(PLOT_3) ;Координаты 3-ей вершины.
         60348   221AED        LD (COORD),HL  ;
         60351   CD33ED        CALL ED33      ;Рисование стороны 1-3.
         60354 ED5BD2EB        LD DE,(PLOT_2) ;Координаты 2-ой вершины.
         60358   2AD0EB        LD HL,(PLOT_1) ;Координаты 1-ой вершины.
         60361   221AED        LD (ED1A),HL   ;
         60364   CD33ED        CALL ED33      ;Рисование стороны 1-2.
         60367       C9        RET            ;Выход из процедуры.

         60368          PLOT_1 DEFW           ;Коорд. первой вершины
         60370          PLOT_2 DEFW           ;Коорд. второй вершины
         60372          PLOT_3 DEFW           ;Коорд. третьей вершины
         60698          COORD  DEFW           ;Переменная, служащая для
                                              ;связи с процедурой печа-
                                              ;ти прямых линий.

                      Примеры использования процедуры.
                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
              Возможность  получения  изображения  треугольника является
         очень важной для программиста. К сожалению, в стандартном  БЕЙ-
         СИКе оператора для этой цели не предусмотрено, а ведь треуголь-
         ник служит базовым элементом для многих и многих геометрических
         форм и прочих изображений - пирамиды, горы, деревья, кустарники
         и пр. и  пр. Список можно  было бы продолжить.  Простейшая про-
         грамма  "Прожектор"  покажет  Вам  каких  оригинальных эффектов
         можно достичь изображением только треугольников.

              "Прожектор".
              ~~~~~~~~~~~~
                   100  DEF FN i(x,y,p,q,r,s) = USR 60300
                   110  BORDER 0: PAPER 0: INK 6:
                   120  CLS
                   130  LET s=4: LET a=0: LET ad=s*PI/128
                   140  LET x1=162: LET y1 = 20
                   150  FOR i=0 TO 255 STEP s
                   160  LET  x=x1+INT (90*SIN a)
                   170  LET  y=y1+INT (10*COS a)
                   180  LET  x2=x1+INT (90*SIN (a+PI))
                   190  RANDOMIZE  FN i(x,y,x2,y,5,170)
                   200  LET a=a+ad
                   210  NEXT i

              "Калейдоскоп".
              ~~~~~~~~~~~~~~~~
                   Если Вы в работе используете цветной телевизор (мони-
         тор), то не пожалеете,  что набрали следующую программу,  но не
         забудьте, что предварительно должен быть подгружен машинный код
         процедуры FN b(x,y,h,v,c,b,f).

                   100  DEF FN b(x,y,h,v,c,b,f) = USR 62800
                   110  DEF FN i(x,y,p,q,r,s) = USR 60300
                   120  BORDER 4: PAPER 4: INK 1:
                   130  CLS
                   140  FOR a=0 TO 75 STEP 4
                   150  RANDOMIZE FN i(a,0,0,175-a,0,0)
                   160  RANDOMIZE FN i(a,175,0,a,0,175)
                   170  RANDOMIZE FN i(255-a,175,255,a,255,175)
                   180  RANDOMIZE FN i(255-a,0,255,175-a,255,0)
                   190  NEXT a
                   200  RANDOMUZE FN b(8,4,16,14,2,0,0)
                   210  FOR a= 78 TO 178  STEP 4
                   220  RANDOMIZE FN i(a,38,178,a-40,256-a,138)
                   230  RANDOMIZE FN i(256-a,138,78,216-a,a,38)
                   240  NEXT a



СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



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

Похожие статьи:
Drink'em - Алкодомино.
О всём про всё - "В поисках Несси".
Письмо №281
Семь и 1/2 - Презентация Deja VU.
Юмор - Анекдоты.

В этот день...   21 ноября