How to make a more realistic snow effect?

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
Lightworker
Regular
Posts: 104
Joined: Sun Dec 13, 2015 2:06 pm
Projects: Detroit.exe
Discord: Happiness+#1168
Contact:

How to make a more realistic snow effect?

#1 Post by Lightworker »

I took the code from the old documentation http://www.renpy.org/wiki/renpy/doc/coo ... now_effect however, when I put it in my script I got this error. What does this mean?

Code: Select all

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/script.rpy", line 285, in script
    p "People say that there is no such place as Heaven. "
  File "renpy/common/00nvl_mode.rpy", line 285, in do_display
    **display_args)
  File "game/script.rpy", line 156, in create
    self.speed*depth_speed,  # the vertical speed of the particle
TypeError: can't multiply sequence by non-int of type 'float'

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

Full traceback:
  File "game/script.rpy", line 285, in script
    p "People say that there is no such place as Heaven. "
  File "H:\renpy-6.99.8-sdk\renpy\ast.py", line 603, in execute
    renpy.exports.say(who, what, interact=self.interact)
  File "H:\renpy-6.99.8-sdk\renpy\exports.py", line 1121, in say
    who(what, interact=interact)
  File "H:\renpy-6.99.8-sdk\renpy\character.py", line 826, in __call__
    self.do_display(who, what, cb_args=self.cb_args, **display_args)
  File "renpy/common/00nvl_mode.rpy", line 285, in do_display
    **display_args)
  File "H:\renpy-6.99.8-sdk\renpy\character.py", line 491, in display_say
    rv = renpy.ui.interact(mouse='say', type=type, roll_forward=roll_forward)
  File "H:\renpy-6.99.8-sdk\renpy\ui.py", line 277, in interact
    rv = renpy.game.interface.interact(roll_forward=roll_forward, **kwargs)
  File "H:\renpy-6.99.8-sdk\renpy\display\core.py", line 2424, in interact
    repeat, rv = self.interact_core(preloads=preloads, **kwargs)
  File "H:\renpy-6.99.8-sdk\renpy\display\core.py", line 2765, in interact_core
    self.draw_screen(root_widget, fullscreen_video, (not fullscreen_video) or video_frame_drawn)
  File "H:\renpy-6.99.8-sdk\renpy\display\core.py", line 1849, in draw_screen
    renpy.config.screen_height,
  File "renpy/display/render.pyx", line 394, in renpy.display.render.render_screen (gen\renpy.display.render.c:6190)
    rv = render(root, width, height, 0, 0)
  File "renpy/display/render.pyx", line 185, in renpy.display.render.render (gen\renpy.display.render.c:2721)
    rv = d.render(widtho, heighto, st, at)
  File "H:\renpy-6.99.8-sdk\renpy\display\layout.py", line 650, in render
    surf = render(child, width, height, cst, cat)
  File "renpy/display/render.pyx", line 103, in renpy.display.render.render (gen\renpy.display.render.c:3104)
    cpdef render(d, object widtho, object heighto, double st, double at):
  File "renpy/display/render.pyx", line 185, in renpy.display.render.render (gen\renpy.display.render.c:2721)
    rv = d.render(widtho, heighto, st, at)
  File "H:\renpy-6.99.8-sdk\renpy\display\layout.py", line 650, in render
    surf = render(child, width, height, cst, cat)
  File "renpy/display/render.pyx", line 103, in renpy.display.render.render (gen\renpy.display.render.c:3104)
    cpdef render(d, object widtho, object heighto, double st, double at):
  File "renpy/display/render.pyx", line 185, in renpy.display.render.render (gen\renpy.display.render.c:2721)
    rv = d.render(widtho, heighto, st, at)
  File "H:\renpy-6.99.8-sdk\renpy\display\layout.py", line 650, in render
    surf = render(child, width, height, cst, cat)
  File "renpy/display/render.pyx", line 103, in renpy.display.render.render (gen\renpy.display.render.c:3104)
    cpdef render(d, object widtho, object heighto, double st, double at):
  File "renpy/display/render.pyx", line 185, in renpy.display.render.render (gen\renpy.display.render.c:2721)
    rv = d.render(widtho, heighto, st, at)
  File "renpy/display/accelerator.pyx", line 104, in renpy.display.accelerator.transform_render (gen\renpy.display.accelerator.c:1905)
    cr = render(child, widtho, heighto, st - self.child_st_base, at)
  File "renpy/display/render.pyx", line 185, in renpy.display.render.render (gen\renpy.display.render.c:2721)
    rv = d.render(widtho, heighto, st, at)
  File "H:\renpy-6.99.8-sdk\renpy\display\image.py", line 261, in render
    return wrap_render(self.target, width, height, st, at)
  File "H:\renpy-6.99.8-sdk\renpy\display\image.py", line 124, in wrap_render
    rend = render(child, w, h, st, at)
  File "renpy/display/render.pyx", line 103, in renpy.display.render.render (gen\renpy.display.render.c:3104)
    cpdef render(d, object widtho, object heighto, double st, double at):
  File "renpy/display/render.pyx", line 185, in renpy.display.render.render (gen\renpy.display.render.c:2721)
    rv = d.render(widtho, heighto, st, at)
  File "H:\renpy-6.99.8-sdk\renpy\display\particle.py", line 412, in render
    return renpy.display.render.render(self.sm, w, h, st, at)
  File "renpy/display/render.pyx", line 103, in renpy.display.render.render (gen\renpy.display.render.c:3104)
    cpdef render(d, object widtho, object heighto, double st, double at):
  File "renpy/display/render.pyx", line 185, in renpy.display.render.render (gen\renpy.display.render.c:2721)
    rv = d.render(widtho, heighto, st, at)
  File "H:\renpy-6.99.8-sdk\renpy\display\particle.py", line 243, in render
    redraw = self.update_function(st)
  File "H:\renpy-6.99.8-sdk\renpy\display\particle.py", line 365, in update_callback
    add_parts = self.factory.create(particles, st)
  File "game/script.rpy", line 156, in create
    self.speed*depth_speed,  # the vertical speed of the particle
