Page 1 of 2

Layered Parallax Code

Posted: Tue Jan 09, 2018 5:07 pm
by Geckos
Thought I'd share the parallax code that's floating around the forums, but in one place with all the fiddly bits fixed.

This code was not written originally by me. I am just sharing what I found on the forums.
This code lets you use different layers to give a parallax effect to in-game elements with the movements of your mouse.
parallax_example_potd1.gif
Perceptions of the Dead clip

Code: Select all


init 800 python:
    class MouseParallax(renpy.Displayable):
        def __init__(self,layer_info):
            super(renpy.Displayable,self).__init__()
            self.xoffset,self.yoffset=0.0,0.0
            self.sort_layer=sorted(layer_info,reverse=True)
            cflayer=[]
            masteryet=False
            for m,n in self.sort_layer:
                if(not masteryet)and(m<41):
                    cflayer.append("master")
                    masteryet=True
                cflayer.append(n)
            if not masteryet:
                cflayer.append("master")
            cflayer.extend(["transient","screens","overlay"])
            config.layers=cflayer
            config.overlay_functions.append(self.overlay)
            return
        def render(self,width,height,st,at):
            return renpy.Render(width,height)
        def parallax(self,m):
            func = renpy.curry(trans)(disp=self, m=m)
            return Transform(function=func)
        def overlay(self):
            ui.add(self)
            for m,n in self.sort_layer:
                renpy.layer_at_list([self.parallax(m)],n)
            return
        def event(self,ev,x,y,st):
            import pygame
            if ev.type==pygame.MOUSEMOTION:
                self.xoffset,self.yoffset=((float)(x)/(config.screen_width))-0.5,((float)(y)/(config.screen_height))-0.5
            return
    MouseParallax([(40,"farback"),(20,"back"),(-20,"front"),(-40,"inyourface")])
            
    def trans(d, st, at, disp=None, m=None):
        d.xoffset, d.yoffset = int(round(m*disp.xoffset)), int(round(m*disp.yoffset))
        return 0
        
      
Note: for this line of code "if(not masteryet)and(m<41):" the number must be higher than your highest number. Such as, for this code, 41 (as it is greater than the 40 for 'farback'.)

Example of code in use.

Code: Select all

show background_image onlayer farback
show midground_image onlayer back
show sprite1 onlayer front
show sprite2 onlayer inyourface
Other things to note: When using this layered method you must hide each layer individually to display new images. You cannot just 'wipe' the scene by putting
Scene black

you have to go

Code: Select all

hide background_image 
hide midground_image 
hide sprite1 
hide sprite2 
Hope this helps others! I enjoyed this code a lot.

Re: Layered Parallax Code

Posted: Sun Jan 14, 2018 5:38 pm
by Borisu
Really interesting dude! I'll see in what this can be used

Re: Layered Parallax Code

Posted: Fri Mar 09, 2018 6:08 pm
by dirtydonnie
Can this be applied to screen elements such as choice buttons as well? If so, how?

Re: Layered Parallax Code

Posted: Mon Aug 06, 2018 3:31 pm
by Andredron
Geckos wrote:
Tue Jan 09, 2018 5:07 pm

http://renpyfordummies.blogspot.com/201 ... -post.html

Modified parallax. Now the list of layers and their parameters can be changed on the fly. Show layers (showp) and remove them (scenep) with one command. You can add one or more transform effects to the images (see the description of the showp function).

Code: Select all

# Parallax example:

# label start:
    # $ mouse_parallax.set (-20, -5, "l0"), (-40, -10, "l1"), (-60, -15, "l2"))
    # $ showp ("city0", "city1", "city2", "bg room")
    # with dissolve
    # "Move the mouse. \ NParallel parallax. Moving closer to the camera layers."
    # $ scenep ()
    # with dissolve
    # $ mouse_parallax.set (-60, -15, "l0"), (-40, -10, "l1"), (-20, -5, "l2"))
    # $ showp ("city0", "city1", "city2", "bg room")
    # with dissolve
    # "Move the mouse. \ NMirror parallax: The values ​​for the layer shift are reset, the far layers are moving harder now." As if we are looking in the mirror. "
    # $ scenep ()
    # with dissolve
    # return

