Video of it running: https://www.youtube.com/watch?v=z8j8_LLqKCo
Screenshot: Disc image: Owlet link (takes about a minute to load as it lacks precalculated data): http://tinyurl.com/37fv8yxa
The BASIC program is below. It requires a data file that's already on the disc image above, but which can be regenerated by going to MODE 2 and calling PROCgen(40,14) - the first parameter affects the density of the snow.
Code: Select all
10 MODE 2
20 ?&FE4C=?&FE4C OR 1
30 VDU 23;8202;0;0;0;
40 FOR I%=0 TO 14:VDU19,I%,0;0;:NEXT
50 VDU 19,15,7;0;
60 COLOUR 15:PRINTTAB(5,30);"Loading...";
70 *LOAD bg
80 :
90 PRINTTAB(0,0);
100 PROCmessage
110 :
120 PROCanimate(14)
130 :
140 MODE 7
150 END
160 :
170 DEFPROCgen(N%,M%)
180 CLG
190 FOR I%=0 TO N%-1
200 X%=1280*(I%+RND(1))/N%
210 PROCflake(X%,RND(M%))
220 NEXT
230 OSCLI("SAVE bg 3000 8000")
240 ENDPROC
250 :
260 DEFPROCanimate(M%)
270 :
280 PROCsettle2init
290 TI%=TIME
300 I%=1
310 :
320 REPEAT
330 :
340 TI%=TI%+1
350 REPEAT UNTIL TIME>=TI%
360 :
370 J%=(I% MOD M%)+1
380 A$=CHR$19+CHR$J%+CHR$7+CHR$0+CHR$0+CHR$0+CHR$19+CHR$I%+CHR$0+CHR$0+CHR$0+CHR$0
390 *FX19
400 PRINTA$;
410 REMVDU 19,J%,7;0;19,I%,0;0;
420 I%=J%
430 :
440 PROCsettle2
450 :
460 UNTIL0
470 :
480 ENDPROC
490 :
500 DEFPROCflake(X%,C%)
510 Y%=504
520 V%=RND(9)-5
530 W%=RND(5)-3
540 Z%=X%-V%-W%
550 D%=C%-1:IF D%=0 D%=M%
560 REPEAT
570 P%=X%+640:IF P%>1279 P%=P%-1280
580 Q%=Z%+640:IF Q%>1279 Q%=Q%-1280
590 GCOL 0,C%
600 PLOT 69,X%,Y%
610 PLOT 69,Q%,Y%+4
620 GCOL 0,D%
630 PLOT 69,Z%,1016-Y%
640 PLOT 69,P%,1020-Y%
650 V%=V%+RND(5)-3-(V% DIV 4)
660 IF V%<-6 V%=-6 ELSE IF V%>6 V%=6
670 X%=X%+V%+W%
680 Z%=Z%-V%-W%
690 IF X%>1279 X%=X%-1280 ELSE IF X%<0 X%=X%+1280
700 IF Z%>1279 Z%=Z%-1280 ELSE IF Z%<0 Z%=Z%+1280
710 Y%=Y%-8
720 C%=C%+1:IF C%=M%+1 C%=1
730 D%=D%-1:IF D%=0 D%=M%
740 UNTILY%=0
750 ENDPROC
760 :
770 DEFPROCsettle2
780 S%=S%+1
790 T%=T%+1
800 IF T%=256 T%=0:U%=U%+1
810 X%=RND(160)-1
820 Y%=H%(X%)+1
830 IF Y%<=U% H%(X%)=Y%
840 GCOL 0,15
850 PLOT 69,8*X%,32*R%+4*Y%
860 ENDPROC
870 :
880 DEFPROCsettle2init
890 DIM H%(160)
900 FOR I%=0 TO 160:H%(I%)=-1:NEXT
910 S%=0:T%=0:U%=0
920 VDU 19,15,7;0;
930 ENDPROC
940 :
950 DEFPROCst2
960 REPEAT
970 PROCsettle2
980 UNTILU%>256
990 ENDPROC
1000 :
1010 DEFPROCreduce(A$)
1020 PRINTTAB(0,0);A$''
1030 FOR I%=0 TO LEN(A$)-1
1040 FOR Y%=0 TO 7
1050 D%=?(&3000+Y%+I%*8)
1060 D%=D% AND &55
1070 D%=D%+(D% DIV 2)
1080 D%=D% AND &33
1090 D%=D%+(D% DIV 4)
1100 D%=D% AND &0F
1110 IF NOT I% AND 1 THEN D%=D%*16
1120 A%=&3000+640+Y%+(I% DIV 2)*8
1130 ?A%=?A% OR D%
1140 NEXT
1150 NEXT
1160 :
1170 FOR X%=0 TO 19:PRINTSTR$(3000+X%);" DATA ";:FOR I%=0 TO 7:PRINT"&";STR$~(?(B%+8*X%+I%));",";:NEXT:PRINTCHR$8;" ":NEXT
1180 ENDPROC
1190 :
1200 DEFPROCmessage
1210 FOR X%=0 TO 19
1220 IF (X% MOD 7)=0 RESTORE ELSE IF X%=19 RESTORE 1360
1230 VDU 23,224
1240 FOR I%=0 TO 7:READ A%:VDU A%:NEXT
1250 VDU 224
1260 NEXT
1270 ENDPROC
1280 :
1290 DATA &80,&80,&84,&8A,&8E,&88,&E6,&0
1300 DATA &40,&40,&E0,&40,&40,&40,&20,&0
1310 DATA &44,&4,&4E,&44,&44,&44,&22,&0
1320 DATA &0,&0,&6,&8,&4,&2,&C,&0
1330 DATA &0,&0,&C4,&AA,&AA,&AA,&A4,&0
1340 DATA &0,&0,&88,&88,&A8,&F9,&51,&2
1350 DATA &0,&0,&0,&0,&0,&0,&0,&0
1360 DATA &2,&2,&8A,&8A,&AA,&F8,&52,&0
The text was originally drawn in MODE 0 by picking alternate columns from the standard character set, then hand-edited in DATA statements. This process can be repeated by using PROCgenerate("your message here") while in MODE 0, which does the calculations and outputs the DATA lines that are needed.
I experimented quite a bit with the algorithm for how the flakes would fall, and sped it up a bit by drawing several related flake trails simultaneously with various reflections and offsets active. I also tried rendering the flakes as two stacked pixels, to get rounder flakes, but switched back again as flake trails overlapping each other causes a flickering and I thought it better to reduce how much that happened.
There's also an algorithm for showing snow settling at the bottom of the screen. I used something probabilistic at first, but then switched to a bit more of a brute force method - storing the height of each column of pixels in an array. This allowed more control over the rate and evenness of the snow build-up and prevented leaving any gaps even temporarily.
Line 340 can be used to throttle the animation speed - values above about 4 will start slowing things down. 4 corresponds to 25Hz, which is I think about as fast as it can go.