A Quick Primer on Variables in Ren’Py

A Quick Primer on Variables in Ren’Py

This guide will walk you through the very basics of using variables in Ren’Py to prepare you for more involved tutorials later on. If you’re new to Ren’Py or new to coding in general, this guide is for you.

Difficulty Level: Beginner

These tutorials do not expect any prior coding knowledge. This tutorial is a great place to start learning about variables!

What are Variables?

Variables are one of the basic building blocks of programming. You use variables in Ren’Py to keep track of values you’d like to use during your game. In coding, a value is a term for any kind of information you’d like to store and use during a program. Values fall into one of two main categories: constants and variables.

constant, as the name suggests, should have a constant value. It shouldn’t change over the course of a game. In Ren’Py, you use define to declare (set up) a constant e.g. define config.has_music = True. Other built-in features in Ren’Py are expected to be constants too, with some exceptions. For example, the GUI[1] styles which are used to customize the appearance of the game UI, once defined, aren’t expected to change. Ren’Py does not keep track of constants in save files, since they’re not expected to change from their initial value.

variable, on the other hand, is a value that can be updated over the course of a game. You use default to declare a variable in Ren’Py e.g. default ate_pizza = False. Most things you use in the script will be variables, so we’ll cover those first.

[1] GUI stands for Graphical User Interface. It refers to things like the buttons and menus you see on-screen when interacting with a program like a phone app or a game. Similarly, UI stands for User Interface and is a slightly more broad term that encompasses any systems the user uses to interact with a program. For something like a Ren’Py game, these terms are mostly interchangeable.

Booleans

There are lots of values that you can assign to variables. The simplest of these is called a boolean. A boolean (often called a bool for short) is one of either True or False (note the capitalization; it is case-sensitive). You may also see people refer to booleans or variables as “flags”. This is because they’re often used to “flag” places in your script where you would like to do something, such as track a player’s choice to change the script.

There are other variable types, but you’ll see those in a later tutorial. This tutorial will focus on booleans, as they’re the simplest.

Using Variables in your Script

Setting up variables

Before you can get to using variables, you first need to know how to set them up in your game. The most important thing to know about setting up variables is that you should always be using default to declare them (set them up) before the game starts. In previous Ren’Py versions, you’d declare the variable with a line of Python (using $ var = True-style statements), usually in the start label. However, recent versions use default to declare the variables even earlier, before the game starts.

default is essential for save compatibility and reducing errors. If Ren’Py has never seen a variable before, default gives it a default value so you won’t get any errors that a variable is undefined. You will see an example for why this is so important later on. I also cover this topic in more depth in The Definitive Default Define Ren’Py Article. For now, what you need to know is that you should set up your variables with default like so:

default bought_ice_cream = False
label start:
    "It was a hot, sunny day as you walked downtown."

Using default

The basic structure of a default statement is default <var_name> = <value> where <var_name> is the name of your variable, and <value> is the value you are setting it to. In the example above, the name of the variable is bought_ice_cream and the value is False.

Note that default bought_ice_cream = False is not “inside” a label (that is, the code itself is not part of the block under label start). For now, it’s good to declare your variables above label start until you start accumulating a bunch of them.

Tip: Ren’Py is built off of the programming language Python. It borrows most of its syntax and style from Python conventions. In Python, you should name variables using lower_case_with_underscores, commonly called snake_case. This means that the variable name should be all lowercase, with words separated by underscores to improve readability, such as fell_overboardaffection_pointsate_one_cookie, or score. Variable names can only use alphabet letters, numbers, and underscores. Note that while they can have numbers, the numbers can’t be at the start of the name. Both 1_cookie and 1cookie are invalid variable names, but ate_1_cookie is valid. Similarly, they can’t take other separator characters like spaces or hyphens, so affection points or fell-overboard are not valid variable names. Ren’Py also reserves the use of variable names that begin with _, so you can’t use variable names like _score or _affection_points. It is important to follow these conventions where possible to make your code understandable and easy to use by other developers.

So now you’ve got your variable set up with default bought_ice_cream = False. How do you change it in-game?

Changing variables in-game

To change a variable in Ren’Py, you need to use Python. Ren’Py has a shortcut for indicating a particular line of code is Python: $. If you put $ at the beginning of a line of code, Ren’Py knows that it should execute it as a line of Python. So, to change the value of bought_ice_cream, you can do:

default bought_ice_cream = False
label start:
    "It was a hot, sunny day as you walked downtown."
    $ bought_ice_cream = True
    "You decided to stop and buy some ice cream."

The code on line 4 will change the value of bought_ice_cream to True.

