RenPY Coding Tips

Night Hacker

Forum Fanatic
Jul 3, 2021
4,341
21,408
As I have learned to code RenPY, there have been a few useful things I have learned about it. Some are probably well known, others maybe not so much. I have added to this text file as I went and just thought I would share it here...

Python:
#Useful Ren'PY code

# Getting a main character's name while providing a visible default and ensuring it isn't an empty string
# length = 15 limits the length of the name to 15, adjust this as needed.  The "exclude" does not allow the characters listed.
$ name = renpy.input("What's your name?", "Mark", length=10, exclude='{0123456789/*-+.`~!@#$%^&*()_+-=[];\,<>?:|/}')
$ name = name.strip() or "Mark" #note that if the name is blank the strip will return false and it will assign "Mark" to $name instead

# Ensuring a value is not subtracted lower than zero.
# max() will return the highest value, which would be zero if the value drops below zero.
$ player_health = max(player_health - damage, 0)

# You can also ensure the value doesn't go higher than a specific range.
# min() in this case returns the lowest number so if player_health is higher than 100, it will return 100
# which will cap the maximum you can have at 100.
$ player_health = min(player_health + boost, 100)

# Dialog name and text black outline around font. Values are: [(outline, colour, x, y)]
define gui.name_text_outlines = [(2, "#000", 0, 0)]
define gui.dialogue_text_outlines = [(2, "#000", 0, 0)]

# To pause output in the middle of a sentence use: {w}
"Add in a {w} to pause output in the middle of this sentence."
# You can also add in a pause timer to it like {w=1.5} which forces it to continue on
"Add in a {{w=1.5}{w=1.5} to pause output in the middle of this sentence for 1.5 seconds."

# To add italics use: {i}text{/i}, good for private thoughts.
# To add an underline use: {u}text{/u}, good for emphasizing a word like "I {u}really{/u} need to go!"
# To add bold use: {b}bold text{/b}
# To change text colour use: {color=#0F0}text{/color}  Note, use #RGB or #RRGGBB, HTML hex colour codes.

#To output double quotes within a text printout, most people will use \" like...
"Test \"quotes\""
# This will produce: Test "quotes".  But this looks ugly to program and there is a simpler way.  Python doesn't care about single or double
# quotes.  If you want to embed double quotes, just use single quotes for the entire statement like this...
'Test "quotes"'
#...that will produce the same results.  You can do the same if you want single quotes with...
"Test 'quotes'"

#Outputting a string with variables embedded.
OutputStr = "Backgrounds/{}_{}_{}.jpg".format(location, chapter, sequence)

# Adding a pause between lines of code. (see also "$renpy.pause()")
pause       #pause until key pressed
pause 1.0   #pause for 1 seconds or until key pressed
pause .5    #pause for 1/2 second or until key pressed

# Show text slowly printing out at center of screen using a font and color.
# Note: Use a background image with scene like "scene black", this will print over it.
# This will print "Slowly printing text." on the center of your screen using MyFont.ttf at 10 characters
# per second, with the color #F66 (light red) and a font size of 60.
centered "{size=60}{font=MyFont.ttf}{cps=10}{color=#F66}Slowly printing text.{/color}{/cps}{/font}"

# RenPY arrays and random numbers
# Example code which picks a name at random and displays it.
default Jessica = ["Jessica", "Jess", "Mam", "Mum"]  # create an array of four names, add to this if you wish.
$ name = renpy.random.choice(Jessica)
"random name = [name]"

# Adding a progress bar is really simple (https://www.renpy.org/doc/html/splashscreen_presplash.html#adding-a-progress-bar)
You need two images, presplash_background.png (can also be a JPG) for the background, and presplash_foreground.png which will be drawn from left to right as the game loads.  This should probably be transparents with a bar or whatever.

### Showing a tall vertical image that pans up and down the length of it.
#First set up a pan_view early in code, with your other defines...
transform pan_view:
    yalign 0.0
    ease 6.0 yalign 1.0
    ease 6.0 yalign 0.0
    repeat 2
# Then when you want to pan an image, do this...
show image_name at pan_view
 
Last edited:

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,111
14,790
Python:
#To output double quotes within a text printout, most people will use /" like...
"Test /"quotes/""
The escaping character is \, not /.


Python:
#Outputting a string with variables embedded.
OutputStr = "Backgrounds/{}_{}_{}.jpg".format(location, chapter, sequence)
What also works for images declaration :
image whatever = "{}/{}/{}.jpg".format( girlName, girlOutfit, girlPose )
Most screen statement:
text ( "It's {}".format( timePeriod ) )
And any statement that can accept an expression format:
scene expression "background/{}.jpg".format( currentLocation )

Except the last one, the same can be achieved with text substitution:
OutputStr = "Backgrounds/[location]_[chapter]_[sequence].jpg" (99% sure only)
image whatever = "[girlName]/[girlOutfit]/[girlPose].jpg"
text "It's [timePeriod]"

What mean that the "format" structure is more to use when the value come from a variable that can't be used inside text substitution (like list index by example), or with ternary if (text "It's a {}".format( "girl" if babySex == "female" else "boy" ))


