
-----------------------------------
Abstraction
Fri Apr 06, 2007 1:02 pm

3D Snowflake Generator!
-----------------------------------
It doesn't really generate 3D snowflakes per se, but it does look very three-dimensional
The code isn't very....logical, since it took a lot of fiddling to get it to work in its current state

Also, the snow only moves in one direction at the moment: down. I haven't got it to move in a very snow-like fashion yet


setscreen ("graphics:550;350;position:center;center,nobuttonbar")
View.Set ("offscreenonly")
const CX := maxx div 2
const CY := maxy div 2

var sX : array 1 .. 6 of int
var sY : array 1 .. 6 of int
var minSnowSize : int := 8
var maxSnowSize : int := 17

var flakes : int := 20
var lA : int := 0

fcn cosP (deg, x : int, mX : real) : int
    result round (cosd (deg) * (mX)) + x
end cosP

fcn sinP (deg, y : int, mX : real) : int
    result round (sind (deg) * (mX)) + y
end sinP

fcn angle (x, y : int) : real
    if x = 0 then
        if y > 0 then
            result - 90
        else
            result 90
        end if
    elsif x > 0
            then
        result arctand (y / x)
    else
        result arctand (y / x) + 180
    end if
end angle

var x, y, centerx, centery, a, d, c : array 1 .. flakes, 1 .. 8, 1 .. 6 of int
var n : int := 1

proc assign (xl, yl, cx, cy, nf, i, s : int)
    x (nf, n, i) := xl
    y (nf, n, i) := yl
    a (nf, n, i) := round (angle (xl - cx, yl - cy))
    d (nf, n, i) := round (sqrt ((xl - cx) ** 2 + (yl - cy) ** 2))
    c (nf, n, i) := s + (31 - maxSnowSize)

    %Makes the flakes generally brighter
    if c (nf, n, i) not= 31 then
        c (nf, n, i) += 1
    end if

    centerx (nf, n, i) := cx
    centery (nf, n, i) := cy
end assign

proc oct (s, x, y, cx, cy, nf, snowSize : int)
    for i : 1 .. 6
        sX (i) := round (cosd (i * 60) * s) + x
        sY (i) := round (sind (i * 60) * s) + y
        assign (sX (i), sY (i), cx, cy, nf, i, snowSize)
    end for

    if n < 8 then
        n += 1
    else
        n := 1
    end if
end oct

proc sF (sx, sy, s, nf : int)
    oct (s, sx, sy, sx, sy, nf, s)
    oct (round (s * 0.8), sx, sy, sx, sy, nf, s)

    for i : 1 .. 6
        oct (round (s * 0.3), cosP (i * 60, sx, s * 1.5), sinP (i * 60, sy, s * 1.5), sx, sy, nf, s)
    end for
end sF

for i : 1 .. flakes
    sF (Rand.Int (1, maxx), Rand.Int (1, maxy), Rand.Int (minSnowSize, maxSnowSize), i)
end for

var deg : int

%Varies the snow path
var snowPath : int

var r : array 1 .. flakes of int
for i : 1 .. flakes
    r (i) := 0
end for

var v : int := 6
var sA : int := 270

%Rotates as if it was three dimensional
fcn rotate3D (i, ii, iii, r : int) : int
    result round ((x (i, ii, iii) - centerx (i, ii, iii)) * cosd (r)) + centerx (i, ii, iii)
end rotate3D

loop
    drawfillbox (0, 0, maxx, maxy, 17)

    for i : 1 .. flakes
        %Ensures that each snowflake will rotate at a random speed
        %this method used so that segments of flake are consistent.
        deg := Rand.Int (3, 13)

        %3D Rotation value- Randomized rotation speed
        r (i) += Rand.Int (-5, 25)
        snowPath := Rand.Int (-15, 15)

        if r (i) > 360
                then
            r (i) -= 360
        end if

        %Tries to make sure that it doesn't flatten- looks ugly
        if abs (r (i) - 90) < 10 or abs (r (i) - 270) < 10
                then
            r (i) += 15
        end if

        for ii : 1 .. 8

            for iii : 1 .. 5
                drawline (rotate3D (i, ii, iii, r (i)), y (i, ii, iii),
                    rotate3D (i, ii, iii + 1, r (i)), y (i, ii, iii + 1), c (i, ii, iii))
            end for
            drawline (rotate3D (i, ii, 6, r (i)), y (i, ii, 6), rotate3D (i, ii, 1, r (i)), y (i, ii, 1), c (i, ii, 1))

            %Reassigns the locations for 3D effect
            for iii : 1 .. 6
                %2D Rotation
                a (i, ii, iii) += deg
                x (i, ii, iii) := round (cosd (a (i, ii, iii)) * d (i, ii, iii)) + centerx (i, ii, iii)
                y (i, ii, iii) := round (sind (a (i, ii, iii)) * d (i, ii, iii)) + centery (i, ii, iii)

                %Moves the flakes based on velocity and angle
                x (i, ii, iii) += round (cosd (sA + snowPath) * v)
                y (i, ii, iii) += round (sind (sA + snowPath) * v)
                centerx (i, ii, iii) += round (cosd (sA) * v)
                centery (i, ii, iii) += round (sind (sA) * v)
            end for
        end for
    end for

    %Generates new snowlakes when old ones disappear
    for i : 1 .. flakes
        for ii : 1 .. 8
            for iii : 1 .. 6
                %Generates a new snowflake everytime one leaves the boundaries of the screen
                if centerx (i, ii, iii) < -18 or centerx (i, ii, iii) > maxx + 18
                        or centery (i, ii, iii) < -18
                        then
                    sF (Rand.Int (0, maxx), Rand.Int (maxy, maxy + 200), Rand.Int (8, 16), i)
                end if
            end for
        end for
    end for

    View.Update
end loop


-----------------------------------
LaZ3R
Fri Apr 06, 2007 5:11 pm

Re: 3D Snowflake Generator!
-----------------------------------
You only really need to Rand.Int the new x value of each snowflake, and make it so that the bigger snowflakes have a greater decrease in y value compared to the smaller ones... I'm slightly confused with your coding though :(

Very cool program however! :)

-----------------------------------
lordroba
Fri Apr 06, 2007 8:13 pm

Re: 3D Snowflake Generator!
-----------------------------------
wow, there is a really messed up glitch.  Try these settings for the min and max snowflake size
var minSnowSize : int := 1
var maxSnowSize : int := 2

after an initial round of small white snowflakes, you get big colorful snowflakes.  it's really weird.

-----------------------------------
Abstraction
Mon Apr 09, 2007 1:58 pm

Re: 3D Snowflake Generator!
-----------------------------------
Ah....oops....I was supposed to use the minSnowSize & maxSnowSize variables instead of 8 and 16 ^^

 %Generates new snowlakes when old ones disappear
for i : 1 .. flakes
for ii : 1 .. 8
for iii : 1 .. 6
%Generates a new snowflake everytime one leaves the boundaries of the screen
if centerx (i, ii, iii) < -18 or centerx (i, ii, iii) > maxx + 18
or centery (i, ii, iii) < -18
then
sF (Rand.Int (0, maxx), Rand.Int (maxy, maxy + 200), Rand.Int (8, 16), i)
end if
end for
end for
end for

-----------------------------------
kshorting
Wed Apr 25, 2007 10:17 pm

Re: 3D Snowflake Generator!
-----------------------------------
Very cool.  I like it.  Mistakes and all.  Thanks for your hard work to put this together.
