SNOWFLAKES
'Twas the night before Christmas, and all through the house, not a creature was stirring, not even a mouse...except for me and my Atari, that is. According to a REM statement in the first version of this program, it was 3:20 in the morning on December 25 when "Snowflakes" first ran successfully. Luckily, with this ready-to-type-in listing, you won't have to stay up until the wee small hours!
The program calls on your Atari's artistic skills to draw lacy, detailed snowflakes in GRAPHICS 8+16. And, by using the RND (random) function, the Atari snowflakes imitate Mother Nature's - no two will be alike. Let's look at how it works.
Drawing the main arms of the snowflakes is easy enough: just draw six equally-long lines outward from the center of the screen, at angles of 0,60,120,180,240, and 300 degrees. (Snowflakes have six equally-spaced arms 60 degrees apart.)
How do you make the arms equally long when they're not just vertical or horizontal lines -- when they're at an angle? There are several ways, but I decided to think of each arm as being a radius of a circle. This allows you to locate any point along the arm with two equations:
X=RDS*SIN(angle)+160
Y+RDS*COS(angle)+96
where X,Y is the location of the point, RDS is the radius of the circle (distance from the center), and 160 and 96 are the horizontal and vertical center of the screen in GR.8+16. Note that since we're expressing angles in degrees, the program has to include the DEG command - see line 1120. Without it, the Atari computes angles in radians. (one radian equals about 57 degrees.)
How long should the arms be? I chose 84 as the length because it looks attractive - the snowflakes fill the screen nicely without crowding the edges. 84 is also evenly divisible by 6, which makes some calculations convenient later on.
Once the six arms are drawn, the program goes back to the center of the snowflake and begins drawing the little spikes that extend from the arms. The spikes are random lengths and are placed either three or six units apart. They can point outward from the center, point inward, or alternate their directions. (In my original early-morning program, these factors were randomly selected. However, this required using the RND function many times while drawing each snowflake, and the drawing went very slow. Simplifying things in the way I've described speeds up the program without really reducing the variety of snowflakes you'll see.)
The variable TYPE defines 12 different kinds of snowflakes, with an almost-infinite variety of patterns possible within each type. In addition to varying the distance between spikes and which way they point, TYPE specifies whether the spikes will be just random lengths or whether they will be random but will taper to shorter and shorter sizes as you move out toward the end of each arm. I don't know exactly what shapes it is possible to find in real snowflakes, but using these variables creates patterns that look pretty lifelike to my eye. (And I'm a lifelong resident of Rochester, New York, where everyone is an expert on snow!)
SETTING THINGS UP
The program begins by jumping past the drawing routine (lines100-270) and going to the setup or initialization section. This is done to keep the frequently-used FOR/NEXT loops in the drawing section as close to the beginning of the program as possible. When the program is running, the Atari has to look for each FOR/NEXT loop beginning at program line 0. The closer the loop is to the beginining, the faster the program will run. Since a single snowflake has as many as 336 spikes, shaving time from the drawing routine makes a noticeable difference.
Line 1000 sets up GR.1 for the title screen. It also sets CONSOLE=53279, which is memory location for reading whether the console keys ([START],[SELECT],[OPTION]) have been pressed. Also, if you POKE a number into this memory location, the Atari's built-in speaker (not the television speaker) buzzes.
Lines 1010 through 1110 generate the opening display. 1100 simply loops back on itself until [START] is pressed. 1120 DIMensions two matrixes and one array: TRIG, which stores sine and cosine values; TILT, which stores the angles for the spikes. 1130-1150 place the necessary numbers into TRIG and TILT. (Arrays and matrixes are simply series of variables - like A,B,C - but since they're indexed by number - like SPIKE(10) - they're valuable in FOR/NEXT loops, because you can use each number in turn.)
Lines 1200-1290 set the snowflake TYPE and compute the numbers that make each snowflake different: ST, the step size between spikes (either 3 or 6); TAPER, to set whether the random lengths will taper or not; and SLANTFLAG, to determine the direction of the spikes. Lines 1250-1270 fill the SPIKE array with random numbers of the needed size. POKE location 77 with 0, in line 1280, to prevent the Atari from going into its color-shifting attract mode. (Pressing any regular key on the keyboard prevents this, but using the console keys such as [START] does not turn off the attract mode.) Finally, line 1290 sends us back to the drawing routine at line 100.
DRAWING A SNOWFLAKE
Line 100 sets high-resolution graphics (GR.8+16=GR.24, the full-screen version without a text window at the bottom). The background color will be blue if it isn't changed, and the program uses blue when TYPE=1, by skipping line 110. If TYPE=2 to 12, line 110 sets a random color and brightness for the background and the lines in the snowflakes.
Line 120 draws the main arms. The TRIG matrix serves as a look-up table for the sine and cosine values needed. The reason for using a matrix instead of just including SIN and COS commands is that the trigonometric functions are relatively slow, and using them hundreds of times for each snowflake slows down the drawing process. Especially since we're using only 12 trig values anyway (sine and cosine for 0,60,120,180,240, and 300 degrees), it's faster to place the values in a matrix and just look them up instead of recomputing them.
Lines 130-230 are the main drawing loop. RDS is the radius, or distance from the center; the program starts at the center and works its way out to the ends of the arms. First, it checks how long the spike will be (SPIKELN) by looking in the SPIKE array. Then it determines the direction of the spike from SLANTFLAG, and switches SLANT from 0 to 1 for the designs that alternate directions. In line 170, D1 and D2 are the codes for the two spikes' directions - one on each side of the arm - taken from the TILT matrix. 180-200 compute X and Y for the spot on each arm from which the spikes branch out, and X1,Y1 and X2,Y2 are the ends of the two spikes.
After all that, line 210 is very simple command that actually draws the spikes. 220 and 230 complete the loops, and 240 buzzes the speaker to say that the snowflake is done. After you press [START], the program goes back to line 1200 to change to the next TYPE...and then it's back to line 100 to draw the next snowflake.
There are certainly other ways this program could be written, and some of them are simpler. I took this approach to make the drawing go as fast as possible. I avoided repeated SIN, COS, and RND commands in the main drawing routine by calculating the values in advance and storing them in arrays and matrixes, so the program could just look them up. For a program written entirely in BASIC, the drawing speed is very satisfactory.
Perhaps the best part of this is that you can type in the program and run it even if some parts aren't completely clear. And if you have questions or suggestions about "Snowflakes," please send them to ANTIC. We'd like to hear from you!
Listing: SNOWFLAK.BAS Download