Python:
# Adding a pause between lines of code. (see also "$renpy.pause()")
pause       #pause until key pressed
pause 1.0   #pause for 1 seconds or until key pressed
pause .5    #pause for 1/2 second or until key pressed
The pause statement with duration are to avoid at all cost. Unlike it's Python equivalent renpy.pause(), it's not a real pause, but a blank transition that will last "duration" seconds.
This mean that if the player configured Ren'Py to skip transition, the pause will not happen, what will break the way the game looks.
 

Night Hacker

Forum Fanatic
Jul 3, 2021
4,341
21,408
The escaping character is \, not /.
You're right, don't know where my head was in that, been coding in C for decades, LOL...
Another good way to insert quotes without an escape character, and using quotes that look a little nicer is to us ALT+0147 and ALT+0148 for inserting “quotes”.

The pause statement with duration are to avoid at all cost. Unlike it's Python equivalent renpy.pause(), it's not a real pause, but a blank transition that will last "duration" seconds.
This mean that if the player configured Ren'Py to skip transition, the pause will not happen, what will break the way the game looks.
This breaks the skip? Good to know! I'll alter my code in the future.
 

Night Hacker

Forum Fanatic
Jul 3, 2021
4,341
21,408
The pause statement with duration are to avoid at all cost. Unlike it's Python equivalent renpy.pause(), it's not a real pause, but a blank transition that will last "duration" seconds.
This mean that if the player configured Ren'Py to skip transition, the pause will not happen, what will break the way the game looks.
I tested this in my own code by holding down CTRL to skip over any dialog I already read and it had zero problems skipping over the PAUSE commands. There was no pause at all. So I don't see how this breaks anything.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,111
14,790
I tested this in my own code by holding down CTRL to skip over any dialog I already read
What is absolutely not related with what I said, while...


and it had zero problems skipping over the PAUSE commands.
...this is the opposite of the consequences I talked about.


So, I start again:

There's three different options to tweak the skip feature, all available from the preference menu:
1) Skip even the text that you haven't seen ;
2) Continue to skip after menus ;
3) Skip the transitions.

It's the third option that lead to issues when you use the pause statement with a duration.
And the issue is that Ren'Py will skip over the pause (because in this case it will be a transition), not the opposite.

The effect is limited, since it apply only to badly defined animations, but yet it's something that should be kept in mind when you design your game.
 

Night Hacker

Forum Fanatic
Jul 3, 2021
4,341
21,408
Meh, it doesn't sound like much of an issue to me when I doubt many, if any use the features you mention. I have never used them in all the games I have played, so I don't worry about it.
 

darlic

Well-Known Member
Feb 27, 2017
1,806
3,034
I don't think the skip transitions feature is that unpopular.
I, for example, use it in all the games where the devs abuse them. Transitions can be very frustrating if they alter the flow or make it longer to advance dialogues (not talking about skipping with CTRL).
 
  • Like
Reactions: Night Hacker

Night Hacker

Forum Fanatic
Jul 3, 2021
4,341
21,408
I don't think the skip transitions feature is that unpopular.
I, for example, use it in all the games where the devs abuse them. Transitions can be very frustrating if they alter the flow or make it longer to advance dialogues (not talking about skipping with CTRL).
I haven't created a VN yet (well, I am working on one, whether it sees the light of day is yet to be seen), but if I do, I'll keep this in mind. I already converted some code over from "pause 0.5" etc... to "$renpy.pause(0.5)" or whatever. Better safe than sorry.
 
  • Like
Reactions: darlic

Night Hacker

Forum Fanatic
Jul 3, 2021
4,341
21,408
Some more code I learned about...

Python:
### Showing a horizontally scrolling background, like the passing scenery by a car.
#First we display the scrolling background image which should be twice as wide as the screen
#So a 1920x1080 display should have a 3840x1080 image.  The right and left half of the image should match
#so that when the image reaches the right side and jumps back to the start, you don't notice the jump
image ParallaxBG:
        "bground.png" #wide image that will be scrolling horizontally
        xalign 1.0         
        linear 1.0 xalign 0.0
        repeat

#show the above scrolling image first
scene ParallaxBG
#overlay a foreground image like a person in a car with a transparent area like a window to see the background through
show fground #"fground" in this is the name of the foreground image
 

Bibifoc

Engaged Member
Apr 7, 2018
2,093
4,201
So, I start again:

There's three different options to tweak the skip feature, all available from the preference menu:
1) Skip even the text that you haven't seen ;
2) Continue to skip after menus ;
3) Skip the transitions.

It's the third option that lead to issues when you use the pause statement with a duration.
And the issue is that Ren'Py will skip over the pause (because in this case it will be a transition), not the opposite.
Hello,
You're sure of that? I did a test:
Python:
label start:

    "Start"

    scene expression "#ff0000"
    pause 1.0
    scene expression "#00ff00"
    pause 1.0
    scene expression "#ff0000"
    pause 1.0
    scene expression "#00ff00"

    "End"

    return
