IzhNews #09
05 сентября 2000

Nonsese - процедура и описание алгоритма эффекта Пламени (огня).

__________________________________________
┌─┬┐┌─┐┌─┬┐┌─┐┌─┐┌─┬┐┌─┐┌─┐
││││││││││││├┤││││││││├┤│││
││││││││││││ │││││││││ ││││
│││││││││││├┤││─┤││││├┤││─┤┌┐┌┐
└┴─┘└─┘└┴─┘└─┘└─┘└┴─┘└─┘└─┘└┘└┘

                                   Если кодеру отрезать руки,
                                   Если ноги отрезать тоже,
                                   Этот кодер помрет...со скуки,
                                   Потому что кодить не сможет!
(c)PIXel/BrC
__________________________________________

  Люди, как так можно? Вы только посмотри-
те, что  творится! Если в ЭСМИ есть что-то
для начинающих кодеров, то это обязательно
что-то типа: "Регистры бывают 8-и  и  16-и
разрядные... команды делятся на группы.. и
т.п.". Все это, конечно, хорошо, но  после
этого обычно  ничего  не  следует. Поэтому
новичок загружает, например, DoD  и  видит
там такое, что сразу теряет всякую надежду
написать что-либо красивое. Сегодня я  по-
пытаюсь объяснить, как разжечь огонь, буду
разжевывать алгоритм его создания.
  Ну,начнем:
               ORG 25000
               ENT
  Ах да, точно, надо бы сперва  придумать,
как  оно будет работать и как  имитировать
огонь. Ну так вот, делаем так:
  1.В буфере создаем массив,  элементы ко-
торого  задают интенсивность свечения эле-
мента огня  (например, артибута, чанка или
пикселя).
  2.Печатаем тот самый массив.
  3.Изменяем элементы массива по опреде-
ленным правилам.
  4.пауза, если необходимо.
  5.переходим к пункту 2.
  Правила  изменения массива в каждом слу-
чае свои (они могут зависеть и от печатал-
ки  буфера  на  экран). Элементарный огонь
подчиняется следующему правилу:
  Элемент буфера (х,у) принимает значение,
равное половине суммы его (х,у) значения и
значения элемента находящегося под ним (х,
у+1).Т.е:M[x,y]:=(M[x,y]+M[x,y+1])/2
если эти два элемента равны, то первый об-
нуляется:
  if M[x,y]=M[x,y+1] then M[x,y]:=0;
  M[x,y]:=(M[x,y]+M[x,y+1])/2;
  Нижняя строка элементов массива забивае-
тся случаимыми числами в пределах (max/2;
max),например:
    Исходный буфер:     Полученный буфер:
 0---------------->x 0----------------->x
 |................   |..........2......
 |..........5.....   |..13......2......
 |..27......5.....   |..13..1...3......
 |......3...2.....   |.....443.........
 |.....ххх........   |.....ХХХ.........
 y                   y
Как это ни странно, но получаем эффект го-
рящего  огня или пламени, что одно и тоже.
Если  все понятно, то продолжим, если нет,
то  читай  с  самого начала руководство по
программингу на BASIC'е.
  Для  простоты  будем  изображать буфер в
области  атрибутов  с #5b00. Буфер засунем
по  адесу  #c000, а занимать он будет, как
вы,  наверно,  догадались,  ровно   768+32
байтиков.
  Чистим буфер, что ли:
               LD      hl,#c000
               LD      de,#c001
               LD      (hl),L
               LD      bc,768+32
               LDIR
  Теперь будем над ним извращаться:
flame          LD      ix,#c000+32;[0,1]
               LD      de,#c000   ;[0;0]
               LD      bc,768     ;длина
begin          LD      a,(DE)     ;берем
               CP      (ix)       ;сравним
               JR      nz,loop1   ;не равно
               XOR     a          ;обнулим, если равно
loop1          ADD     a,(ix)     ;
               SRL     a          ; >M[x,y]:=(M[x,y]+M[x,y+1])/2
               LD      (de),A     ;/
               INC     ix         ; следующий
               INC     de         ;/ элемент
               DEC     bc         ;
               LD      a,B        ;
               OR      c          ;
               JR      nz,begin   ;если не все, то дальше

               CALL    print      ;печатаем на экран
               CALL    pr_key     ;опрос кнопков ;)

               LD      de,#c000   ;
               LD      a,R        ;
               AND     %00011111  ;
               LD      h,A        ;
               LD      a,R        ;
               LD      l,A        ;
               LD      de,#c000+768;типа на последнюю строку
               LD      bc,32      ; x'ов у нас 32
rnd            LD      a,R        ;
               OR      (hl)       ;сгенерили случайное число,
rang           AND     31         ;чтоб не больше max
               LD      (de),A     ;суем в последн строку
               INC     hl         ; следующий элемент
               INC     de         ;/ последней строки
               DJNZ    rnd        ;пока не кончатся x'ы
               JR      flame      ;и все с самого начала.