TypeError: can't multiply sequence by non-int of type 'float'

Windows-7-6.1.7601-SP1
Ren'Py 6.99.8.949
The Legend 0.0

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: How to make a more realistic snow effect?

#2 Post by xela »

This means that you're multiplying a sequence object with a float. That is old code, I posted two modern variants in your other thread, they should both just work and you can tweak either one to work in a way you consider realistic.

==>
And this variant just works as well by the way, without any errors...
Like what we're doing? Support us at:
Image

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: How to make a more realistic snow effect?

#3 Post by xela »

Try this with the ATL/UDD variant:

Code: Select all

# Image definitions for snow particles:
image snow_small = Transform("snow.png", zoom=0.5)
image snow_normal = "snow.png"
image snow_large = Transform("snow.png", zoom=1.5)
image snow_very_large = Transform("snow.png", zoom=6.0, alpha=0.7, additive=0.7)

# Definition for Snowing UDD:
image snowing = Fixed(
    Snowing("snow_small", interval=(0.1, 0.15), speed=(5.5, 7.5), slow_start=(7, (0.2, 0.3))),
    Snowing("snow_normal", interval=(0.15, 0.25), speed=(3.5, 4.5), slow_start=(7, (0.4, 0.5))),
    Snowing("snow_large", interval=(0.25, 0.35), speed=(2.5, 3.5), slow_start=(5, (0.5, 0.6))),
    Snowing("snow_very_large", interval=(2, 5), speed=(0.4, 0.8), slow_start=(20, (4, 6))))
I kept the wind effect to the east, I don't like when it's falling in random directions but you can change that by simply adding the start pos/end pos properties. This looks one looks really decent to me but you can keep tweaking it until you get it just right :)

