Now that you’ve learned about booleans and the basics of variables in Ren’Py as well as some basic conditional statements, you’re ready to learn about more variable types.
As with before, I recommend you have a passing familiarity with choice menus before going through this guide, and that you go through the previous two tutorials as well (A Quick Primer on Variables in Ren’Py and Conditional Statements in Ren’Py).
Simple Variable Types
- Booleans – A boolean (often called a
bool
for short) is one of eitherTrue
orFalse
. A Quick Primer on Variables in Ren’Py covers booleans as well. - Integers – Numbers without decimal places like
1
,-72
,0
, and51687
. May be calledint
for short. - Floats – Numbers with decimal places, like
0.0
,3.14159
,-500043.2
and0.00004
.Float
is short forFloating Point Number
, named for the fact that the decimal point can “float” anywhere in the number, since there isn’t a fixed number of digits before or after the decimal point e.g.100.05
has the decimal point after the third number but4.9543
has it after the first number, even though both have 5 digits. - Strings – Words you put inside quotation marks. Python and Ren’Py allow you to declare strings with either apostrophes (
'like this'
) or with quotations ("like this"
). Anything inside quotes is a string. So"1"
is a string, not an integer, because it’s in quotes. Other example strings are"This is a string"
,'Pi is approximately equal to 3.14159'
, and"!!!!"
. - None – This is actually a very special kind of value, the
None
value. If you’re familiar with other programming languages,None
is approximately equivalent toNULL
. For the most part, you can think ofNone
as a bit like a specialFalse
value.
Matching variables to use cases
Now we’ll go over what situations you might want to use each variable type for. There will also be a quiz testing what you’ve learned.
Booleans
Booleans are usually the first variable type most people find out about, and are probably the most common across Ren’Py games. As mentioned, they are one of two values: True
or False
.
In a default Ren’Py game, you’ll see booleans already in use in several places. For example, in screens.rpy
there is a screen called screen navigation
, and a line inside there that says if main_menu:
. main_menu
is a boolean variable that Ren’Py sets to be True
if the player is on the main menu and False
if they’re in-game. In this case, if the player is on the main menu, they should be shown a Start
button to start the game. If they’re already in-game though, there’s no need to show them a start button.
Places where you SHOULD use Booleans:
- Tracking player actions e.g. did they give Ashwin a gift? True/False
gave_ashwin_gift = True
- Keeping track of binary choices e.g. did the player lie about knowing who Xia is?
lied_about_xia = False
- Toggling preferences e.g. do they have animations toggled on or off?
persistent.animations_on = True
Places where you should NOT use Booleans:
- When you have 2+ values that are
Example boolean use:
default player_ate_apple = False
label start():
"One day, Snow White was visited by a strange old lady selling apples."
menu:
"Eat the apple":
$ player_ate_apple = True
"She ate the apple. It was lovely and red and juicy."
"Don't eat the apple.":
$ player_ate_apple = False
"She shook her head at the old woman and decided not to take the apple."
"After the woman left, Snow White returned to her cleaning."
if player_ate_apple:
"She began to feel quite unwell and fainted in the kitchen."
jump ate_apple
else:
jump end_day_1
This is a good use for boolean values as there are only two possibilities – either the player ate the apple (True) or they didn’t (False). This doesn’t conflict with anything else they could have done. You may also note that the $ player_ate_apple = False
line under the "Don't eat the apple."
choice is technically optional because player_ate_apple
begins with a value of False
. So, unless you change it earlier in the code, it will still be False whenever you go to check it. However, it’s good to add it for clarity and to prevent accidental errors in case player_ate_apple
was somehow set to True
before reaching this choice menu.
You may also notice that there is a conditional statement there – the thing that says if player_ate_apple
. This is a useful feature of booleans is that you can just check if boolean_variable
to see if boolean_variable
is True. You can see more examples of conditional statements with booleans in Conditional Statements in Ren’Py.
The else
statement basically says “if the condition(s) before this statement were NOT true, then do this”. So in the case of
if player_ate_apple:
jump ate_apple
else:
jump end_day_1
when player_ate_apple
is False
, the line if player_ate_apple
isn’t True (the player didn’t eat the apple). So the program moves on to the next condition, which is the else
line and jumps to the end_day_1
label instead.
Integers
Integers are excellent for tracking any sort of numerical values in your game, such as love point totals for characters or the number of times the player has gone to the park. Remember that an integer is any non-decimal number e.g. -5, 20, 0, or 124083
In a default Ren’Py game, integers are used for some preferences, such as the number of characters displayed per-second for dialogue (also known as CPS characters per second), and for lots of defined GUI values like the text size of in-game dialogue or the width (in pixels) of the dialogue box.
Places where you SHOULD use Integers:
- When keeping track of collected points e.g. how many affection points do they have with Xia?
xia_love_points = 0
andxia_love_points += 1
- When counting how many times a certain action has been done e.g. how many times has the player visited the park?
player_park_visits = 1
- Tracking the number of actions the player has left before time runs out e.g. there’s only enough time to dance with two people at the ball. Once you’ve danced with two people, the ball is over.
num_dance_partners = 2
- Tracking how many items a player is holding or has acquired e.g. How many life jackets did the player manage to get?
num_life_jackets = 3
Places where you should NOT use Integers:
- Variables where there are only two outcomes e.g. either they have enough life jackets or they don’t, and there’s no way to acquire/lose just one or two (instead of all the life jackets)
- In this case, a boolean would be more appropriate (see the definition of mutual exclusivity)
- Keeping track of multiple distinct but diverse options e.g. the player can be either tall or short. You use a variable like
player_height = 0
for short and1
for tall- This is more subjective; it’s not a bad choice per se, but in the case of player heights, it can make your code harder to read by using numbers for non-numerical concepts. Additionally, what would happen if you wanted to allow players to be “average” height? Do you use
0.5
?2
? In this case, a better choice would be to use strings likeplayer_height = "short"
,player_height = "average"
etc - However, if you wanted to represent height as actual numerical values like 150cm, then an integer would be a good choice, especially if you’re doing comparisons like
if player_height < 150
->"You couldn't reach the top shelf."
- This is more subjective; it’s not a bad choice per se, but in the case of player heights, it can make your code harder to read by using numbers for non-numerical concepts. Additionally, what would happen if you wanted to allow players to be “average” height? Do you use
Example integer use:
default zoran_love_points = 0
label start():
"Zoran shuffles awkwardly, looking down at his feet."
menu:
"Make a joke.":
$ zoran_love_points += 1
"He smiles when you finish telling the joke."
"Tell him to get over himself.":
$ zoran_love_points -= 1
"He looks almost angry at you."
"Then he gets up and leaves."
Note that $ zoran_love_points += 1
will set the value of zoran_love_points
equal to 1 + whatever the previous value of zoran_love_points
was. So, if zoran_love_points
was 5, after the line $ zoran_love_points += 1
it will be equal to 6. A later tutorial will cover this and other numerical operators.
Floats
Floats are very similar to integers, but refer to numbers with decimal places like 3.1415, -19.0, and 0.2
In a default Ren’Py game, floats are mostly used for alignment properties of GUI elements like the choice buttons. The alignment property, align
for short, can position things like buttons on the screen. It uses floats to represent a percentage of the screen rather than a set number of pixels. So, a value like 0.5
indicates the alignment should be 50% of the way down/across the screen (aka centered).
Places where you SHOULD use Floats:
- Tracking numbers which have decimal places, such as how much money the player has (including cents).
money = 100.00
- Using decimal places as percentages
grade = 30.0/40.0
orgrade = 0.9
Places where you should NOT use Floats:
- Anywhere that you need distinct values or need to compare exact numbers.
- Floats can’t be exact due to the infinite nature of decimal points. When it comes to numbers with a lot of decimal places like pi, the computer has to limit how many digits it will use so it can do calculations, which means that there will be some rounding errors.
- So if you find yourself comparing two floats like
if grade == 0.9
, you may want to rethink if you should use integers OR check for a range instead e.g.if grade >= 0.85 and grade <= 0.95
. We will cover these types of comparisons in Numerical Comparisons and Combinations in Ren’Py later on.
- Same rules where integers would be bad also generally apply to floats
Example float use:
default cash = 10.00
label start():
"You went to the market to make some purchases."
menu:
"What will you buy?"
"A Flower ($4.99)":
$ cash -= 4.99
"You purchased a flower."
"Don't purchase anything":
"You didn't end up buying anything."
Strings
Strings are one of the most flexible variable types. They’ll contain just about anything so long as you put it in quotation marks. As a result, they’re useful for holding a variety of information.
In a default Ren’Py game, strings are used for things like defining colour codes to use for text (e.g. "#FF0000"
, the hex colour code for red) and for the name of your game and what the current version is. They’re also used to specify file paths for things like images, sound effects, and font files.
Places where you SHOULD use Strings:
- When you have a lot of possible values for a variable that correspond to words e.g. keeping track of what colour hair the player has
hair_color = "black"
- When you want to use a variable in dialogue during the script e.g.
player_height = "short"
and thenp "Yeah, I'm pretty [player_height]."
. This would display to the player like"Yeah, I'm pretty short."
- When a variable corresponds to an image or filename you want to use e.g.
xia_hair = "long"
and thenimage xia happy = "Characters/xia/[xia_hair].png"
. Like variable substitution in dialogue, this will search for an image atimages/Characters/xia/long.png
. If you later change Xia’s hair to be short ($ xia_hair = "short"
), then the game would instead look for the fileimages/Characters/xia/short.png
. (This will be covered in a later tutorial) - If you want to have branching storylines reconvene at some common event, then branch off again depending on past choices.
- For example, the player can be on Xia, Zoran, or Ashwin’s romance routes. There is a common event to all three routes where the player spends the day at work. After they finish their job, the next scene depends on who they are romancing. Before you jump to the common event label, you can set up a variable like
$ next_scene = "zoran_scene_4"
at the end of each specific route, and then at the end of the common event you can writejump expression next_scene
to jump to the label saved in thenext_scene
variable (so for Zoran it would jump to a label namedzoran_scene_4
)jump expression
is a special variation of thejump
statement that lets you use a string to get the label name to jump to.
- This and other more complex use of strings will be covered in a later tutorial.
- For example, the player can be on Xia, Zoran, or Ashwin’s romance routes. There is a common event to all three routes where the player spends the day at work. After they finish their job, the next scene depends on who they are romancing. Before you jump to the common event label, you can set up a variable like
Places where you should NOT use Strings:
- When you’re keeping track of counters (numbers that increase/decrease during the game, like affection points or counting how many times the player has said a swear word) or other numerical values
- Usually integers are better for this. Sometimes floats are also helpful.
- If the variable only has two possible values in a yes/no-style pattern
- An exception to this is if you use the variable to determine which image to use for a character e.g. the character has two different outfits, their work outfit and their normal outfit. You have a variable
ashwin_outfit = "work"
orashwin_outfit = "normal"
. Even though Ashwin is either wearing/not wearing their work uniform, you might use this variable inside an image definition likeimage ash = "Characters/Ashwin/[ashwin_outfit].png"
so it makes sense to keep it as a string so you can take advantage of Ren’Py’s variable substitution. With the above format, Ren’Py will either look for the imageimages/Characters/Ashwin/work.png
orimages/Characters/Ashwin/normal.png
depending on the value ofashwin_outfit
. (Keep an eye out for a later tutorial on this topic)
- An exception to this is if you use the variable to determine which image to use for a character e.g. the character has two different outfits, their work outfit and their normal outfit. You have a variable
Example string use:
default gift = ""
label start():
"At the mall, you decided you wanted to buy Ashwin something."
menu:
"Buy them a bath bomb.":
$ gift = "bath bomb"
"Buy them a self-help book.":
$ gift = "self-help book"
"Buy them a digital camera.":
$ gift = "digital camera"
"Later that day, you were able to give them the [gift] you bought earlier."
"They liked it a lot."
The player can only get one gift for Ashwin, so it makes sense to store this variable as a string. Even more useful is that we can have Ren’Py substitute it in the sentence after the menu so that if the player bought Ashwin a bath bomb the line reads “Later that day, you were able to give them the bath bomb you bought earlier.” This saves us having to write out three separate sentences for each gift with only the name of the gift changed, but you can also customize later text by checking for conditions like if gift == "bath bomb"
(these sorts of comparisons are covered in more detail in the next tutorial, Equality Comparisons in Ren’Py).
Flow Chart
For a visual example of when it is best to use each variable type, you can use the following flowchart:
Next Steps
Now that you know about the four basic variable types in Ren’Py, it’s time to see what you’ve learned with a quiz. Try the Simple Variables Quiz before moving onto the next tutorial, Equality Comparisons in Ren’Py.