Automatically Assign Background Images to Layer? [SOLVED]

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
MasterLillyclaw
Newbie
Posts: 7
Joined: Sun Jul 16, 2017 9:00 pm
Projects: The Crossroads Where They Connect
Contact:

Automatically Assign Background Images to Layer? [SOLVED]

#1 Post by MasterLillyclaw » Mon Jul 17, 2017 5:12 pm

In my game, sometimes when changing the background, I'll call "scene", but other times, I call "show". I usually do "scene" at some sort of time jump, and "show" when I'm doing a brief transition - "scene" causes the textbox to disappear, which is an effect I like for that transition, while it stays during a "show" transition. "Scene" will always wipe the slate of everything, including characters, but that's not the issue. Sometimes, when I call "show", I want the characters to disappear, but other times, I want them to stay on screen. However, just having the background be shown will place it on TOP of any preceding images, including sprites. I currently have two solutions:

(1) Re-show the sprite(s) I want to keep every time I want to keep them on-screen during a "show" background change.
  • Pros: I'm pretty sure I'll have less sprites staying on screen than not, although that may change as I write more of my story.
    Cons: It requires me paying very careful attention to if a character is supposed to stay on screen or not, lest the scene change and suddenly an invisible person is talking. I may also run out of layers, since "show" doesn't wipe the slate, and the character may not come up on screen regardless.
(2) Place the backgrounds on a different layer, and specifically label each and every background as being in that section, ensuring that I hide all characters as necessary since the background will no longer cover them during a "show".
  • Pros: I want to hide all characters who disappear during scene changes before changing the background anyways, since I think it looks nicer, so that's not an issue. This method also feels more "pythonic" (or ren'pythonic? More conceptually accurate?), as it's not me constantly overwriting a sprite, but rather adding another level of organization.
    Cons: Currently, this requires me adding "onlayer bg" to each and every scene change, since the background layer needs to be before the sprites so that it doesn't cover them:

    Code: Select all

        $ config.layers = ['bg', 'master', 'transient', 'screens', 'overlay']
    
    This, however, seems extremely tedious, and along the same lines as before, I have to make sure that I type this every time it's required, or sprites will stay on screen when they're supposed to leave.
I want to know if there is a way to create a layer, and then when images are created, specifically assign those images to said layer. Basically, have a background layer, and tag all my images when they're created so they specifically show up in the background layer, instead of having to assign it each and every time I show a background image. This way, I could get the organization of layers without the tediousness and larger margin of error involved in having to specifically attach the tag every time I show a background image.
I don't know if this is possible, although it would be nice, since it feels both code-efficient and logical. If not, do you think one of the two methods I mentioned before is better than the other? Or is there some other method that is better? For now I'll be hard-writing in sprites staying on screen just because it's easier, although that may change once I've gotten more progress.
Last edited by MasterLillyclaw on Tue Jul 18, 2017 2:43 pm, edited 1 time in total.

philat
Eileen-Class Veteran
Posts: 1853
Joined: Wed Dec 04, 2013 12:33 pm
Contact:

Re: Automatically Assign Background Images to Layer?

#2 Post by philat » Mon Jul 17, 2017 9:19 pm

MasterLillyclaw wrote:I want to know if there is a way to create a layer, and then when images are created, specifically assign those images to said layer.
As far as I know, no.

I have no preference over either method you've described.

MasterLillyclaw
Newbie
Posts: 7
Joined: Sun Jul 16, 2017 9:00 pm
Projects: The Crossroads Where They Connect
Contact:

Re: Automatically Assign Background Images to Layer?

#3 Post by MasterLillyclaw » Tue Jul 18, 2017 2:42 pm

philat wrote: As far as I know, no.
Alas, I feel that I keep thinking of complicated things to try in Ren'Py that aren't feasible :roll:

Well I'll be marking this as solved, then. For anyone else who reads it though, I'm actually going to stick with assigning images to a background layer rather than re-call the sprites, because that adds more clutter to the master layer and makes it more likely to overflow and stop showing images (especially since I'm using "show" and not scene, so the slate isn't getting wiped). Using a different layer significantly decreases the clutter, so at the cost of adding "onlayer bg" to every background, I don't have to worry about sprites not showing up or backgrounds not changing.

MasterLillyclaw
Newbie
Posts: 7
Joined: Sun Jul 16, 2017 9:00 pm
Projects: The Crossroads Where They Connect
Contact:

