(Кадр м/ф «Падал прошлогодний снег», «Союзмультфильм», 1983 г.)
А вернее не прошлогодний, а олдскульный. Да и речь пойдет не о быстрых алгоритмах а об истории создания демо. По окончании зимы неплохо бы вспомнить об старом и красивом эффекте. Думаю, что многие вспомнят об увиденном эффекте в Blastersound BBStro by iguana.
Похожий эффект я решил сделать для проведения NY gift compo,объявленный ААА в 2012 году. Для bbstro приложены исходные тексты, где написано следующее:
very first ASM routines that JCAB and I coded, long ago, on
the ZX Spectrum. We liked the way it looked, and as it
seems that this year we will not have snow in Madrid, we
brought the concept back. :-) Of course, we have improved it
(more pixel resolution and a random windy thing).
Я провел несколько часов, рассматривая, как работает эффект, потому что не разобрался в исходных текстах из-за незнания VGA.
Первая идея была следующая: нужно посчитать количество точек под пикселем (снежинкой):
*
421
Позиции точек пронумерованы для удобства, таким образом получается 8 значений, в зависимости от которых реализуется поведение снежинки:
0 (бинарное 0b000) — снег падает вниз
1 (0b001) – то же самое
4 (0b100) – то же самое
5 (0b101) – то же самое
2 (0b010) – производится случайный выбор: куда скатится снежинка, влево или вправо.
3 (0b011) – снежинка падает влево
6 (0b110) – снежинка падает вправо
7 (0b111) – стоп движения
Я написал простой код и после просмотра работы добавил еще одну вариацию — скорость падения.
Исходный код я прокомментирую по частям:
device zxspectrum128 ORG #4000 incbin "tree2-3.scr" ORG #6000 begin
6800-68FF: младший байт экранного адреса
6900-69FF: старший байт экранного адреса
6A00-6AFF: значение X/8
6B00-6BFF: битовые значения 128,64,32,16,8,4,2,1 для X.
;-----------tables for fast plot-------------------- FORMER LD DE,#4000,BC,#8000,L,E FLP1 LD H,PLOTTBL/256 LD (HL),D:INC H:LD (HL),E:INC H LD (HL),C:INC H:LD (HL),B RRC B LD A,C:ADC A,0:LD C,A FBR1 INC D:LD A,D:AND 7 JR NZ,FNXT:LD A,E:ADD A,32 LD E,A:JR C,FNXT LD A,D:SUB 8:LD D,A FNXT INC L:JR NZ,FLP1 LD HL,PLOTTBL+#C0,BC,#3F LD DE,HL:INC E LD (HL),0:LDIR
6C00-6CFF – X координата точки
6D00-6DFF – Y координата точки
6E00-6EFF – скорость падения точки
;-------------------------- PLOTTBL EQU #6800 yacc equ #6c00 sn equ #6d00;x,y=#6E000 ld hl,yacc ylp1:ld (hl),3:inc l:jr nz,ylp1;!3 ld b,170/2 ylp2:ld (hl),2:inc l:djnz ylp2 ld hl, sn prep_snowflake: call random ld (hl),a:inc h call random:and #0F ld (hl),a:dec h inc l:jr nz,prep_snowflake ;Начало работы ;----------------------main loop repeat1: ld hl, sn ei:halt
proceed_snow:
ld e,(hl):inc h:ld d,(hl):dec h ; ;стереть точки ; push de:exx:pop de LD H,HIGH PLOTTBL,L,D,B,(HL):INC H LD A,(HL),L,E ;B.A-адрес вертикальной линии INC H OR (HL) ;C+X/8 – адрес экрана по координатам. INC H:LD C,A
ld A,(BC),e,a
ld a,(HL) cpl and e LD (BC),A exx ld b,yacc/256,c,l,a,(bc),c,a ; ;движение "скорость" ;
push de,bc ld b,0 yloop: inc d push hl,bc LD H,HIGH PLOTTBL,L,D,B,(HL):INC H LD A,(HL),L,E:INC H:OR (HL) INC H:LD C,A ld A,(BC) and (hl) pop bc,hl jr z,foundbyte inc b foundbyte dec c:jr nz,yloop ld a,b pop bc,de or a:jr nz,step_one ld a,c:add a,d:ld d,a jr start_check
step_one: inc d start_check: push de inc e ld c,#00 call getpixel jr z,nextpix1 inc c;set 0,c nextpix1: dec e call getpixel jr z,nextpix2 set 1,c nextpix2: dec e call getpixel jr z,nextpix3 set 2,c nextpix3: pop de
push hl ld h,0,l,c add hl,hl ld bc,casetab add hl,bc ld c,(hl):inc hl ld b,(hl) pop hl push bc ret casetab: dw L1,L1,case3,case3,L1,L1,case6,case7 ;case0:;000 ; jp L1 ;case1:;001 ; jp L1 case2:;010 call random and 2:dec a:add a,e:ld e,a;+1 or -1 jp L1 case3:;011 dec e jp L1 ;case4:;100 ; jp L1 ;case5:;101 ; jp L1 case6:;110 inc e jp L1 case7:;111--------------stop dec d call putpixel ld d,0;;10h;0 call random ld e,a ; jp L1
L1: call putpixel ld (hl),e:inc h:ld (hl),d:dec h
inc l bit 7,l:jp z,proceed_snow
jp repeat1;to the loop ;---------------------------------------------
putpixel push hl LD H,HIGH PLOTTBL,L,D,B,(HL):INC H LD A,(HL),L,E:INC H:OR (HL) INC H:LD C,A ld A,(BC) OR (HL):LD (BC),A pop hl ret getpixel push de exx pop de LD H,HIGH PLOTTBL,L,D,B,(HL):INC H LD A,(HL),L,E:INC H:OR (HL) INC H:LD C,A ld A,(BC) and (HL) exx ret random LD A,(R1),C,A LD A,(R2):ADD A,C:LD C,A LD (R1),A,A,(R3) SUB C:LD C,A,(R2),A RRCA:LD (R3),A LD A,C RET R1 DB #15 R2 DB #70 R3 DB #FD end display /d,end-begin savesna "SnowF.sna",begin
Сообщение форума