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 Вот теперь всё! __________________________________________
Другие статьи номера:
Похожие статьи:
В этот день... 21 ноября