[SOLVED] Snow effect not working?

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
User avatar
Rinzamakani
Regular
Posts: 74
Joined: Wed Aug 16, 2017 3:23 pm
Completed: Love's Apathy (Ciro route), A Frigid Space, Telechronic Static
Projects: Love's Apathy (Full)
itch: rinzamakani.itch.io
Contact:

[SOLVED] Snow effect not working?

#1 Post by Rinzamakani »

Hello. So, I've made a new project in one of the latest versions of Renpy and the snow code I've been trying to use doesn't seem to be working.
This is the code I've been using:
https://www.renpy.org/wiki/renpy/doc/co ... now_effect

And this is the error it gives me:

Code: Select all

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/script.rpy", line 13, in script
    image snow = Snow("snowflake.png")
  File "game/script.rpy", line 13, in <module>
    image snow = Snow("snowflake.png")
NameError: name 'snow' is not defined

-- Full Traceback ------------------------------------------------------------

Full traceback:
  File "game/script.rpy", line 13, in script
    image snow = Snow("snowflake.png")
  File "C:\Users\xion1\Documents\renpy-6.99.13-sdk\renpy\ast.py", line 980, in execute
    img = renpy.python.py_eval_bytecode(self.code.bytecode)
  File "C:\Users\xion1\Documents\renpy-6.99.13-sdk\renpy\python.py", line 1937, in py_eval_bytecode
    return eval(bytecode, globals, locals)
  File "game/script.rpy", line 13, in <module>
    image snow = Snow("snowflake.png")
NameError: name 'snow' is not defined

Windows-8-6.2.9200
Ren'Py 7.1.3.1092
A Frigid Space 1.0
Fri Mar 15 16:33:29 2019
I've made a different screen for this and placed the first part of the code in there.
The

Code: Select all

init:
   image snow = Snow("snowflake.png")
is above the label start.

Is there a way to get this to work?
Last edited by Rinzamakani on Sat Mar 16, 2019 12:51 pm, edited 1 time in total.

User avatar
Imperf3kt
Lemma-Class Veteran
Posts: 3791
Joined: Mon Dec 14, 2015 5:05 am
itch: Imperf3kt
Location: Your monitor
Contact:

Re: Snow effect not working?

#2 Post by Imperf3kt »

You need to define the image before renpy tries to use it.
Since it is needed for the main menu, the image will be asked for before init runs because the screen will be created first during init -1

Try init -2

Code: Select all

init -2:
   image snow = Snow("snowflake.png")
Warning: May contain trace amounts of gratuitous plot.
pro·gram·mer (noun) An organism capable of converting caffeine into code.

Current project: GGD Mentor

Twitter

User avatar
Rinzamakani
Regular
Posts: 74
Joined: Wed Aug 16, 2017 3:23 pm
Completed: Love's Apathy (Ciro route), A Frigid Space, Telechronic Static
Projects: Love's Apathy (Full)
itch: rinzamakani.itch.io
Contact:

Re: Snow effect not working?

#3 Post by Rinzamakani »

Imperf3kt wrote: Fri Mar 15, 2019 6:14 pm You need to define the image before renpy tries to use it.
Since it is needed for the main menu, the image will be asked for before init runs because the screen will be created first during init -1

Try init -2

Code: Select all

init -2:
   image snow = Snow("snowflake.png")
Thank you. But this still didn't work. Am I placing this in the correct place? Above the label start. And I have the snowflake image in the "images" folder.

User avatar
Imperf3kt
Lemma-Class Veteran
Posts: 3791
Joined: Mon Dec 14, 2015 5:05 am
itch: Imperf3kt
Location: Your monitor
Contact:

Re: Snow effect not working?

#4 Post by Imperf3kt »

Rinzamakani wrote: Fri Mar 15, 2019 6:27 pm Am I placing this in the correct place? Above the label start. And I have the snowflake image in the "images" folder.
as long as it is not inside a label, you can place it anywhere.
For example, both of the following examples would work, but the one with it before label start, is generally the recommended one for two reasons:
1) its generally neater and better coding practice,
2) its easier to explain to those unfamiliar with how it works, and makes it less complicated

Code: Select all

init:
    some stuff
    
label start:
    "some text"
    jump french_toast

label french toast:
    "more text"
    return

Code: Select all

label start:
    "some text"
    jump french_toast
    
init:
    some stuff
    
label french toast:
    "more text"
    return

If what I suggested didn't work, then the code may be outdated too much.
Perhaps one of the others here who knows more about Python than I do, could help. I am not able to help much more than this as its beyond my understanding.
Warning: May contain trace amounts of gratuitous plot.
pro·gram·mer (noun) An organism capable of converting caffeine into code.

