❄ Snow!

I’ve refactored the original code in order to cache all pre-calculated values. :heavy_plus_sign:
However, it didn’t speed anything. Alas, I guess it’s got slightly slower! :no_mouth:
Regardless, using FX2D instead of default JAVA2D is what actually makes the sketch race! :racing_car:

"""
 Snow! (v1.1)
 by Sky (2019-Jan-04)
 mod GoToLoop (2019-Jan-07)
 https://Discourse.Processing.org/t/snow/7156/3
"""

from math import copysign

FLAKES, YMIN, YMAX = 1001, -500, 50
RANGE = tuple(range(FLAKES))

def setup():
    size(700, 500, FX2D)
    noStroke()
    fill(178, 32, 201)

    global flakes
    flakes = tuple(Flake(random(width), random(YMIN, YMAX)) for i in RANGE)


def draw():
    background(150)
    for f in flakes: f.show().update()
    changeAllFlakesSpeed()
    this.surface.title = 'FPS: ' + `this.round(frameRate)`


def keyPressed():
    k = chr(keyCode) if key != CODED else keyCode

    if k == 'R' or k == ENTER or k == RETURN:
        for f in flakes: f.reset(random(width), random(YMIN, YMAX))


def changeAllFlakesSpeed():
    if not keyPressed: return

    k = key.upper() if key != CODED else keyCode

    if k == 'W' or k == UP:
        for f in flakes: f.vel.y -= f.maps[2]

    elif k == 'S' or k == DOWN:
        for f in flakes: f.vel.y += f.maps[2]

    elif k == 'A' or k == LEFT:
        for f in flakes: f.vel.x -= f.maps[2]

    elif k == 'D' or k == RIGHT:
        for f in flakes: f.vel.x += f.maps[2]


class Flake:
    Z, INC = 3.0, .01

    def __init__(f, x, y):
        f.vec = __pvector__()
        f.vel = __pvector__()
        f.reset(x, y)


    def __str__(f):
        return 'vec: %s\tvel: %s' % (f.vec, f.vel)


    def reset(f, x, y):
        z = random(f.Z)

        f.maps = (
            map(z, 0, f.Z, .5, 1.5),
            map(z, 0, f.Z, 2, 5),
            map(z, 0, f.Z, .01, .03)
        )

        f.vec.set(x, y)
        f.vel.set(0, f.maps[0])

        return f


    def show(f):
        ellipse(f.vec.x, f.vec.y, f.maps[1], f.maps[1])
        return f


    def update(f):
        f.vec.add(f.vel)
        f.vel.add(copysign(f.INC, -f.vel.x), f.INC)

        if f.vec.y > height:
            f.vec.set(random(width), random(YMIN, -YMAX))
            f.vel.y = f.maps[0]

        if   f.vec.x < 0:     f.vec.x = random(width>>1, width)
        elif f.vec.x > width: f.vec.x = random(100)

        return f
1 Like