# ❄ Snow!

**URL:** <https://discourse.processing.org/t/snow/7156>\
**Category:** Processing.py\
**Created:** [January 4, 2019, 11:31am UTC](https://discourse.processing.org/t/snow/7156 "2019-01-04T11:31:05Z")\
**Posts on this page:** 1\
**Showing post:** 3

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [January 7, 2019, 6:12pm UTC](https://discourse.processing.org/t/snow/7156/3 "2019-01-07T18:12:44Z")

</div>

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

```python
"""
 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

```

---

_[View the full topic](https://discourse.processing.org/t/snow/7156)._