I don't see any difference with "Skip transition" on or off. :unsure:
With Renpy 8.0.1 at least.

The effect is limited, since it apply only to badly defined animations, but yet it's something that should be kept in mind when you design your game.
Could you also clarify what you mean with "badly defined animations" please?
Thx
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,111
14,790
You're sure of that?
Yes, I'm sure. But after some search it's not anymore the default behavior. Ren'Py silently (it's not in the changelog) introduced a configuration variable that now tweak this behavior.


Could you also clarify what you mean with "badly defined animations" please?
An animation should be defined with the (ATL) and not directly into a label.
 
  • Like
Reactions: Bibifoc

FranceToast

Active Member
Donor
Jul 31, 2018
562
894
I personally love the pan feature when it is done well, especially if the VN doesn't have animations.
Is there a way to do smooth zooms as well?
 

Night Hacker

Forum Fanatic
Jul 3, 2021
4,341
21,408
I personally love the pan feature when it is done well, especially if the VN doesn't have animations.
Is there a way to do smooth zooms as well?
Try this out. Play around with the "ease" value for how fast it zooms in; the "zoom" value for how much it zooms in and the "xalign" and "yalign" for where it zooms in (0.5 is center, 0.0 is left/top and 1.0 is right/bottom).
Python:
scene background:
        xalign 0.5
        yalign 0.5
        ease 1.0 zoom 1.5
 
Last edited:
  • Like
Reactions: FranceToast

FranceToast

Active Member
Donor
Jul 31, 2018
562
894
Try this out. Play around with the "ease" value for how fast it zooms in, the "zoom" value for how much in zooms in and the "xalign" and "yalign" for where it zooms in (0.5 is center, 0.0 is left/top and 1.0 is right/bottom).
Python:
scene background:
        xalign 0.5
        yalign 0.5
        ease 1.0 zoom 1.5
Thanks! I'll give it a try!
 
  • Like
Reactions: Night Hacker

Freshenstein

Member
Jan 1, 2018
105
137
How would you code a age input but only for a specific range, like they can choose any age between 18 and 40?
 

Night Hacker

Forum Fanatic
Jul 3, 2021
4,341
21,408
How would you code a age input but only for a specific range, like they can choose any age between 18 and 40?
This works...

Python:
label getage:
    $ a = renpy.input("What is her age (18-40)?", "33", allow="0123456789")   #only allow numeric input
    $ a = a.strip() or "33"   #if the player enters nothing, default to 33
    $ age = int(a)            #convert the string to an integer
    if age < 18 or age > 40:  #make sure we're within limits
        "Please enter a value between 18 and 40."
        jump getage

    "You entered [age]."
    return
 
Last edited:
  • Like
Reactions: Freshenstein

Freshenstein

Member
Jan 1, 2018
105
137
This works...

Python:
label getage:
    $ a = renpy.input("What is her age (18-40)?", "33", allow="0123456789")   #only allow numeric input
    $ a = a.strip() or "33"   #if the player enters nothing, default to 33
    $ age = int(a)            #convert the string to an integer
    if age < 18 or age > 40:  #make sure we're within limits
        "Please enter a value between 18 and 40."
        jump getage

    "You entered [age]."
    return
That work's beautifully. Thank you so much!
 
  • Red Heart
Reactions: Night Hacker

Night Hacker

Forum Fanatic
Jul 3, 2021
4,341
21,408
Adding code which displays a small image in the upper left corner for a second or two, generally used if you wish to show the player when they gain or lose something, like points. In this example I have a VN with a wife who can gain good wife or bad wife points, and it shows a small image indicating this for 2 seconds. It's fairly simple to implement but adds a little extra to your game...
Python:
### Points Alerts - briefly displays a small image in the upper left corner
# useful for showing points gained or lost with character relations
# Set these up ahead of time...
image pts_wife_plus:
        "gui/pts_wife_plus.png" # the image to display, usually something small
        linear 2.0 alpha 0.0     # blending used and the alpha (0.0 = transparent)
        
screen screenPtsWifePlus():
    zorder 1     # Make sure the image is on top of the rest of the screen
    add "pts_wife_plus" xalign 0.05 yalign 0.05  # show the image in the upper left corner
    timer 2.0 action Hide("screenPtsWifePlus")  # after 2 seconds, hide the image

### Use this line in game code to show the points image before altering the points
show screenPtsWifePlus # show the small image indicating points changed
$ wifepoints += 1       # add the points or whatever

If you wish to embed a URL into your game with a link that can be clicked on, this is fairly simple...
Python:
### Embedding a URL in text
# Note: be sure to include http:// or https:// before it to open the default browser.
"{size=50}Greetings to everyone at {a=https://f95zone.to/threads/a-wife-and-mother-fan-art.15218/}F95 Zone's A Wife and Mother Fan Art page{/a}!"
...in the above code, the text between {a= and } is the URL to go to, followed by the text to display for the link, in this example it's "F95 Zone's A Wife and Mother Fan Art page" followed by {/a} which indicates the end of the link.