(you'll need a snow image for snowflakes, I switched from Solids to see what it looks like)
Like what we're doing? Support us at:
Image

Lightworker
Regular
Posts: 104
Joined: Sun Dec 13, 2015 2:06 pm
Projects: Detroit.exe
Discord: Happiness+#1168
Contact:

Re: How to make a more realistic snow effect?

#4 Post by Lightworker »

Wow, thanks a lot. Oh yeah, how do make this effect show over my nvl textbox? Right now, it's behind the NVL window and I want the snow to fall in front of the text for narrative purposes. How do I do that?
Seriously though, thanks, sometimes I feel real silly when coding stuff like this.

Lightworker
Regular
Posts: 104
Joined: Sun Dec 13, 2015 2:06 pm
Projects: Detroit.exe
Discord: Happiness+#1168
Contact:

Re: How to make a more realistic snow effect?

#5 Post by Lightworker »

My snowflake sprites are huge :shock: , how do I make them smaller like 5-10 pixels in diameter? How do I make them rotate like in real life? Then it'll be perfect :mrgreen:

User avatar
SinaAzad
Veteran
Posts: 204
Joined: Mon May 27, 2013 11:27 pm
IRC Nick: SinaAzad
Deviantart: sinaazad
Skype: sina_m_azad
Soundcloud: Sina_Azad
Location: Firenze, Italy
Contact:

Re: How to make a more realistic snow effect?

#6 Post by SinaAzad »

Lightworker wrote:My snowflake sprites are huge :shock: , how do I make them smaller like 5-10 pixels in diameter? How do I make them rotate like in real life? Then it'll be perfect :mrgreen:

you use photoshop or gimp or any other image editors to do that , snowblossom code sucks your systems resources a lot.
I am very proud to be a part of this generous, nice and friendly community!
but please, don't go around telling people that their work is somehow off! thats not how critique works!
Mainly a C# Programmer

My drawings:

Image

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: How to make a more realistic snow effect?

#7 Post by xela »

You'd want to resize the sprite itself using any image editing tool so the normal snowflake is of the size you desire. You can change the "zoom" of a Transform as well but I'd do it to the image first and adjust Transforms later if required.

NVL is shown on a screen, you'll have to put it on a layer higher than screen layer or show it on a screen with higher zorder than the NVL screen.

For rotation, adjust the ATL bit (parallel rotation and movement).
Like what we're doing? Support us at:
Image

Lightworker
Regular
Posts: 104
Joined: Sun Dec 13, 2015 2:06 pm
Projects: Detroit.exe
Discord: Happiness+#1168
Contact:

Re: How to make a more realistic snow effect?

#8 Post by Lightworker »

NVL is shown on a screen, you'll have to put it on a layer higher than screen layer or show it on a screen with higher zorder than the NVL screen.


How do I do that?
For rotation, adjust the ATL bit (parallel rotation and movement).
So I would use something like this

Code: Select all

image snowing = Fixed(
    Snowing("snow_small", interval=(0.1, 0.15), speed=(5.5, 7.5), rotate=45, slow_start=(7, (0.2, 0.3))),

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: How to make a more realistic snow effect?

#9 Post by xela »

Lightworker wrote:
NVL is shown on a screen, you'll have to put it on a layer higher than screen layer or show it on a screen with higher zorder than the NVL screen.


How do I do that?
Look in the docs/search the forum. This is very basic and is well documented/chewed in the threads.
Lightworker wrote:
For rotation, adjust the ATL bit (parallel rotation and movement).
So I would use something like this

Code: Select all

image snowing = Fixed(
    Snowing("snow_small", interval=(0.1, 0.15), speed=(5.5, 7.5), rotate=45, slow_start=(7, (0.2, 0.3))),
No... the ATL bit (search Documentation for ATL and more specifically parallel and rotate), there are also dozen examples on the forum and in the tutorial video.
Like what we're doing? Support us at:
Image

Lightworker
Regular
Posts: 104
Joined: Sun Dec 13, 2015 2:06 pm
Projects: Detroit.exe
Discord: Happiness+#1168
Contact:

Re: How to make a more realistic snow effect?

#10 Post by Lightworker »

What tutorial video?
I've read the documentation and searched the forum on rotating snow, but I do not get it. Like how do you rotate all three of the snow sprites in midst of all this

Code: Select all

image snow_small = Transform("snowflake1.png")
image snow_normal = "snowflake2.png"
image snow_large = Transform("snowflake3.png")
# Definition for Snowing UDD:
image snowing = Fixed(
    Snowing("snow_small", interval=(0.1, 0.15), speed=(5.5, 7.5), slow_start=(7, (0.2, 0.3))),
    Snowing("snow_normal", interval=(0.15, 0.25), speed=(3.5, 4.5), slow_start=(7, (0.4, 0.5))),
    Snowing("snow_large", interval=(0.25, 0.35), speed=(2.5, 3.5), slow_start=(5, (0.5, 0.6))))
# This bit is required for the Snowing effect:
transform particle(d, delay, startpos, endpos, speed):
    subpixel True
    pause delay
    d
    pos startpos
    linear speed pos endpos

init python:
    class Snowing(renpy.Displayable, NoRollback):
        def __init__(self, d, interval=(0.2, 0.3), start_pos=((-200, config.screen_width), 0), end_pos=({"offset": (100, 200)}, config.screen_height), speed=4.0, slow_start=False, transform=particle, **kwargs):
            """Creates a 'stream' of displayable...
           
            @params:
            -d: Anything that can shown in Ren'Py.
            -interval: Time to wait before adding a new particle. Expects a tuple with two floats.
            -start_pos: x, y starting positions. This expects a tuple of two elements containing either a tuple or an int each.
            -end_pos: x, y end positions. Same rule as above but in addition a dict can be used, in such a case:
                *empty dict will result in straight movement
                *a dict containing an "offset" key will offset the ending position by the value. Expects an int or a tuple of two ints. Default is (100, 200) and attempts to simulate a slight wind to the right (east).
            -speed: A time before particle eaches the end_pos. Expects float or a tuple of floats.
            -slow_start: If not the default False, this will expect a tuple of (time, (new_interval_min, new_interval_max)):
                *This will override the normal interval when the Displayable is first shown for the "time" seconds with the new_interval.
            -transform: ATL function to use for the particles.
               
            The idea behind the design is to enable large amounts of the same displayable guided by instructions from a specified ATL function to
            reach end_pos from start_pos in speed amount of seconds (randomized if needs be). For any rotation, "fluff" or any additional effects different ATL funcs with parallel can be used to achieve the desired effect.
            """
            super(Snowing, self).__init__(**kwargs)
            self.d = renpy.easy.displayable(d)
            self.interval = interval
            self.start_pos = start_pos
            self.end_pos = end_pos
            self.speed = speed
            self.slow_start = slow_start
            self.transform = transform
           
            self.next = 0
            self.shown = {}
       
        def render(self, width, height, st, at):
               
            rp = store.renpy
               
            if not st:
                self.next = 0
                self.shown = {}
               
            render = rp.Render(width, height)
           
            if self.next <= st:
                speed = rp.random.uniform(self.speed[0], self.speed[1])  if isinstance(self.speed, (list, tuple)) else self.speed
                   
                posx = self.start_pos[0]
                posx = rp.random.randint(posx[0], posx[1]) if isinstance(posx, (list, tuple)) else posx
               
                posy = self.start_pos[1]
                posy = rp.random.randint(posy[0], posy[1]) if isinstance(posy, (list, tuple)) else posy
               
                endposx = self.end_pos[0]
                if isinstance(endposx, dict):
                    offset = endposx.get("offset", 0)
                    endposx = posx + rp.random.randint(offset[0], offset[1]) if isinstance(offset, (list, tuple)) else offset
                else:
                    endposx = rp.random.randint(endposx[0], endposx[1]) if isinstance(endposx, (list, tuple)) else endposx
               
                endposy = self.end_pos[1]
                if isinstance(endposy, dict):
                    offset = endposy.get("offset", 0)
                    endposy = posy + randint.randint(offset[0], offset[1]) if isinstance(offset, (list, tuple)) else offset
                else:
                    endposy = rp.random.randint(endposy[0], endposy[1]) if isinstance(endposy, (list, tuple)) else endposy
               
                self.shown[st + speed] = self.transform(self.d, st, (posx, posy), (endposx, endposy), speed)
                if self.slow_start and st < self.slow_start[0]:
                    interval = self.slow_start[1]
                    self.next = st + rp.random.uniform(interval[0], interval[1])
                else:
                    self.next = st + rp.random.uniform(self.interval[0], self.interval[1])
           
            for d in self.shown.keys():
                if d < st:
                    del(self.shown[d])
                else:
                    d = self.shown[d]
                    render.blit(d.render(width, height, st, at), (d.xpos, d.ypos))
                   
            rp.redraw(self, 0)
           
            return render
           
        def visit(self):
            return [self.d]
How do I rotate each sprite in a parallel block? What would that code look like? Would it look like this?

Code: Select all

image snow:
        "snowflake1.png"
        rotate 360
        repeat
What about yanchor and xanchor? :?

Post Reply

Who is online

Users browsing this forum: piinkpuddiin