❄ Snow!

``````from random import randint

class flake:
def __init__ (self,x,y):
self.vec = PVector(x,y)
self.z = random(0,3)
self.velY = map(self.z,0,3,0.5,1)
self.velX = 0

def show(self):
ellipse(self.vec.x,self.vec.y,map(self.z,0,3,2,5),map(self.z,0,3,2,5))

def update(self):
self.vec.y += self.velY
self.vec.x += self.velX
self.velY += 0.01
if self.velX > 0:
self.velX -= 0.01
elif self.velX < 0:
self.velX += 0.01

if self.vec.y > height:
self.vec.x = randint(0,width)
self.vec.y = randint(-500,-50)
self.velY = map(self.z,0,3,0.5,1.5)
if self.vec.x < 0:
self.vec.x = randint(350,width)
if self.vec.x > width:
self.vec.x = randint(0,100)

width = 700
height = 500
snow = []
total = 1001 #num of snowflakes

for i in range(0,total):
snow.append(flake(randint(0,width),randint(-500,50)))

def setup():
size(width,height)
noStroke()
fill(178,32,201)

def draw():
background(150)
for i in range(0,total):
snow[i].show()
snow[i].update()
if keyPressed:
if key == "w":
for i in range(0,total):
a = map(snow[i].z,0,3,0.01,0.03)
snow[i].velY -= a
if key == "s":
for i in range(0,total):
a = map(snow[i].z,0,3,0.01,0.03)
snow[i].velY += a
if key == "d":
for i in range(0,total):
a = map(snow[i].z,0,3,0.01,0.03)
snow[i].velX += a
if key == "a":
for i in range(0,total):
a = map(snow[i].z,0,3,0.01,0.03)
snow[i].velX -= a
if key == "r":
del snow [:]
for i in range(0,total):
snow.append(flake(randint(0,width),randint(-500,50)))

``````

(I know that with rain I have less gravity acceleration limitations, but in my city snowed )

Use wasd to control snow, r to reset
(If I add more i lag )

What can I improve?

In `draw` loop you have this operations:

`a = map(snow[i].z,0,3,0.01,0.03)`
`map(self.z,0,3,2,5)`
`self.velY = map(self.z,0,3,0.5,1.5)`

They depends on `z` that isn’t changing. By counting this values before drawing you can win some processing time.

1 Like

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!

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