init 1111 python:
    # class for parallax
    class MouseParallax (renpy.Displayable):
        def set (self, * args):
            self.xoffset, self.yoffset = 0.0, 0.0
            self.layer_info = args
            for i in self.layers ():
                if i in config.layers + ["master2"]:
                    config.layers.remove (i)
            index = config.layers.index ("master") + 1
            for xdist, ydist, layer in args:
                if not layer in config.layers:
                    config.layers.insert (index, layer)
                    index + = 1
            config.layers.insert (index, "master2")

        def __init __ (self, * args):
            super (renpy.Displayable, self) .__ init __ ()
            self.set (* args)
            config.overlay_functions.append (self.overlay)
            return

        def layers (self):
            layers = []
            for dx, dy, layer in self.layer_info:
                layers.insert (0, layer)
            return layers

        def render (self, width, height, st, at):
            return renpy.Render (width, height)

        def parallax (self, xdist, ydist):
            func = renpy.curry (trans) (xdist = xdist, ydist = ydist, disp = self)
            return Transform (function = func)

        def overlay (self):
            ui.add (self)
            for xdist, ydist, layer in self.layer_info:
                renpy.layer_at_list ([self.parallax (xdist, ydist)], layer)
            return

        def event (self, ev, x, y, st):
            import pygame
            if ev.type == pygame.MOUSEMOTION:
                self.xoffset, self.yoffset = ((float) (x) / (config.screen_width)) - 0.5, ((float) (y) / (config.screen_height)) - 0.5
            return

    def trans (d, st, at, xdist = None, ydist = None, disp = None):
        d.xoffset, d.yoffset = int (round (xdist * disp.xoffset)), int (round (ydist * disp.yoffset))
        if xdist! = 0 or ydist! = 0:
            xzoom = (config.screen_width + abs (xdist + xdist)) / float (config.screen_width)
            yzoom = (config.screen_height + abs (ydist + ydist)) / float (config.screen_height)
            if yzoom> xzoom:
                d.zoom = yzoom
            else:
                d.zoom = xzoom
            d.anchor = (.5, 1.0)
            d.align = (.5, 1.0)
        return 0

    # list for storing images with layers
    parallax_images = []

    # show multiple images, each on its parallax layer
    # possible with the effect of transform or even with several
    # the number of images should not exceed the number of layers
    # otherwise superfluous will be displayed on the master2 layer on top of the rest
    # $ showp ("city1", ("city2", truecenter), ("city3", [truecenter, woo]))
    def showp (* args):
        global parallax_images
        layers = mouse_parallax.layers ()
        for i in args:
            at = []
            image = i
            if isinstance (image, tuple):
                image, at = image
                if not isinstance (at, list):
                    at = [at]
            l = "master2"
            if len (layers)> 0:
                l = layers.pop ()
            renpy.show (image, at_list = at, layer = l)
            i = (image, l)
            if not i in parallax_images:
                parallax_images.append (i)

    # remove one image from the specified (or from any) layer
    def hidep (image, layer = None):
        global parallax_images
        if not layer:
            layer = "master2"
            for ii, ll in parallax_images:
                if ii == image:
                    layer = ll
        i = (image, layer)
        renpy.hide (image, layer = layer)
        if i in parallax_images:
            parallax_images.remove (i)

    # clear all parallax layers
    # and, if necessary, add new images
    def scenep (* args):
        global parallax_images
        for i in parallax_images:
            image, layer = i
            renpy.hide (image, layer = layer)
        parallax_images = []
        if args:
            showp (* args)

    mouse_parallax = MouseParallax ((-60, -15, "l0"), (-40, -10, "l1"), (-20, -5, "l

Re: Layered Parallax Code

Posted: Wed Aug 29, 2018 3:24 am
by KingsCard
Worked like a charm, thank you very much :)

Re: Layered Parallax Code

Posted: Sat Sep 22, 2018 9:49 am
by Invader777
Really cool piece of code.
I tried the Gecko's code and it worked smoothly. I had all the layers loading in and animating the way I wanted them to. but when it came time to hide the layers to bring up a new scene.
typing
hide background_image
did not remove the parallaxed layer in question. (A layer I'd created earlier in the script by typing
show backgroundimage onlayer farback at truecenter

I modified it back to read
show backgroundimage at truecenter
and from that point it was hidden like it was supposed to (But obviously not parallaxing like I wanted)

The Parallax works real nice and smooth like. It's exactly what I wanted. I layered it up with 5 layers of depth, put in a nice additive blend overlay for some light effects, put in a character with a blink animation... it was looking pretty sweet. I can even add new parallax layers when I need them
but it's kind of useless unless I can find a way to change a scene, or remove a layer when I need to.

any idea what I'm doing wrong?


(and as a side question - it seems to self arrange layer priorities by the number listed in Mouse Parralax.. is there any way to set manual layer priority? - typing 'behind' functions no longer seems to work")

Re: Layered Parallax Code

Posted: Sun Nov 25, 2018 8:36 am
by M-77
The first code example works fine for me (The second code is missing some parameters). I use 4 layers.
Now I want put another pic with transparent bg (a character standing there as background) over/on top the 4 layers depending on the situation in my game. And show only the 4 layers again without the character pic later. But the pic will not show up. Even with "zorder +1", or "zorder +12".
I also want to show up two character profiles, one at right and one at left. Both with transparent bg. Over the whole scene. Doing some dialog. And then hide again. The usual VN stuff.
But none of them is showing up. Need help, what did I miss here? Thank you.

Re: Layered Parallax Code

Posted: Mon Nov 26, 2018 3:05 pm
by M-77
I solved my issue with not showing up characters adding another layer ("inyoureye") to the code and display all tree character pics I needed on that layer:

Code: Select all

init 800 python:
    class MouseParallax(renpy.Displayable):
        def __init__(self,layer_info):
            super(renpy.Displayable,self).__init__()
            self.xoffset,self.yoffset=0.0,0.0
            self.sort_layer=sorted(layer_info,reverse=True)
            cflayer=[]
            masteryet=False
            for m,n in self.sort_layer:
                if(not masteryet)and(m<41):
                    cflayer.append("master")
                    masteryet=True
                cflayer.append(n)
            if not masteryet:
                cflayer.append("master")
            cflayer.extend(["transient","screens","overlay"])
            config.layers=cflayer
            config.overlay_functions.append(self.overlay)
            return
        def render(self,width,height,st,at):
            return renpy.Render(width,height)
        def parallax(self,m):
            func = renpy.curry(trans)(disp=self, m=m)
            return Transform(function=func)
        def overlay(self):
            ui.add(self)
            for m,n in self.sort_layer:
                renpy.layer_at_list([self.parallax(m)],n)
            return
        def event(self,ev,x,y,st):
            import pygame
            if ev.type==pygame.MOUSEMOTION:
                self.xoffset,self.yoffset=((float)(x)/(config.screen_width))-0.5,((float)(y)/(config.screen_height))-0.5
            return
    MouseParallax([(10,"farback"),(05,"back"),(-20,"front"),(-0,"inyourface"),(-1,"inyoureye")])
            
    def trans(d, st, at, disp=None, m=None):
        d.xoffset, d.yoffset = int(round(m*disp.xoffset)), int(round(m*disp.yoffset))
        return 0
Also adding "at left" and additional "with dissolve" commands working.
Hey, "Invader777"! How your code is looking? Can you post it here too please?

Re: Layered Parallax Code

Posted: Tue Aug 20, 2019 6:22 pm
by BeanNoodle
I tried using the code and got an error, it's probably not best for a beginner to try something like this but I really want to implement this in my game.

Re: Layered Parallax Code

Posted: Wed Aug 21, 2019 11:07 am
by ArizaLuca
Which code? The first or the later ones? As long as you don't make any edits and paste it in directly I think it should work. (I've tested it and generally it does work; it just also makes transitions more annoying.)

Re: Layered Parallax Code

Posted: Thu Aug 22, 2019 12:43 pm
by dino999z
Hi. Is it possible to apply ATL on those layers?
Like zoom into a picture while keeping it parallax?

Re: Layered Parallax Code

Posted: Fri Aug 23, 2019 8:28 pm
by dino999z
ArizaLuca wrote:
Wed Aug 21, 2019 11:07 am
Which code? The first or the later ones? As long as you don't make any edits and paste it in directly I think it should work. (I've tested it and generally it does work; it just also makes transitions more annoying.)
Hi. Were you able to apply ATL on those layers? I'm having problems with that

Re: Layered Parallax Code

Posted: Sun Aug 25, 2019 7:54 am
by M-77
Hello "BeanNoodle" try the code from here (download the project and look how it work. Get code from it that you need. And try, try...): http://renpyfordummies.blogspot.com/201 ... -post.html I am also still new to Renpy, but I made it easyly work after some tryout.
See my code example above to compare what could be missing.
Hello "dino999z", I not sure if ATL works with it, I could made it show game characters add as 5th layer (-1, "inyoureye"), show up and hide with "moveouleft" etc. so it could be possible to combine it with zoom too.
Hello "Invader777"! How your code is looking? Can you show us please how do more with this?

Re: Layered Parallax Code

Posted: Sun Aug 25, 2019 10:17 am
by ArizaLuca
M-77 wrote:
Sun Aug 25, 2019 7:54 am
Hello "BeanNoodle" try the code from here (download the project and look how it work. Get code from it that you need. And try, try...): http://renpyfordummies.blogspot.com/201 ... -post.html I am also still new to Renpy, but I made it easyly work after some tryout.
See my code example above to compare what could be missing.
Hello "dino999z", I not sure if ATL works with it, I could made it show game characters add as 5th layer (-1, "inyoureye"), show up and hide with "moveouleft" etc. so it could be possible to combine it with zoom too.
Hello "Invader777"! How your code is looking? Can you show us please how do more with this?
I also can't use ATL on those layers, unfortunately-- just Dissolves and Fades. No moving. I also kinda wanna fix that issue but it's alright xD

Re: Layered Parallax Code

Posted: Sun Aug 25, 2019 4:51 pm
by M-77
I can do this:
show Elie_stand_ssuit001 onlayer inyoureye at left with dissolve
(inyoureye is my 5th layer on top of the other 4) This displays one of my characters PNG with transparent bg.
And I can hide them with this, let them move out to the left in this case:
hide Elie_stand_ssuit001 onlayer inyoureye at left with dissolve
So more ATL should be possible? Like this if want zoom?:
hide Elie_stand_ssuit001 onlayer inyoureye
show Elie_stand_ssuit001 onlayer inyoureye at left with zoom 3.0
Or like this, I forgot how ATL is done correct, as I am now more busy with game art design then coding:
show Elie_stand_ssuit001 onlayer inyoureye at left:
with zoom 3.0

Not sure if the paralax code accept this.