Skip to main content

Snow effect

Author: NingNing
Last update:2022-05-28

It's not a tutorial, you can directly copy the code to use in your game


The following code should be placed before label start

init python:
import random
random.seed()

def Snow(image, max_particles=150, speed=100, wind=100, xborder=(0,100), yborder=(50,400), **kwargs):
return Particles(SnowFactory(image, max_particles, speed, wind, xborder, yborder, **kwargs))
class SnowFactory(object):
def __init__(self, image, max_particles, speed, wind, xborder, yborder, **kwargs):
# the maximum number of particles we can have on screen at once
self.max_particles = max_particles

# the particle's speed
self.speed = speed

# the wind's speed
self.wind = wind

# the horizontal/vertical range to create particles
self.xborder = xborder
self.yborder = yborder

# the maximum depth of the screen. Higher values lead to more varying particles size,
# but it also uses more memory. Default value is 10 and it should be okay for most
# games, since particles sizes are calculated as percentage of this value.
self.depth = kwargs.get("depth", 50)

# initialize the images
self.image = self.image_init(image)


def create(self, particles, st):
# if we can create a new particle...
if particles is None or len(particles) < self.max_particles:

# generate a random depth for the particle
depth = random.randint(1, self.depth)

# We expect that particles falling far from the screen will move slowly than those
# that are falling near the screen. So we change the speed of particles based on
# its depth =D
depth_speed = 1.5-depth/(self.depth+0.0)

return [ SnowParticle(self.image[depth-1], # the image used by the particle
random.uniform(-self.wind, self.wind)*depth_speed, # wind's force
self.speed*depth_speed, # the vertical speed of the particle
random.randint(self.xborder[0], self.xborder[1]), # horizontal border
random.randint(self.yborder[0], self.yborder[1]), # vertical border
) ]


def image_init(self, image):
rv = [ ]

# generate the array of images for each possible depth value.
for depth in range(self.depth):
# Resize and adjust the alpha value based on the depth of the image
p = 1.1 - depth/(self.depth+0.0)
if p > 1:
p = 1.0

rv.append( im.FactorScale( im.Alpha(image, p), p ) )

return rv


def predict(self):
"""
This is called internally by the Particles object to predict the images the particles
are using. It's expected to return a list of images to predict.
"""
return self.image

class SnowParticle(object):
"""
Represents every particle in the screen.
"""
def __init__(self, image, wind, speed, xborder, yborder):
"""
Initializes the snow particle. This is called automatically when the object is created.
"""

# The image used by this particle
self.image = image

# For safety (and since we don't have snow going from the floor to the sky o.o)
# if the vertical speed of the particle is lower than 1, we use 1.
# This prevents the particles of being stuck in the screen forever and not falling at all.
if speed <= 0:
speed = 1

# wind's speed
self.wind = wind

# particle's speed
self.speed = speed

# The last time when this particle was updated (used to calculate the unexpected delay
# between updates, aka lag)
self.oldst = None

# the horizontal/vertical positions of this particle
self.xpos = random.uniform(0-xborder, renpy.config.screen_width+xborder)
self.ypos = -yborder


def update(self, st):
"""
Called internally in every frame to update the particle.
"""

# calculate lag
if self.oldst is None:
self.oldst = st

lag = st - self.oldst
self.oldst = st

# update the position
self.xpos += lag * self.wind
self.ypos += lag * self.speed

# verify if the particle went out of the screen so we can destroy it.
if self.ypos > renpy.config.screen_height or\
(self.wind< 0 and self.xpos < 0) or (self.wind > 0 and self.xpos > renpy.config.screen_width):
## print "Dead"
return None

# returns the particle as a Tuple (xpos, ypos, time, image)
# since it expects horizontal and vertical positions to be integers, we have to convert
# it (internal positions use float for smooth movements =D)
return int(self.xpos), int(self.ypos), st, self.image

Define particle image The following is how to define the particle image - Snow (the path of the image is followed by the path of the image, and should be changed according to the place where you put the image

The following code should also be placed before label start

init:
image snowfall = Snow("images/snowflake.png")

To use it, use the following code (after label start):

show snowfall

You can get pictures from my Google Drive --> https://drive.google.com/file/d/1exgbzgHMoYhZiuIZkbhdqFL7cHh2SVHW/view?usp=sharing
You can download it (or make it yourself)

Preview:
Image

Term Of Use / License:

  • Can be used in commercial (paid) /non-commercial (free) games
  • This resource cannot be resold, redistribute or reupload
  • The sale of the resource itself is prohibited
  • For use other than making games, please contact me in advance
  • No need to contact/notify when using in the game
  • Credit is not need but alwalys welcome ( ̄︶ ̄)
  • Can be used in 18+ games
  • It is OK to use it in Doujin, derivative work and other type of games as long as it does not violate the law