Layered Parallax Code

A place for Ren'Py tutorials and reusable Ren'Py code.
Forum rules
Do not post questions here!

This forum is for example code you want to show other people. Ren'Py questions should be asked in the Ren'Py Questions and Announcements forum.
Message
Author
User avatar
Geckos
Veteran
Posts: 471
Joined: Fri Aug 17, 2012 8:33 am
Completed: Brilliant Shadows, Perceptions of the Dead, The Phantom Icecream Truck
Projects: Embers of Magic, Pale Spectrum, Perceptions of the Dead
Organization: Ithaqua Labs
Tumblr: geckosart
Deviantart: sitaart
Contact:

Layered Parallax Code

#1 Post 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.
Perceptions of the Dead clip
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.
Image ImageImage

User avatar
Borisu
Newbie
Posts: 3
Joined: Fri Apr 29, 2016 2:26 am
Contact:

Re: Layered Parallax Code

#2 Post by Borisu »

Really interesting dude! I'll see in what this can be used

dirtydonnie
Newbie
Posts: 5
Joined: Mon Jan 01, 2018 5:44 pm
Soundcloud: dirtydonnie
Contact:

Re: Layered Parallax Code

#3 Post by dirtydonnie »

Can this be applied to screen elements such as choice buttons as well? If so, how?

User avatar
Andredron
Miko-Class Veteran
Posts: 700
Joined: Thu Dec 28, 2017 2:37 pm
Location: Russia
Contact:

Re: Layered Parallax Code

#4 Post 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

KingsCard
Newbie
Posts: 14
Joined: Sat Feb 17, 2018 8:58 am
Contact:

Re: Layered Parallax Code

#5 Post by KingsCard »

Worked like a charm, thank you very much :)

Invader777
Newbie
Posts: 1
Joined: Sat Sep 22, 2018 9:29 am
Contact:

Re: Layered Parallax Code

#6 Post 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")

M-77
Regular
Posts: 56
Joined: Tue Sep 04, 2018 7:58 am
Contact:

Re: Layered Parallax Code

#7 Post 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.

M-77
Regular
Posts: 56
Joined: Tue Sep 04, 2018 7:58 am
Contact:

Re: Layered Parallax Code

#8 Post 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?

BeanNoodle
Newbie
Posts: 1
Joined: Thu Jul 18, 2019 7:05 pm
itch: https://beannoodle.i
Contact:

Re: Layered Parallax Code

#9 Post 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.

ArizaLuca
Veteran
Posts: 241
Joined: Tue Feb 20, 2018 12:59 pm
Completed: Through the Screen, Riddle Me This, Trust Fall, Phobias, Another Adventure
Projects: The Souls in the Seams, Fata Morgana, Minecraft: Story Mode - Behind the Scenes
Organization: Astral Autumn Games
Tumblr: astralautumngames
Deviantart: ArizaLuca
itch: astralautumngames
Contact:

Re: Layered Parallax Code

#10 Post 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.)

dino999z
Newbie
Posts: 11
Joined: Wed May 15, 2019 12:18 pm
Contact:

Re: Layered Parallax Code

#11 Post by dino999z »

Hi. Is it possible to apply ATL on those layers?
Like zoom into a picture while keeping it parallax?

dino999z
Newbie
Posts: 11
Joined: Wed May 15, 2019 12:18 pm
Contact:

Re: Layered Parallax Code

#12 Post 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

M-77
Regular
Posts: 56
Joined: Tue Sep 04, 2018 7:58 am
Contact:

Re: Layered Parallax Code

#13 Post 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?

ArizaLuca
Veteran
Posts: 241
Joined: Tue Feb 20, 2018 12:59 pm
Completed: Through the Screen, Riddle Me This, Trust Fall, Phobias, Another Adventure
Projects: The Souls in the Seams, Fata Morgana, Minecraft: Story Mode - Behind the Scenes
Organization: Astral Autumn Games
Tumblr: astralautumngames
Deviantart: ArizaLuca
itch: astralautumngames
Contact:

Re: Layered Parallax Code

#14 Post 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

M-77
Regular
Posts: 56
Joined: Tue Sep 04, 2018 7:58 am
Contact:

Re: Layered Parallax Code

#15 Post 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.

Post Reply

Who is online

Users browsing this forum: No registered users