Of course, this would make more sense if you had a choice menu rather than just setting it to True for every player. Choice menus aren’t covered in this tutorial, but you can refer to the Ren’Py documentation for information on them. Consider, then:

default bought_ice_cream = False
label start:
    "It was a hot, sunny day as you walked downtown."
    menu:
        "You decided to stop and buy some ice cream.":
            $ bought_ice_cream = True
        "You whistled a tune as you walked.":
            $ bought_ice_cream = False

Now in this case, only a player who bought ice cream will have the value of bought_ice_cream set to True. You can use this later to do things like change the dialogue based on whether the player bought an ice cream or not.

Why use default?

You might be wondering what the point of using default is to set up variables when you can also set variables using code like $ bought_ice_cream = True. For an example, consider the following:

# Version 1 (Incorrect)
label start:
    menu:
        "Go to the store":
            $ went_to_store = True
            "You went to the store."
        "Go to the park":
            $ went_to_park = True
            "You went to the park."
    "You had a nice trip."
    if went_to_store:
        "You didn't buy anything, though."
    "All in all, it was an alright day."
    return

If the player goes to the store, went_to_store is given the value True. When you get to the line if went_to_store:, since went_to_store is True, you will see the line "You didn't buy anything, though."

On the other hand, if the player goes to the park, went_to_park is given the value True. When you get to the line if went_to_storeRen’Py has not seen the variable went_to_store yet, so it causes an error (Specifically, a NameError).

A slightly improved solution might look like:

# Version 2 (Incorrect)
label start:
    menu:
        "Go to the store":
            $ went_to_store = True
            $ went_to_park = False
            "You went to the store."
        "Go to the park":
            $ went_to_park = True
            $ went_to_store = False
            "You went to the park."
    "You had a nice trip."
    if went_to_store:
        "You didn't buy anything, though."
    "All in all, it was an alright day."
    return

which would solve the issue earlier where went_to_store wasn’t a known variable for players who went to the park.

However, let’s say that you released a demo of your game which had the first code (Version 1). A player went through your game and went to the park. They then made a save file while at the line “You had a nice trip”. You inform the player that there was an error with the code and you’ve updated it to Version 2. The player updates to the new version, then loads their save game and clicks to continue. NameError: name 'went_to_store' is not defined. What happened?

Even though the player updated their code, in their save game, they’ve already passed the point where the new line $ went_to_store = False was added, so it doesn’t run and the variable still isn’t assigned a value. They run into the same issue as Version 1, but at least in this version they can begin a new game from the start and won’t get the error message.

Luckily, there’s a solution to both of these problems, and that’s default:

# Version 3 (Correct)
default went_to_store = False
default went_to_park = False
label start:
    menu:
        "Go to the store":
            $ went_to_store = True
            "You went to the store."
        "Go to the park":
            $ went_to_park = True
            "You went to the park."
    "You had a nice trip."
    if went_to_store:
        "You didn't buy anything, though."
    "All in all, it was an alright day."
    return

Now when our player loads up their save file at the line “You had a nice trip”, Ren’Py sees that this save file doesn’t have a value for went_to_store yet, so it gives it its default value of False. It does have a value for went_to_park, so it leaves that variable alone. Now when the player clicks to continue, they will skip the line "You didn't buy anything, though." since went_to_store is False and move on to the line "All in all, it was an alright day." without throwing any errors. Success!

Summary

In summary, booleans are a variable type that can be either True or False.

You will use default to set up the initial value of your variable before the game starts, and use $ to change that value during gameplay. Note that default and define go outside of labels, at something called the top level; that is, they should occur during initialization[2] and not inside of a label. So the following two are not the same:

# Correct! This is run before the game starts.
default watched_tv = False
label start:
    menu:
        "Watch TV":
            $ watched_tv = True
        "Go to sleep":
            $ watched_tv = False
    return
label start:
    # Incorrect! While Ren'Py will not
    # complain about this, this code does
    # not run in the start label.
    default watched_tv = False
    menu:
        "Watch TV":
            $ watched_tv = True
        "Go to sleep":
            $ watched_tv = False
    return

[2] Initialization refers to the period of time before the game starts when the game is getting set up. When you hit Launch Game on the Ren’Py launcher, it takes it a few seconds before your game actually opens. The main tasks performed during that time are initializing values like variables and images, loading script files and menu screens into memory to display them, etc. To initialize a variable means to give it some value during this time, as opposed to giving it a value after the game has already started.

Next Steps

Now that you’re feeling more comfortable declaring and using variables, you should have all the tools you need to move onto the next tutorial about Conditional Statements. If you’d like to read more about using default and define and how to ensure your variables are set up for the save/load system, you can read The Definitive Default Define Ren’Py Article.

Leave a Reply