Wednesday 6 September 2017

Using layers in Ren'Py

Sometimes you might want some custom layers in Ren'Py.

There is some information over in the documentation here: https://www.renpy.org/doc/html/displaying_images.html#layer

It explains what the 4 default layers (master, transient, screens and overlay) are for and the order they are in.

To add some additional ones you'll want to add a line of code to the bottom of the options.rpy file, like this:

    config.layers = [ 'zero', 'master', 'transient', 'belowmid', 'midlayer', 'abovemid', 'screens', 'overlay']
 
That gives us another four layers to play with, of course you can have more or less and in any order, just remember to test things to make sure you have the layers in the order you want!

I put a new layer called zero right at the bottom, I typically fill this with a solid colour so that the player never accidentally sees the default transparent background. Then the others that I will use for art / displayables are between transient and screens, you might find it better to have some below transient, just experiment to see what happens where!

Here is a script.rpy file as an example of showing things on custom layers:

image nrblack = "#181818"

image skyani:
    "sky1.png" with Dissolve(1.5, alpha=True)
    pause 1.5
    "sky2.png" with Dissolve(1.5, alpha=True)
    pause 1.5
    "sky3.png" with Dissolve(1.5, alpha=True)
    pause 1.5
    "sky2.png" with Dissolve(1.5, alpha=True)
    pause 1.5
    repeat 20

label start:

    show nrblack onlayer zero

    show skyani onlayer belowmid with dissolve
    centered "A simple animated sky background."
    centered "Followed by some midground."
    show midground onlayer midlayer with dissolve
    centered "Finally the foreground."
    show foreground onlayer abovemid with dissolve

    pause

    centered "Now we should hide all of the relevent layers to get ready for the next scene..."

    hide skyani onlayer belowmid
    hide midground onlayer midlayer
    hide foreground onlayer abovemid with dissolve

    "That's it!"

    return


The main thing to note is the onlayer followed by the custom layer name which you'll need on both the show and hide statements.

The two images that aren't defined (midground and foreground) are files names midground.png and foreground.png which are in the images folder, Ren'Py picks these up automatically so they don't need to be manually defined!

This particular example could more easily be achieved just by using show and letting Ren'Py put them in the order they are declared onto the screen, but if you're reading this you probably have run into some case where the standard behaviour isn't enough for your needs and layers might be useful!

Don't forget to hide the images on the layers when you are done with them! XD

Gif:


As a quick aside you may have noticed that the sky animation is set to repeat 20 times, instead of infinitely (repeat). I have started doing this mainly because I noticed quite a lot of system resources being used when multiple infinite animations are displayed at once (as you can imagine!). I'm still trying to get my head around the best practices for being efficient with animations in terms of system resource, so I can't offer much advice in that area, but with only one animation running at a time you shouldn't have any problems!


Monday 4 September 2017

Ren'py fade text in and out

As promised here is the Screens version of the fade in out text! I'll leave the below stuff using the (old!) ui.add on this blog post (below the "--- old post below ---") as it goes into a bit more detail with the custom transform!

So, the way I went about this is to create a new rpy file for my custom screen, I called it custom.rpy, but give it any name you'd like!

This is the entire contents of that file:

screen info_fade:

    text "Look. I'm fading about." at fade_inout_2s


Then in the script.rpy I have:

transform fade_inout_2s:
        xalign 0.5
        yalign 0.5
        alpha 0.08
        easeout_back 2 alpha 0.9
        pause 0
        ease 2 alpha 0.0

label start:

    scene bg room
    "Ok, here we go."
    show screen info_fade
    pause 6
    "That was nice."
    pause
    return

The main bits there being the transform which I declared at the very top of the script.rpy file and the show screen info_fade statement.

I used show screen rather than call screen because I think calling a screen then expects some kind of user interaction, which isn't what I wanted for this effect. I've not used this in a game, so depending on what you are trying to achieve you might need to make some changes, feel free to drop me a line on twitter if you are struggling with anything - I'll help if I can! - @sleepyagents

Here is a gif:



btw I use ScreenToGif to make gifs if anyone is interested - http://www.screentogif.com/ - thanks screentogif people!

And a big thanks to xela and Zetsubou for the lemmasoft thread where I found the basis of this stuff! (link below)

--- (old post below) ---

Here is one way you can fade in and out some text in Ren'Py!

I thought I would be able to do this without looking at the lemmasoft forum, but I failed in that :'D

here is the guide I found from xela https://lemmasoft.renai.us/forums/viewtopic.php?p=336645#p336645
(thanks xela!)

I just changed it a bit as I didn't need the text to move.

You might be thinking that this would be a lot easier with an image - and you'd be correct! but that wouldn't be as accessible, though you could add some text to describe the image, I think this way is better for filesize and flexibility (variables!) anyway.

Right at the top of the script.rpy file I have:

init python:
    def fade_inout_text(text, *args, **kwargs):
        ui.add(At(Text(text, *args, **kwargs), fade_inout_2s))
         
transform fade_inout_2s:
        xalign 0.5
        yalign 0.5
        alpha 0.08
        easeout_back 2 alpha 0.9
        pause 0
        ease 2 alpha 0.0


I don't know much about the def and ui.add bits, so I'll explain a bit about the transform instead!

The xalign and yalign make sure that the text is centered, the alpha 0.08 means that the text is just visible before the animation starts (0 would be invisible), easeout_back 2 alpha 0.9 uses the easing ( see https://www.renpy.org/doc/html/atl.html#warpers for the list of available warpers/easings ) called easeout_back which has a certain effect (see gif below!) which takes 2 seconds to change to 90% visibility (alpha 0.9), of course you could use 1.0 instead for 100% visibility.
Then I added a pause of 0 seconds... followed by ease 2 alpha 0.0 which takes 2 seconds to 'ease' the text to 0% visibility / transparent.
Play around with the numbers and the warpers / easings to get the effect you want!

And then when some text needs to fade in and out during the game you can add this:

    $ fade_inout_text("this is the text that fades in and out", color="#111111", size=30)
    pause 6


You can see I added a 6 second pause after the statement to give it time to do it's thing. You could use a normal pause without an amount of time defined to let the player click to continue.

If you want to display a variable you can replace the string, e.g.

    $ fade_inout_text(my_variable, color="#111111", size=30)

I hope this has been helpful!


I just realised the code to do this with screens is in the forum thread I linked! Which is what I originally intended to do! I'll update this post soon with the code for screens which will be a little nicer haha.