print          LD      hl,#c000   ;просто
               LD      de,#5800   ;кидаем
               LD      bc,768                    LDIR               ;атрибуты
               RET                ;и назад.

pr_key         LD      bc,#7ffe   ;там SPACE живет
               IN      a          ;это IN (C),A
               BIT     0,a        ;самый нулевой бит.
               RET     nz         ;типа никто SP не жал.
               POP     de         ;если надавил, то
               RET                ;возврат в XAS.

 Вот, в принципе, и весь исходник, но мно-
гим  может  не  понравиться то, что в пла-
мени присутствуют синие, зеленые, фиолето-
вые  элементы. Это, конечно, можно  испра-
вить, чем мы, собственно говоря, и займем-
ся. Для начала решим, какие атрубуты в ог-
не присутствовать должны. Рассмотрим их по
нарастающей:
(буду использовать сокращение: pXiY где X-
цвет paper'а, Y-цвет ink'а)
   #00 = p0i0 = %00000000
   #01 = p0i2 = %00000010
   #02 = p0i6 = %00000110
   #03 = p0i7 = %00000111
   #04 = p2i0 = ...
   #05 = ...
   ...
   #0e = p7i6
   #0f = p7i7
Я думаю, вы поняли принцип: должны присут-
ствовать только черный, красный, желтый  и
белый  цвета. Значит, от  нашей  печаталки
требуется принтить в атрибуты не сами зна-
чения  элементов, а  соответствующие  этим
значениям атрибуты. Теперь замените строку
 rang
на:  rang  AND  15  ;  т.к.  значений  15,
а  Call print  на  Call pr_buff.

pr_buff        LD      de,buff      ;начало буфера.
               LD      hl,#5800     ;куда принтим.
               LD      bc,768       ;сколько элементов.
pr_b0          PUSH    bc           ;чтоб не забыть :) .
               LD      a,(DE)       ;возьмем, чтоб разглядеть.
               AND     #0f          ;нам чужого(a>15) не надо.
               PUSH    hl           ;смотри pr_b0.
               LD      hl,cnv_tab   ;начало таблицы атрибутов,
               LD      b,0          ;в которой записано, какому
               LD      c,A          ;значению какой атрибут
               ADD     hl,BC        ;соответствует.
               LD      a,(HL)       ;берем из таблички
               POP     hl           ;вспомним HL
               LD      (hl),A       ;зафигачим, куда надо :)
               POP     bc           ;скока тама ужо элементов?
               INC     hl           ;дальше - больше!
               INC     de           ;больше и лучше! :)
               DEC     bc           ;осталось на одного меньше.
               LD      a,B          ;
               OR      c            ; > всё или как?
               JR      nz,pr_b0     ;/ если не всё, то или как.
               RET                  ;всё так всё, я не виноват.
cnv_tab
;000102030405060708090a0b0c0d0e0f   ;табличка значений для тебя.
#000206071012161730323637383a3e3f   ;соответствующие атрибуты.

   Вот и всё. Вроде,ничего сложного - ста-
тья  даже не требует глубоких знаний мате-
матики  (хотя  кодеру  они не вредят). Все
исходники  написаны на XAS'е, а посему мо-
жет присутствовать специФИЧНЫЙ синтаксис и
прочее, например:
   #0123456789abcdef
надо понимать как:
   DB #01,#23,#45,#67,#89,#AB,#CD,#EF
Вообще, для написания небольших программ и
алгоритмов  этот  ассемблер подходит лучше
всего  (хотя, может, не лучше STORM'а). Он
является  компромиссом  между  STORM'ом  и
ALASM'ом (версии 4.2). Пишешь 3D-rotator -
грузи STORM, пишешь операционную систему -
добро  пожаловать  в  ALASM. Вот если бы к
ALASM'у  приделать XAS'овый или STORM'овый
редактор, то получится  АССЕМБЛЕР МЕЧТЫ, и
я думаю, что не только  моей. Ну да ладно,
чё-то меня не в ту сторону занесло. Совсем
не слышу никаких отзывов :( Наверно, зря я
тут стараюсь, и Nonsense... можно закрыва-
ть как раздел. Буду вам рассказывать  луч-
ше, как  я в детском саду (когда был мале-
нький) выжигал детям ладони увеличительным
стеклом (фокусируя лучь на кожу) и т.п. :)
Опять не туда... Ладно, похоже, на сегодня
всё, что  я  знал  об  огне, я  рассказал.
Пока.
   P.S. забыл сказать еще одну формулу:
M[x,y]:=(M[x-1,y+1]+M[x,y+1]+M[x+1,y+1]+M[x,y])/4
   Вот теперь всё!
__________________________________________




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

Похожие статьи:
Обмен опытом - Как не платить за междугородние телефонные разговоры?
Oт редакции - Приближается Enlight'97.
Железо - история подключение Hayes модема в Уфе.

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