Re: Automatically Assign Background Images to Layer? [SOLVED

#4 Post by MasterLillyclaw » Tue Jul 18, 2017 5:28 pm

UPDATE: I actually found out a way to do this!!!
Someone named Ziassan has a lovely link here: (viewtopic.php?f=51&t=16371) that allows you to go through and assign image names based on their folder names (although Ren'Py does do this automatically now if you file your images into folders and name them correctly - and it can apply to both sprites and backgrounds. I was also looking through information on configuring dictionaries and things like that when I came across "config.tag_layer", which lets you do exactly what I want - assign an image to a specific layer. I then combined the two for the following code:

Code: Select all

    # adds the background layer
    config.layers = ['bg', 'master', 'transient', 'screens', 'overlay']
    
    # defines all images
    for file in renpy.list_files():
        if file.startswith('images/') and file.endswith('.png'):
            filename = file.replace('images/', '').replace('/', ' ').replace('.png', '')
            renpy.image(filename, Image(file))
            # auto-assigns backgrounds to bg layer
            if filename.startswith('bg'):
                config.tag_layer = { filename : 'bg' }
So first I put in the background layer, then I assigned all file images their names, and if a file had 'bg' in it, then I tagged that image with the background layer. I removed all instances of 'onlayer bg' from my code and my code is still working! So hooray for random chance :D

Note: As far as I can tell, you have to assign all images with this method if you want to assign them to a tag. I tried only doing it for images with the name 'images/bg/' and my character sprites didn't show correctly. There might be a way around this, but as far as I know, it's not a problem if all images are assigned this way, since this is basically how Ren'Py does it but also making sure to assign backgrounds to the background layer.

User avatar
shin.e.d
Newbie
Posts: 22
Joined: Sat Jan 10, 2015 10:50 am
Projects: Data Lion and an unnamed bxb game with dinosaurs!
Contact:

Re: Automatically Assign Background Images to Layer? [SOLVED

#5 Post by shin.e.d » Tue Jul 18, 2017 8:50 pm

Too lazy to figure out what that code does, but I think config.tag_layer already does this thankfully.

Edit: Now that I look at it, that code allows multiple bg images to be shown at once doesn't it? What I put below auto-replaces anything named 'bg name_here'. So that's one difference.

Edit2: edited the example code.
Edit3: and added more stuff.

Layers example:

Code: Select all

define config.layers = ['bg_layer', 'master', 'transient', 'screens', 'overlay']
define config.tag_layer = {'bg':'bg_layer'} ## 'image's name':'layer's name'

image bg place1 = Solid("666")

label start:
    show bg place1 ## now this image is on bg_layer.
    pause

    hide bg place1
    ## ^ hides bg place1 onlayer bg_layer. Luckily this works without 'onlayer',
    ## but only if the full name is used.

    scene onlayer bg_layer ## this would clear the whole layer.
Though folders that auto assign the tags sounds like it could make things easier. The tag dictionaries can get pretty long.

An alternative to putting stuff on layers, is config.tag_zorder which only changes the draw order.

Zorder and layers example:

Code: Select all

## put in to script file or wherever. ##########################################
define config.layers = ['master', 'transient', 'screens', 'fx', 'overlay']

## automatically assign images to layers.
define config.tag_layer = {'snow':'fx','snow_pile':'fx'}

## Rearrange the order that images are drawn. Default is zorder 0.
define config.tag_zorder = {'black':-101, 'bg':-100,
    'text':100}
## ^ the line can be broken up with an indent.

image text = ParameterizedText(xalign=0.5, yalign=0.3)
image snow = SnowBlossom(Solid("#fff", xysize=(12,12)), count=10, xspeed=(80, 400), yspeed=(80, 200), horizontal=True)
image snow_small = SnowBlossom(Solid("#fff", xysize=(6,6)), count=10, xspeed=(80, 400), yspeed=(80, 200), horizontal=True)
image snow_pile = Solid("#fff", xysize=(90,400))
image bg place1 = Solid("666")
image bg place2 = Solid("ccc", xysize=(800,680))
image boy ok = Placeholder("boy")
image boy flip = Placeholder("boy", flip=True)

label test_order:
    show snow ## tagged to the new layer 'fx' (above screens)
    show snow_pile at right ## ^same

    scene black ## scene only clears the default layer. So snow fx is still going.

    show text "Snow School" ## text is tagged to zorder 100, on the default layer.

    menu:
        "next":
            pass

    show boy ok ## has no config tags. So it's on the default layer and zorder 0.

    show bg place1 ## bg is tagged to zorder -100.
    ## black is tagged to zorder -101, so bg isn't hidden under it.

    show snow_small behind boy ## using 'behind' adjusts zorder too.

    menu:
        "next":
            pass

    show bg place2 ## replaces place1 with place2 since it shares the name 'bg '
    with dissolve
    "Oh hello! I didn't see ya there. My name is uh... boy."

    ## animate a simple move for a character.
    show boy with move:
        xalign 0.3
    pause 1.0

    show boy flip ## change the characters sprite
    "Anyways, gotta run, see ya later."

    menu:
        "ok":
            pass

    hide boy with dissolve
    "Welp guess I'm dissolving instead of walking.\nByeee...."

    hide snow ## hides the snow on fx (luckily this works without using onlayer)
    hide snow_small
    with dissolve

    show text "The snow stopped." as text2 zorder 100:
        yalign 0.5
    pause
    ## ^ renamed this to text2 so that the Snow School text would stay.
    ## But now its name isn't in the config tags... so zorder was put directly.
    ## Or since config.tag_zorder is a python dict, stuff can be added like this.
    $config.tag_zorder['text2'] = 100

    scene ## clear the default layer
    scene onlayer fx ## clear the fx layer
    with fade
    menu:
        "end":
            return
Last edited by shin.e.d on Sat Jul 22, 2017 10:51 am, edited 1 time in total.

MasterLillyclaw
Newbie
Posts: 7
Joined: Sun Jul 16, 2017 9:00 pm
Projects: The Crossroads Where They Connect
Contact:

Re: Automatically Assign Background Images to Layer? [SOLVED

#6 Post by MasterLillyclaw » Wed Jul 19, 2017 4:44 pm

shin.e.d wrote: Too lazy to figure out what that code does, but I think config.tag_layer already does this thankfully.

Edit: Now that I look at it, that code allows multiple bg images to be shown at once doesn't it? What I put below auto-replaces anything named 'bg name_here'. So that's one difference.

Layers example:

Code: Select all

define config.layers = ['bg', 'master', 'transient', 'screens', 'overlay']
define config.tag_layer = {'bg':'bg'} ## 'image's name':'layer's name'

image bg place1 = Solid("666")

label start:
    show bg place1 ## now this image is on a layer.
    pause

    hide bg ## hides the bg (luckily this works without using onlayer)
    scene onlayer bg ## clears whole layer
My code uses config.tag_layer, but the difference is that mine assigns each individual background image to the layer separately as it parses through every file; the code basically looks through all files, and if the files are in the images folder then it will create them, and if they're in the background folder then it will assign them to the background layer.
Your code assigns only one string, 'bg', to the background, which is why you can only have the one background layer at a time. tag_layer works in my mind basically as a dictionary; you're reassigning what the string assigned is every time, whereas my code keeps adding new inputs into the dictionary to expand it.

shin.e.d wrote: An alternative to putting stuff on layers, is config.tag_zorder which only changes the draw order.
From what I can tell from your code example, tag_zorder seems to be more for forcing certain effects within the same layer to be either above or beneath each other? I'm not quite sure why you'd want to zorder 'black' and 'bg' to different orders when calling the 'bg' should cover 'black' anyways if they're on the same layer. I guess if you wanted to always have it in the background, but you could still just hide all other images on the layer to reveal it.And if the text is zordered onto the default layer, do you need to zorder it at all?
I'm still pretty new to Ren'Py so a lot of stuff still doesn't quite make sense to me.

User avatar
shin.e.d
Newbie
Posts: 22
Joined: Sat Jan 10, 2015 10:50 am
Projects: Data Lion and an unnamed bxb game with dinosaurs!
Contact:

Re: Automatically Assign Background Images to Layer? [SOLVED

#7 Post by shin.e.d » Thu Jul 20, 2017 11:34 am

From what I can tell from your code example, tag_zorder seems to be more for forcing certain effects within the same layer to be either above or beneath each other?
Yep. zorder makes images to be above/below other images on the same layer.
It isn't used in most Ren'py games though. Usually 'show', and 'behind' is sufficent, but it would depend on the game and writing style.

Anyways thanks abunch for providing that little python script btw! :3 It's really useful. I edited it down to look like this for my game: (Hopefully it works well enough.) edit: fixed a thing.

Code: Select all

## this adds images to config.tag_layer based on their subfolder.
init python hide:
    for file in renpy.list_files():
        if file.startswith('images/bg/') and file.endswith('.png'):
            ## extract the file's name.
            getfilename = file.replace('images/bg/', '').replace('.png', '')
            ## if there's a space in the file's name this won't work properly,
            ## eg "bg place1.png" BUT the image's tag 'bg' can be added instead
            ## utilizing the line below.
            ## Though with this everything starting with 'bg ' will be affected.
            getfilename = "".join(getfilename.split(" ")[0])
            ## assign the file's name to the layer's name.
            config.tag_layer[getfilename] = 'bg'

Post Reply

Who is online

Users browsing this forum: Google [Bot]