Current project: GGD Mentor

Twitter

User avatar
Rinzamakani
Regular
Posts: 74
Joined: Wed Aug 16, 2017 3:23 pm
Completed: Love's Apathy (Ciro route), A Frigid Space, Telechronic Static
Projects: Love's Apathy (Full)
itch: rinzamakani.itch.io
Contact:

Re: Snow effect not working?

#5 Post by Rinzamakani »

Imperf3kt wrote: Fri Mar 15, 2019 8:07 pm
Rinzamakani wrote: Fri Mar 15, 2019 6:27 pm Am I placing this in the correct place? Above the label start. And I have the snowflake image in the "images" folder.
as long as it is not inside a label, you can place it anywhere.
For example, both of the following examples would work, but the one with it before label start, is generally the recommended one for two reasons:
1) its generally neater and better coding practice,
2) its easier to explain to those unfamiliar with how it works, and makes it less complicated

Code: Select all

init:
    some stuff
    
label start:
    "some text"
    jump french_toast

label french toast:
    "more text"
    return

Code: Select all

label start:
    "some text"
    jump french_toast
    
init:
    some stuff
    
label french toast:
    "more text"
    return

If what I suggested didn't work, then the code may be outdated too much.
Perhaps one of the others here who knows more about Python than I do, could help. I am not able to help much more than this as its beyond my understanding.
Then I think I placed it correctly. Here's the code to the script of the game:

Code: Select all

define e = Character("Eileen")
########################Images#############################
image winterbench = "Winterbench.png"

# The game starts here.
########################Snow###############################
init -2:
   image snow = Snow("snowflake.png")

label start:
    play music "The Fugue.mp3"
    scene black
    show text "{i}It's cold.{/i}" with dissolve
    $ renpy.pause()
    show text "{i}Why is it so cold?{/i}" with dissolve
    $ renpy.pause()
    scene winterbench with fade
    show snow
    "I sat up and observed my surroundings."
    return
So, I'm guessing it is outdated. Thanks for trying to help. It still gives the same error as above.

User avatar
IrinaLazareva
Veteran
Posts: 399
Joined: Wed Jun 08, 2016 1:49 pm
Projects: Legacy
Organization: SunShI
Location: St.Petersburg, Russia
Contact:

Re: Snow effect not working?

#6 Post by IrinaLazareva »

It's working properly. As long as Renpy uses the python 2.7 this code can't get out of date.
Are you sure you've placed all 187 lines of the code?

User avatar
Imperf3kt
Lemma-Class Veteran
Posts: 3791
Joined: Mon Dec 14, 2015 5:05 am
itch: Imperf3kt
Location: Your monitor
Contact:

Re: Snow effect not working?

#7 Post by Imperf3kt »

Oh, I mistakenly thought you were using it in the main menu. As such, my prior posts about init can be ignored.

Having said that, I decided to take a look myself and it works just fine for me.
https://i.imgur.com/ukpyYVt.gifv

EDIT:

I deleted the code myself and removed "show snow", but forgot to remove the init where I defined snow and got the same error, so I think maybe you didn't copy the code to your project? Its not included with Ren'Py by default so you need to add it to a file somewhere.

-----------------------------------------------------------------------------------------------------------------------

Original post


Maybe try copying it again just to be sure:

Code: Select all

init python:
    
    #################################################################
    # Here we use random module for some random stuffs (since we don't
    # want Ren'Py saving the random number's we'll generate.
    import random
    
    # initialize random numbers
    random.seed()
    
    #################################################################
    # Snow particles
    # ----------------
    def Snow(image, max_particles=50, speed=150, wind=100, xborder=(0,100), yborder=(50,400), **kwargs):
        """
        This creates the snow effect. You should use this function instead of instancing
        the SnowFactory directly (we'll, doesn't matter actually, but it saves typing if you're
        using the default values =D)
        
        @parm {image} image:
            The image used as the snowflakes. This should always be a image file or an im object,
            since we'll apply im transformations in it.
        
        @parm {int} max_particles:
            The maximum number of particles at once in the screen.
            
        @parm {float} speed:
            The base vertical speed of the particles. The higher the value, the faster particles will fall.
            Values below 1 will be changed to 1
            
        @parm {float} wind:
            The max wind force that'll be applyed to the particles.
            
        @parm {Tuple ({int} min, {int} max)} xborder:
            The horizontal border range. A random value between those two will be applyed when creating particles.
            
        @parm {Tuple ({int} min, {int} max)} yborder:
            The vertical border range. A random value between those two will be applyed when creating particles.
            The higher the values, the fartest from the screen they will be created.
        """
        return Particles(SnowFactory(image, max_particles, speed, wind, xborder, yborder, **kwargs))
    
    # ---------------------------------------------------------------
    class SnowFactory(object):
        """
        The factory that creates the particles we use in the snow effect.
        """
        def __init__(self, image, max_particles, speed, wind, xborder, yborder, **kwargs):
            """
            Initialize the factory. Parameters are the same as the Snow function.
            """            
            # 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", 10)
            
            # initialize the images
            self.image = self.image_init(image)
            

        def create(self, particles, st):
            """
            This is internally called every frame by the Particles object to create new particles.
            We'll just create new particles if the number of particles on the screen is
            lower than the max number of particles we can have.
            """
            # 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):
            """
            This is called internally to initialize the images.
            will create a list of images with different sizes, so we
            can predict them all and use the cached versions to make it more memory efficient.            
            """
            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
The best place to paste it would probably be in its own file called snoweffect.rpy or something
Warning: May contain trace amounts of gratuitous plot.
pro·gram·mer (noun) An organism capable of converting caffeine into code.

Current project: GGD Mentor

Twitter

User avatar
Rinzamakani
Regular
Posts: 74
Joined: Wed Aug 16, 2017 3:23 pm
Completed: Love's Apathy (Ciro route), A Frigid Space, Telechronic Static
Projects: Love's Apathy (Full)
itch: rinzamakani.itch.io
Contact:

Re: Snow effect not working?

#8 Post by Rinzamakani »

Imperf3kt wrote: Sat Mar 16, 2019 4:37 am Oh, I mistakenly thought you were using it in the main menu. As such, my prior posts about init can be ignored.

Having said that, I decided to take a look myself and it works just fine for me.
https://i.imgur.com/ukpyYVt.gifv

EDIT:

I deleted the code myself and removed "show snow", but forgot to remove the init where I defined snow and got the same error, so I think maybe you didn't copy the code to your project? Its not included with Ren'Py by default so you need to add it to a file somewhere.

-----------------------------------------------------------------------------------------------------------------------

Original post


Maybe try copying it again just to be sure:

Code: Select all

init python:
    
    #################################################################
    # Here we use random module for some random stuffs (since we don't
    # want Ren'Py saving the random number's we'll generate.
    import random
    
    # initialize random numbers
    random.seed()
    
    #################################################################
    # Snow particles
    # ----------------
    def Snow(image, max_particles=50, speed=150, wind=100, xborder=(0,100), yborder=(50,400), **kwargs):
        """
        This creates the snow effect. You should use this function instead of instancing
        the SnowFactory directly (we'll, doesn't matter actually, but it saves typing if you're
        using the default values =D)
        
        @parm {image} image:
            The image used as the snowflakes. This should always be a image file or an im object,
            since we'll apply im transformations in it.
        
        @parm {int} max_particles:
            The maximum number of particles at once in the screen.
            
        @parm {float} speed:
            The base vertical speed of the particles. The higher the value, the faster particles will fall.
            Values below 1 will be changed to 1
            
        @parm {float} wind:
            The max wind force that'll be applyed to the particles.
            
        @parm {Tuple ({int} min, {int} max)} xborder:
            The horizontal border range. A random value between those two will be applyed when creating particles.
            
        @parm {Tuple ({int} min, {int} max)} yborder:
            The vertical border range. A random value between those two will be applyed when creating particles.
            The higher the values, the fartest from the screen they will be created.
        """
        return Particles(SnowFactory(image, max_particles, speed, wind, xborder, yborder, **kwargs))
    
    # ---------------------------------------------------------------
    class SnowFactory(object):
        """
        The factory that creates the particles we use in the snow effect.
        """
        def __init__(self, image, max_particles, speed, wind, xborder, yborder, **kwargs):
            """
            Initialize the factory. Parameters are the same as the Snow function.
            """            
            # 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", 10)
            
            # initialize the images
            self.image = self.image_init(image)
            

        def create(self, particles, st):
            """
            This is internally called every frame by the Particles object to create new particles.
            We'll just create new particles if the number of particles on the screen is
            lower than the max number of particles we can have.
            """
            # 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):
            """
            This is called internally to initialize the images.
            will create a list of images with different sizes, so we
            can predict them all and use the cached versions to make it more memory efficient.            
            """
            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
The best place to paste it would probably be in its own file called snoweffect.rpy or something
Turns out it was the init that was causing the problem. It works now! Thank you! :)

Post Reply

Who is online

Users browsing this forum: AWizardWithWords, Google [Bot], henne