If you reached this page through a search engine, you may not be viewing the documentation for the latest version of Ren'Py. Please go to the main Ren'Py page and choose "View the Ren'Py Reference Manual".

The Ren'Py Reference Manual

Last Updated: 2006-07-11 22:28

  1. A Simple Ren'Py Script
  2. Script, Line, and Block Structure
  3. Syntax Constructs
  4. Call Statement
  5. Hide Statement
  6. If Statement
  7. Image Statement
  8. Init Statement
  9. Jump Statement
  10. Label Statement
  11. Menu Statement
  12. Pass Statement
  13. Python Statement
  14. Return Statement
  15. Say Statement
  16. Scene Statement
  17. Show Statement
  18. With Statement and Clauses
  19. While Statement
  20. Starting Ren'Py
  21. Saving, Loading, and Rollback
  22. Defining Characters
  23. Text
  24. Displayables
  25. Transitions
  26. Interaction Functions
  27. Overlays
  28. Multimedia: Sound, Music, and Movies
  29. Configuration Variables
  30. Properties and Styles
  31. Text Tags
  32. SFonts
  33. Obfuscating your Game
  34. Localizing Ren'Py
  35. Changing the Keymap
  36. UI Functions
  37. Image Manipulators
  38. Low-Level Audio Functions
  39. Themes
  40. Customizing the Main and Game Menus
  41. Developer Tools
  42. Default Definitions
  43. Function Index
  44. Variable Index
  45. Property Index
  46. Style Index
  47. Style Hierarchy
  48. Definition Index
  49. Example Script

Ren'Py is a programming language and runtime, intended to ease the creation of visual-novel type games. It contains features that make it easy to display thoughts, dialogue, and menus; to display images to the user; to write game logic; and to support the saving and loading of games. Ren'Py tries to be like an executable script, allowing you to get a working game without much more effort than is required to type the game script into the computer.

Ren'Py is implemented on top of Python, and that python heritage shows through in many places. Many Ren'Py statements allow Python expressions to be used, and there are also Ren'Py statements that allow for the execution of arbitrary python code. Many of the less-used features of Ren'Py are exposed to the user by way of Python. By only requiring use of the simplest features of Python, it's hoped that Ren'Py will be usable by all game authors.

A Simple Ren'Py Script

The following is a simple but complete Ren'Py script. The colors are added to make it easier to read, and aren't part of the script proper.

init:
    image bg whitehouse = "whitehouse.jpg"
    image eileen happy = "eileen_happy.png"
    image eileen upset = "eileen_upset.png"
    $ e = Character('Eileen')

label start:

    scene bg whitehouse
    show eileen happy

    e "I'm standing in front of the White House."

    show eileen upset

    e "I once wanted to go on a tour of the West Wing, but you have to
       know somebody to get in."

    "For some reason, she really seems upset about this."

    e "I considered sneaking in, but that probably isn't a good idea."

This example, shows many aspects of a Ren'Py script. The first four lines of the script serve to load in three images. After the label indicating the start of the game, a character is declared. The script then proceeds to display a picture of a character on top of a background image, and to have the character say two lines of dialogue, changing her picture in between. The POV character then thinks a line of dialogue, before the character says her final line.

We'll go into detail into what each of the statements here does over the course of this tutorial. For now, however let me just point out that the first 6 statements initialize the game, while the last 7 (starting with "scene") show images and display dialogue. As such, the bulk of a game is more like the last 7 then the first 6.

Of particular note is that a keyword isn't required to introduce dialogue. This allows visual novels consisting mostly of dialogue to be expressed in a concise form.

The Ren'Py Language

This section describes the Ren'Py language, and the functions found in that language.

Script, Line, and Block Structure

Ren'Py scripts consist of one or more .rpy files. These script files may be read in any order, and all of them together make up a Ren'Py script. Please see ''TODO'' for information about where Ren'Py searches for .rpy files.

Each of these files is divided into a series of logical lines. The first logical line of a file begins at the start of a file, and another logical line begins after each logical line ends, until the end of the file is reached. By default, a logical line is terminated by the first newline encountered. However, a line will not terminate if any of the following are true:

Ren'Py script files also can include comments. A comment begins with a hash mark that is not contained within a string, and continues to, but does not include, the next newline character. Some examples are:

# This line contains only a comment.
scene bg whitehouse  # This line contains a statement as well.

If, after eliminating comments, a logical line is empty, that logical line is ignored.

Logical lines are then combined into blocks. Two logical lines are in the same block if the lines have the same indentation preceding them, and no logical line with a lesser amount of indentation occurs between the two lines. Indentation may only consist of spaces, not tabs. In the following example:

line 1
    line a
    line b
line 2
    line c
    line d

In this example, here are three blocks. One block contains lines 1 and 2, another lines a and b, and the third contains lines c and d. This example can also serve to illustrate the concept of a block associated with a line. A block is associated with a line if the block starts on the next logical line following the line. For example, the block containing lines a and b is associated with line 1.

There are three kinds of blocks in an Ren'Py program. The most common is a block containing Ren'Py statements. Blocks may also contain menuitems or python code. The top-level block (the one that contains the first line of a file) is always a block of Ren'Py statements.

Syntax Constructs

Before we can describe Ren'Py statements, we must first describe a number of syntactic constructs those statements are built out of. In this subsection, we describe such constructs.

Keywords are words that must literally appear in the source code. They're used ito introduce statements, or to delimit parts of statements. You'll see keywords throughout the descriptions of statements. In grammar rules, keywords are in quotes. The keywords used by Ren'Py are:

at
call
elif
else
expression
hide
if
image
init
jump
label
menu
onlayer
pass
python
return
scene
set
show
with
while

A name consists of a letter or underscore (_) followed by zero or more letters, numbers, or underscores. For this purpose, unicode characters between U+00a0 and U+fffd are considered to be letters. A name may not be a keyword.

A simple_expression is a python expression that starts with a name, a string, or any python expression in parenthesis. This may be followed by any number of the following:

A python_expression is an arbitrary python expression that may not include a colon. These expressions are generally used to express the conditions in the if and while statements.

An image_name consists of one or more names, separated by spaces. The first name in an image_name is known as the image_tag.

image_spec -> image_name ( "onlayer" name) ( "at" transform_list )? ( "with" simple_expression )?

An image_spec consists of an image name, optionally an `onlayer` keyword, optionally an `at` clause followed by a comma-separated list of simple_expressions that evaluate to functions that transform displayables to displayables, and optionally a `with` clause.

Grammar Rules. We will be giving grammar rules for some of the statements. In these rules, a word in quotes means that that word is literally expected in the script. Parenthesis are used to group things together, but they don't correspond to anything in the script. Star, question mark, and plus are used to indicate that the token or group they are to the right of can occur zero or more, zero or one, or one or more times, respectively.

If we give a name for the rule, it will be separated from the body of the rule with a crude ascii-art arrow (->).

Call Statement

The call statement is used to transfer control to the statement with the given name. It also pushes the name of the statement following this one onto the call stack, allowing the return statement to return control to the statement following this one.

call_statement -> "call" name ( "from" name )?
call_statement -> "call" "expression" simple_expression ( "from" name )?

If the expression keyword is present, the expression is evaluated, and the string so computed is used as the name of the statement to call. If the expression keyword is not present, the name of the statement to call must be explicitly given.

If the optional from clause is present, it has the effect of including a label statement with the given name as the statement immediately following the call statement. An explicit label is required here to ensure that saved games with return stacks can return to the proper place when loaded on a changed script. From clauses should be included for all calls in released games.

As from clauses may be distracting when a game is still under development, we provide with Ren'Py a program, called add_from, that adds from clauses to all bare calls in any game directory. It can be found in tools/add_from, although it needs to be run from the base directory. The easiest way to do this on windows is by running tools/game_add_from.bat. It should be run before a final release of your game is made. Be sure to make a backup of your game directories before running add_from. Also note that add_from produces .bak files for all files it can change, so delete them when you're satisfied that everything worked.

e "First, we will call a subroutine."

call subroutine from _call_site_1

# ...

label subroutine:

    e "Next, we will return from the subroutine."

    return

Hide Statement

The hide statement is used to hide an image from the screen, based on a supplied image_spec.

hide_statement -> "hide" image_spec

A hide statement operates on the layer supplied in the onlayer clause of the image_spec, defaulting to "master" if no such clause has been supplied. It finds an image beginning with the image tag of the image name in the image_spec, and removes it from that layer.

Please note that the hide statement is rarely used in practice. Show can be used by itself when a character is changing emotion, while scene is used to remove all images at the end of a scene. Hide is only necessary when a character leave at the end of a scene.

If Statement

The if statement is used to conditionally execute a block of statements.

if_statement -> "if" python_expression ":"
elif_clause -> "elif" python_expression ":"
else_clause -> "else" ":"

The if statement is the only statement which consists of more than one logical line in the same block. The initial if statement may be followed by zero or more elif clauses, concluded with an optional else clause. The expression is evaluated for each clause in turn, and if it evaluates to a true value, then the block associated with that clause is executed. If no expression evaluates to true, then the block associated with the else clause is executed. (If an else clause exists, execution immediately continues with the next statement.) In any case, at the end of the block, control is transferred to the statement following the if statement.

if points >= 10:

   e "Congratulations! You're getting the best ending!"

elif points >= 5:

   e "It's the good ending for you."

else:

   e "Sorry, you're about to get the bad ending."

Image Statement

The image statement is used to declare images to Ren'Py. Image statements can only appear in init blocks.

image_statement -> "image" image_name "=" python_expression

An image statement binds an image name to a displayable. The displayable is computed by the supplied python expression, with the result of the expression being passed to the im.Image function in loose mode. This means that if the assignment is a single string, it is interpreted as an image filename. Displayables are passed through unmolested. Once an image has been defined using an image statement, it can be used by the scene, show, and hide statements.

init:
    image eileen happy = "eileen/happy.png"
    image eileen upset = "eileen/upset.png"

Init Statement

The init statement is used to execute blocks of Ren'Py statements before the script executes. Init blocks are used to define images and characters, to set up unchanging game data structures, and to customize Ren'Py. Code inside init blocks should not interact with the user or change any of the layers, and so should not contain say, menu, scene, show, or hide statements, as well as calls to any function that can do these things.

init_statement -> "init" (number)? ":"

An init statement is introduced with the keyword init, followed by an optional priority number, and a mandatory colon. If the priority is not given, it defaults to 0.

The priority number is used to determine when the code inside the init block executes. Init blocks are executed in priority order from low to high. Within a file, init blocks with the same priority are run in order from the top of the file to the bottom. Between files, the order of evaluation of priority blocks is undefined.

The init blocks are all run once, during a special init phase. When control reaches the end of an init block during normal execution, execution of that block ends. If an init statement is encountered during normal execution, the init block is not run. Instead, control passes to the next statement.

Jump Statement

The call statement is used to transfer control to the statement with the given name.

jump_statement -> "jump" name 
jump_statement -> "jump" "expression" simple_expression 

If the expression keyword is present, the expression is evaluated, and the string so computed is used as the name of the statement to jump to. If the expression keyword is not present, the name of the statement to jump to must be explicitly given.

Unlike call, jump does not push the target onto any stack. As a result, there's no way to return to where you've jumped from.

label loop_start:

e "Oh no! It looks like we're trapped in an infinite loop."

jump loop_start

Label Statement

Label statements allow a name to be assigned to a program point. They exist solely to be called or jumped to, whether by script code or the Ren'Py library.

label_statement -> "label" name ":"

A label statement may have a block associated with it. In that case, control enters the block whenever the label statement is reached, and proceeds with the statement after the label statement whenever the end of the block is reached.

Menu Statement

Menus are used to present the user with a list of choices that can be made. In a visual novel, menus are the primary means by which the user can influence the story.

menu_statement -> "menu" ( name )? ":"

A menu statement is inroduced by the keyword "menu", an optional name, and a colon. If the name is supplied it's treated as a label for this menu statement, as if the menu statement was preceded by a label statement.

A menu statement must have a block associated with it. This is a menuitem block that must contain one or more menuitems in it. There are several kinds of menuitems that can be contained in a menuitem block.

caption_menuitem -> string

The first kind of menuitem is a string. This string is placed into a menu as a caption that cannot be selected. In general, captions are used to indicate what the menu is for, especially when it is not clear from the choices.

choice_menuitem -> string ( "if" python_expression )? ":"

The second kind of menuitem gives a choice the user can make. Each choice must have a block of Ren'Py statements associated with it. If the choice is selected by the user, then block of statements associated with the choice is executed. A choice may also have an optional if clause that includes a python expression. This clause gives a condition that must be satisfied for the choice to be presented to the user. A terminating colon is used to indicate that this menuitem is a choice.

with_menuitem -> "with" simple_expression

The final kind of menuitem is a with clause. Please see Transitions for more information on with clauses.

menu what_to_do:

    "What should we do today?"

    "Go to the movies.":
        "We went to the movies."

    "Go shopping.":
        "We went shopping, and the girls bought swimsuits."
        $ have_swimsuits = True

    "Go to the beach." if have_swimsuits:
        "We went to the beach together. I got to see the girls in their
         new swimsuits."

Details. When a menu is to be shown to the user, the first thing that happens is that a list of captions and choices is built up from the menuitems associated with the menu. Each of the choices that has an expression associated with it has that expression evaluated, and if not true, that choice is removed from the list. If no choices survive this process, the menu is not displayed and execution continues with the next statement. Otherwise, the menu function is called with the list of choices, displays the menu to the user, and returns a chosen choice. Execution continues with the block corresponding to the chosen choice. If execution reaches the end of that block, it continues with the the statement after the menu.

Pass Statement

The pass statement does not perform an action. It exists because blocks of Ren'Py statements require at least one statement in them, and it's not always sensible to perform an action in those blocks.

pass_statement -> "pass"
menu:
    "Should I go to the movies?"

    "Yes":
        call go_see_movie

    "No":
        pass

"Now it's getting close to dinner time, and I'm starving."

Python Statement

The python statement allows one to execute python code in a Ren'Py script. This allows one to use python code to declare things to Ren'Py, to invoke much of Ren'Py's functionality, and to store data in variables that can be accessed by user code. There are two forms of the python statement:

python_statement -> "$" python_code
python_statement -> "python" ( "hide" )? ":"

The first form of a python consists of a dollar sign ($) followed by python code extending to the end of the line. This form is used to execute a single python statement.

A second form consists of the keyword python, optionally the keyword hide, and a colon. This is used to execute a block of python statements, which must be supplied as a block after this statement. Normally, python statements execute in a script-global namespace, but if the hide keyword is given, a new namespace is created for this block. (The script-global namespace can be accessed from the block, but not assigned to.)

$ score += 1

python:
    ui.text("This is text on the screen.")
    ui.saybehavior()
    ui.interact()

Return Statement

The return statement pops the top location off of the call stack, and transfers control to it. If the call stack is empty, the return statement performs a full restart of Ren'Py.

return_statement -> "return"

Say Statement

The say statement is used to present text to the user, in the form of dialogue or thoughts. Since the bulk of the of the content of a script will be dialogue or thoughts, it's important that the say statement be as convenient as possible. Because of this, the Say statement is the only statement that is not delimited with a keyword or other form of delimiter. Instead, it consists of a string, with an optional simple_expression before it to designate who is doing the speaking, and an optional with clause after it used to specify a transition.

say_statement -> ( simple_expression )? string ( "with" simple_expression )?

There are two forms of the say statement, depending on if the spimple expression is provided. The single-argument form consists of a single string (with or without the optional with clause). This form causes the string to be displayed to the user as without any label as to who is saying it. Conventionally, this is used to indicate pov character thoughts or narration.

"I moved to my left, and she moved to her right."

"So we were still blocking each other's path."

"I then moved to my right, and at the same time she moved to her
 left."

"We could be at this all day."

The two-argument form of the say statement consist of a simple_expression, a string, and optionally a with clause. This form of the statement is used to indicate dialogue. The first argument is expected to be an object (usually a Character or DynamicCharacter object) that knows how to show dialogue to the user. The string is then passed to that object, which is responsible for showing it to to the user.

The simple_expression can also be a string, rather than an object. Strings are used directly as the name of the character.

"Girl" "Hi, my name is Eileen."

e "Starting today, I'll be living here."

Details. The two-argument say statement first evaluates the supplied simple expression. It then attempts to call that value (the who value) with the string giving the line of dialogue (the what string). If it can do so, it's finished, as the object that is called is responsible for interacting with the user.

If it can't call the value of the expression, then it calls the say function with the who value and the what string. The say function is then responsible for showing the dialogue to the user.

The single-argument form of the expression simply calls the special function (or object) narrator with the string to be shown. This function is responsible for showing the string to the user. Character and DynamicCharacter objects are suitable for use as the narrator.

The with clause is used to specify a transition, see With Statement and Clauses for details.

Scene Statement

The scene statement clears a layer by removing all images from it. It may then show a supplied image to the user. This makes it appropriate for changing the background of a scene.

scene_statement -> "scene" ("onlayer" name | image_spec )?

The scene statement first clears out all images from a layer. The layer is taken from the image_spec or onlayer clause, if present. The "master" layer is used if no other layer is specified.

If an image_spec is present, it is then added to the layer, as with the show statement.

By default, no background is added to the screen, so we recommend that every script begin with a scene statement that shows a full-screen background to the user.

Show Statement

The show statement takes an image specifier, and adds the specified image to the specified layer, with the "master" layer used if no onlayer clause is present.

show_statement -> "show" image_spec

The show statement first finds a displayable to add to the screen. This is done by looking up the image name in the list of registered images. It then applies all transformations into the at list to the displayable. This yields the image to be added to the layer. The show statement then checks to see if an image beginning with the same image tag can be found in the layer. If such an image exists, it is replaces with the new image. Otherwise, the new image is added to the layer, in a position that makes it closer to the user than any other image.

scene living_room
show eileen happy at left

e "I'm feeling happy right now."

show eileen upset at left

e "But sometimes, I can get upset for no good reason."

With Statement and Clauses

The with statement and with clauses are used to show transitions to the user. These transitions are always from the last screen shown to the user to the current screen. At the end of a with statement, the last screen shown to the user is set to the current screen. The last screen shown to the user can also be updated by say or menu statements, as well as by python code.

The with statement has the form:

with_statement -> "with" simple_expression

The simple_expression is expected to evaluate to a transition function. If it evaluates to the value None, the last screen shown to the user is updated to the current screen, without performing a transition. This is useful to remove transient interface items (like a prior say statement) from partaking in a transition.

For convenience, a number of statements support with clauses. In the case of the scene, show, and hide statements, the with clause is equivalent to placing a "with None" statement before the scene, show or hide statement, and a "with transition" statement after it. For example, the statement:

show eileen happy with dissolve

is equivalent to:

with None
show eileen happy
with dissolve

This behavior can lead to undesired side-effects. The code:

show bg whitehouse with dissolve
show eileen happy with dissolve

will cause two transitions to occur. To ensure only a single transition occurs, one must write:

with None
show bg whitehouse
show eileen happy
with dissolve

With clauses can also be applied to say and menu statements. In this case, the transition occurs when the dialogue or menu is first shown to the user.

For pre-defined transition functions that can be used in any script, see ''TODO''. For functions that return transition functions, see ''TODO''.

While Statement

The while statement is used to execute a block of Ren'Py statement while a condition remains true.

while_statement -> "while" python_expression ":"

When a while statement is executed, the python expression is evaluated. If it evaluates to true, control is transferred to the first statement in the block associated with this while statement. If false, control is instead sent to the statement following the while statement.

When control reaches the end of the block associated with the while statement, it returns to the while statement. This allows the while statement to check the condition again, and evaluate the block if the condition remains true.

while not endgame:

   "It's now morning. Time to get up and seize the day."

    call morning
    call afternoon
    call evening

    "Well, time to call it a night."

"Now it's time to wake up and face the endgame."

The Ren'Py Runtime Environment

Starting Ren'Py

Setting Up Paths

Game Directory. The first thing Ren'Py does when it is started is to find the game directory. To do this, it finds a directory using the following rules:

  1. If a game directory is passed to Ren'Py explicitly using the --game command line option, that directory is used.
  2. Ren'Py uses the name of the executable (.py or .exe file) that was used to start Ren'Py. The executable is stripped of any prefix before and including the first underscore, and any extension after the first dot. If a directory with the remaining name is found underneath the directory containing the executable, that directory is used. (For example, if the executable name is "run_moonlight.exe", we will check for the existence of the "moonlight" directory.)
  3. If a directory with the name "game" is found under the directory containing the executable, that directory is used.
  4. If a directory with the name "data" is found under the directory containing the executable, that directory is used.
  5. If no other directory has been found, the directory contaning the executable is used as the game directory.

Presplash Image. Ren'Py next checks to see if the file "presplash.png" is present in the game directory. If this file is present, it is shown to the user, in its own window, until just after the init code has finished running. The size of the window is determined by the size of the presplash image. Ren'Py attempts to center this window on the screen, and to show the window without a title bar.

Searchpath. Ren'Py then sets up the search path to include the game directory and the directory named 'common' underneath the directory containing the executable. The searchpath is the path script and data files are loaded from. This path can be modified by changing config.searchpath, but only after the script has been loaded.

Default Archives. Ren'Py nexts attempts to add some default archives files. These are files Ren'Py will search in order to find script and data files. There are three archive files Ren'Py will add by default. The first uses the name of the executable used for to start Ren'Py, stripped of any prefix before and including the first underscorte, and any extension after the first dot, with ".rpa" appended to it. The other two files are "game.rpa" and "data.rpa". If these files exist in a directory in the search path, they are added to config.archives, the list of archives Ren'Py will search for script and data files.

Loading Scripts

Once the paths have been setup, Ren'Py attempts to process all of the .rpy and .rpyc files that are found in the searchpath and default archives. The script is contained in these .rpy and .rpyc files, with a .rpy file containing a textual representation of a part of the script, and a .rpyc file containing a serialized representation of a similar part of the script. If a .rpy and .rpyc file exist in the same directory with the same name (differing only in extension), the newer of the pair of files is loaded. When a .rpy file is loaded, the corresponding .rpyc file is written out to disk with the serialized representation of the file. As parsing a .rpy file is expensive, producing a .rpyc file can save a significant amount of time. As there's no place to write the corresponding .rpyc file to, .rpy files may not be loaded from archives.

Once the script has been loaded, Ren'Py must find or generate bytecode for all python blocks in the script. This is first done by loading in the file bytecode.rpyb, if it exists. It may be loaded from disk, or from inside one of the default archives. For each python block, bytecode.rpyb is searched for bytecode generated from that block for the current version of python. If such bytecode cannot be found, that block is compiled from the python source contained in the script. If any compilation was necessary, a new version of bytecode.rpyb is written into the game directory. To prevent bytecode compilation from occuring when a user starts your game, bytecode.rpyb should be shipped as part of the game.

Initialization

After the script has been loaded, Ren'Py can begin executing init blocks. All init blocks found in the script are run, in an order subject to the following two rules.

  1. Init blocks with a lower priority number are run before init blocks with a higher priority number. (Note that init blocks with no explicitly specified priority are assumed to have a priority of 0.)
  2. Within a file, init blocks of the same priority are run in a top-to-bottom order.

Note that we do not specify an ordering of init blocks of the same priority defined in multiple files.

The Ren'Py statements in init blocks should not try to display images, or interact with the user, as the display will not yet be initialized, and such interadction will not work.

Running Game Code

After the last init block has finished running, the display is initialized, and running normal game code can be run. It is at this time that the presplash is removed, if it has been shown.

The first time normal game code is run, the Ren'Py library calls the label splashscreen, if it exists. The code at this label can be used to show a series of in-game splashscreens to the user when the game is first loaded. When the code returns, execution proceeds.

The next thing Ren'Py does is to call the label main_menu, if it exists. If it exists, the main_menu label is called in a new context, and is responsible for showing the main menu to the user. If the main_menu label does not exists, control is transferred to the _library_main_menu label, which shows the default main menu.

While this main menu can be customized (see Customizing Menus for details), the default main menu includes an entry, "Start Game", that causes an out-of-context jump to the label start. Therefore, it's conventional for the execution of a game to start at the label start, which is expected to be defined by the writer of the script.

The main menu and game menu execute in a different context from the main game. (The context is used to determine the current location in the script for saving and loading purposes, among other things.) Because of this, the Ren'Py jump statement cannot be used to jump to a location in the script from the main menu. Instead, a python statement should be used to call renpy.jump_out_of_context. Alternatively, executing a return statement in the main menu function will cause execution of the game proper to begin at the "start" label. So the following code:

label main_menu:
    return

will cause execution to begin immediately, skipping the game menu entirely.

Saving, Loading, and Rollback

Ren'Py supports saving a game to disk, loading that game back in from disk, and rolling back the game to a previous state. As these actions share infrastructure, we will discuss them all in this section, paying attention to what is required to support loading of a saved game when a script changes between saving and loading.

Please note that save-game compatibility is not guaranteed between releases of Ren'Py, even between older and newer releases of Ren'Py. It may be necessary to take this into account when releasing a game with an updated version of Ren'Py.

Saving, Loading, and Rollback can all be seen as operations that affect the game state. Saving is an operation that persists the game state out to disk, Loading consists of restoring the game state from disk, and Rollback reverts the game state to what it was at a previous point in time. This game state consists of two parts: The user state consists of variables and objects that have been changed by the user, while the internal state consists of information used by Ren'Py directly.

Internal State. Specifically, the internal state of Ren'Py consists of the following:

These items are automatically saved, loaded, and rolled back when the appropriate commands are invoked by the user. You do not need do anything for this state to be handled, and there is no way to prevent these things from being saved.

User State. The other kind of state that Ren'Py can save and restore is user state. User state consists of all variables that have been changed after the end of the init phase, and all objects transitively reachable from such variables.

It's important to clarify what it means for a variable to be changed. In Python and Ren'Py, variables reference objects. A variable changes when it is updated to reference a new object. A variable does not change when the object it references changes.

For example, in the following code:

init:
      $ a = 0
      $ state = object()

$ a = 1
$ b = [ ]
$ state.love_love_points = a + 1

In this example, the variables a and b are changed by the code outside of the init block (assuming that code executes), while state is not changed. In the code outside of the init block, a is assigned a different integer object, while b is assigned a new empty list. While a field on the object state refers to has changed, state itself still refers to the same object, and not considered to have changed. (Hence, state and its associated object are not considered part of user state.)

User state is gathered by first finding all variables that have changed outside of init blocks. Ren'Py then finds all objects reachable from one of those variables through some combination of field access, iteration, or iteration over items (as in a dictionary). This combination of variable and object values comprises the user state.

It's important to ensure that every object in the user state can be pickled (serialized) by the python pickle module. Most python constructs can be pickled, including booleans, integers, floating-point numbers, strings, lists, tuples, dictionaries, and most objects. You can also refer to your own classes and functions, provided that they are defined in a python block (not a python hide block) inside an init block, and always exist with the same name in later versions of the script. There are some python objects that cannot be pickled, such as files, iterators, and generators. These objects should not be used outside of python hide blocks.

While these rules may seem to be complex, it's hoped that in practice they can be reduced to a simple heuristic: Any variable changed outside of an init block, and any object reachable from such a variable, will be saved, loaded, and rolled back properly.

State that isn't Saved. There is some state kept by Ren'Py that is not part of the interpreter state. This includes:

As a result, config variables, library variables, and styles should be set up in init blocks, and then left alone for the rest of the game. As the image statement can only be run from inside an init block, it is impossible to set up a mapping from image name to displayable outside of an image block. To ensure compatability between script version, once an image name or style is present in a released version of the game, it should be present in all future released versions of the game.

Details. As the game is played, Ren'Py logs all changes to user and interpreter state. When the game is saved, it writes this log out to disk, alongside the current state. When the game is loaded back in, the variables are reset to what the were when the init code in the current version of the script finished running. The saved user state is then merged with this, with saved user state overriding any variable that was also assigned in the init code. Finally, a rollback is triggered.

The rollback that is triggered on load ends when it can find a statement that has the same name as it had when it was encountered in the log. When the script hasn't changed, all statements have the same name, so the effect of the rollback is to bring control back to the start of the statement that was executing when the user saved. When the script has changed, however, the only statements that retain their names are statements that have an explicit name specified. (These statements are labels, menu statements with an explicit name, and call ... from ... statements.) The game will rollback to the start of the most recent statement that exists in both the old and new games.

When a rollback occurs, both user and interpreter state are restored to what they were when the statement that is being rolled back to began executing. The statement is then executed again, and play continues normally.

Please note that we can only roll back the current statement, and not the return sites listed on the return stack. If the name of a return site changes, we will not be able to return from a procedure call, and the script will crash. If a return site has an explicit name, however, that name is returned to even if the script change. Because of this, it's important that every call site in a released game have a from clause associated with it, giving a name for the return site that can appear in both old scripts.

Finally, if allowed, rollback can be invoked explicitly by the user. When such a rollback occurs, we first look for a previous statement that is a checkpoint (checkpoints are say and menu statements, as well as python blocks that called renpy.checkpoint. Once a checkpoint is found, we look for a statement which has a name that exists in the current script (this is normally the same statement). We then rollback to that statement and begin executing again.

What this means is that when a rollback occurs, the game is usually reverted to the start of the say or menu statement that executed before the currently executing statement.

There is one variable that controls the behavior of loading and saving:

save_name = ''

This is a name that will be associated with save files. It's expected that the game will update this on a regular basis with the name of the section of the script that is currently executing. When a save file is shown to the user, this name will be shown with it. Alternatively, never change this and no save name will be shown.

There is one label associated with loading:

label after_load:

If the after_load label exists, then it is called after a load has occured. It is responsible for updating variables that may have changed between script versions, and performing any other action that may need to be taken in response to the load. When a return statement is executed, execution is transferred to the point where the game was saved.

Please note that when calling after_load, the return stack is not safe, and hence the user should not be allowed to save before control returns from after_load. To be safe, this means the after_load code should not be interactive.

Persistent Data

Ren'Py als supports persistent data, which is saved data that is not associated with a single game. Persistent data is data that is accessed through the fields of the persistent object, which is bound to the variable persistent.

persistent = ...

The persistent variable is bound to the special persistent object. All data reachable through fields on persistent is saved whenver Ren'Py terminates, and loaded when Ren'Py resumes. The persistent object is special in that an access to an undefined field on it will have a None value, rather than causing an exception.

An example use of persistent is the creation of an unlockable image gallery. This is done by storing a flag in persistent that determines if the gallery has been unlocked, as in:

label gallery:

    if not persistent.gallery_unlocked:
        show background
        centered "You haven't unlocked this gallery yet."
        $ renpy.full_restart()

    # Actually show the gallery here.

When the user gets an ending that causes the gallery to be unlocked, the flag must be set to True:

$ persistent.gallery_unlocked = True

Please note that a more sophisticated image gallery ships in the extras/ directory with Ren'Py.

Defining Characters

When showing dialogue to the user using the two-argument form of the say statement, the first argument to the say statement should almost always be a variable bound to a Character object. These objects implement (or call functions that implement) much of the logic required to show dialogue to the user.

Characters are declared by binding variables to the Character objects. Such declarations should take place inside init blocks, to ensure that the bindings are not saved with the game state, as this would prevent revised versions of a game from picking up changes to the init block. Perhaps the simplest definition is:

init:
    $ e = Character("Eileen")

This creates a new character object and binds it to the e variable. When the say statement:

e "Hello, World!"

runs, the line of text "Hello, World!" will be preceded by the label "Eileen", indicating who is talking. It's common to customize the color of this label. This can be done by supplying the color keyword argument to Character, as in:

init:
    $ e = Character("Eileen", color=(200, 255, 200, 255))

The color argument is actually setting the color property on the label. The color property takes an RGBA tuple consisting of four numbers, enclosed in parenthesis and separated by commas, with each number ranging from 0 to 255.

The Character function is defined as follows:

Character (name, **kwargs):

Creates a new character object. This object is suitable for use as the first argument of a two-argument say statement. When it is used as such, it shows a window containing the character name and the second argument to the say statement. This behavior is customized by passing parameters to this function.

name is the name of the character that is speaking. It can be either a string containing the character name, or None to indicate that the label should not be shown. The empty string "" indicates that the label should be blank line, which allows a narrator character to line up narration with character dialogue. name is the only requirement to Character.

Keyword Arguments. In addition to name, Character takes keyword arguments that control its behavior.

dynamic - If true, then name is interpreted as a string containing a python expression that is evaluated to yield the name of the character.

image - If true, then name is interpreted as an image. This image is added to the dialogue window in place of the label.

condition - If present, this should be a string containing a python expression. This expression is evaluated whenever a line is said through this character object. If it evaluates to false, the line is not shown to the user.

interact - If true, the default, causes an interaction to occur when a line is shown to the user. If false, the interaction does not take place, and ui.interact (or some other means) must be called to cause an interaction to occur.

Prefixes and Suffixes. The following keyword arguments can be used to add a prefix or suffix to everything said through a character object. These can be used when lines of dialogue need to be enclosed in quotes, as the preferred alternative to adding those quotes to every line of dialogue in the script.

who_prefix - Text that is prepended to the name of the character when forming the label of the dialogue.

who_suffix - Text that is appended to the name of the character when forming the label of the dialogue.

what_prefix - Text that is prepended to the line of dialogue before it is shown to the user.

what_suffix - Thext that is appended to the line of dialogue before it is shown to the user.

Click-to-continue. These keyword arguements are used to control the click-to-continue indicator:

ctc - If present, this argument takes a displayable that is used as the click-to-continue indicator. If not present or None, then no click-to-continue indicator is displayed.

ctc_position - If "nestled", the click-to-continue indicator is displayed nestled in with the end of the text. If "fixed", the click-to-continue indicator is displayed directly on the screen, with its various position properties determining where it is actually shown.

Functions. The following are keyword that allow one to massively customize the behavior of a character object:

show_function - The function that is called to display each step of a dialogue to the user. (A dialogue may be broken down into steps by pause text tags.) It should have the same signature as renpy.show_display_say.

predict_function - The function that is called to predict the images from this dialogue. It should have the signature of renpy.predict_display_say.

Styles. The following keyword arguments control the styles used by parts of the dialogue:

who_style - Defaults to 'say_label', the style of the label.

what_style - Defaults to 'say_dialogue', the style of the text being said.

window_style - Defaults to 'say_window', the style of the window containing the dialogue.

Additional Keyword Arguments. Additional keyword arguments are interpreted as follows:

There is also a DynamicCharacter function:

DynamicCharacter (name, **kwargs):
Equivalent to calling Character with the same arguments, and with the dynamic argument set to true.

Calling Character Objects. Character objects may be called directly, as if they were functions. They take one positional parameter, the line of dialogue to be show to the user. They also take one keyword parameter, interact, which determines if an interaction should take place. This use can programatically replace say statements. For example, the say statement:

e "Hello, World!"

is equivalent to:

$ e("Hello, World!")

Text

This section covers aspects of text in Ren'Py. It first covers interpolation, supported by the say and menu statements, which allows values to be substituted into text. It next discusses text tags, which allow the style of portions of strings of text to be customized. Finally, it covers how Ren'Py handles fonts.

Interpolation

Interpolation is supported by the say and menu statements. These statements support python string interpolation over the contents of the store. The strings used by the statements support conversion specifiers of the form %(variable)s, where variable is the name of a variable and s is a conversion. Useful conversions include 's', which interpolates a string; 'd', which interpolates an integer; and 'f', which interpolates a floating point number. Conversions may also include characters that modify how the string is converted. More information about conversions can be found at http://www.python.org/doc/2.3.5/lib/typesseq-strings.html.

In strings where interpolation is supported, percent characters (%) must be duplicated (to %%) to prevent them from being interpreted as introducing interpolation.

$ name = 'Samantha'
$ age = 19
$ withyou = 110

girl "My name is %(name)s, and I am %(age)d years old. I'm with you %(withyou)d%%"

When interpolation is not supported, the effect can often be faked by formatting a string against the result of calling the globals() function.

ui.text("%(name)s's Vital Statistics" % globals())

Text tag processing is performed after interpolation, so it's important to ensure interpolation does not introduce text tags.

Text Tags

Text displayed by Ren'Py supports text tags. While styles can only be applied to an entire Text displayable, allow only a portion of the text in the displayable to be customized. As text tags are part of the Text displayable, they may be used in any string that is displayed on the screen. However, some of the text tags will only have effect if used in the appopriate context.

Text tags should be used fairly sparingly. If you find you're using text tags on every line of the game, it's quite possible text tags are not the right solution for the problem at hand. Investigate text styles as a possible alternative to text tags.

Text tags start with a left brace ({}, and continue to the matching right brace (}). Immediately following the left brace is the tag name. The name may be followed by an argument, which is separated from the tag name by an equals sign (=). Some tags require an argument, while others require that the argument be omitted. Text tags are sensitive to case and white space.

Some tags require a corresponding closing tag. A closing tag is any text tag where the name begins with a slash (/). Closing tags should be properly nested: "{b}{i}this is okay{/i}{/b}", while "{b}{i}this is wrong{/b}{/i}". While improper nesting of text tags will generally not cause an error, this problem may cause undesirable rendering results. The text between a tag and the corresponding closing tag is called the enclosed text. All tags must be closed by the end of the text string.

To include a single left brace in text, two left braces ({{) musty be included instead.

Ren'Py supports the following text tags:

When a a hyperlink is clicked, the config.hyperlink_callback function is called with the text of the argument of the hyperlink. The default hyperlink handler interprets argument as a label, and calls this label in a new context. This is an appropriate behavior when using hyperlinks to definitions of unfamiliar terms. Hyperlinks should not be used as a general control-flow tool, as they transfer control to a new context when clicked. If the user saves while inside that context, when he loads the game he will be returned to the screen containing the hyperlink.

init:
    $ definition = Character(None, window_yfill=True, window_xmargin=20, 
                             window_ymargin=20, window_background=Solid((0, 0, 0, 192)))

label start:

    "A game that instructs on how to make a game? Isn't that a sort of {a=define_quine}Quine{/a}?"

    # ...

label define_quine:

    definition "Quine:\n\nA program that prints itself to its output."

    return

The following is an example of a say statement that uses many text tags. Use of this many text tags is not recommended in a high-quality game.

"Using text tags, we can make text {size=+12}bigger{/size} or
 {size=-8}smaller{/size}. We can make it {b}bold{/b}, {i}italic{/i},
 or {u}underlined{/u}. We can even change its {color=#f88}color{/color}."

Fonts and SFonts

The Text displayable attempts to find an an appropriate font using information about the font name, boldness, italics, underline and size. This information is supplied to the Text displayable using style properties, but may then be modified using text tags. Ren'Py translates this into a font using the following algorithm.

The truetype font loading code will automatically scale, bold, italicize, and underline the font as required.

For best results, fonts should be truetype files that ship with the game. This ensures that required fonts are always present on the user's system.

SFonts. Ren'Py supports rendering text using SFonts as well as TrueType fonts. An SFont is a properly prepared image file, usually a PNG, containing images of the character in the font. Ren'Py has its own implementation of SFonts that supports an arbitrary unicode character set and kerning.

SFonts have several advantages and several disadvantages. One of the advantages is that SFonts are bitmap-based. This allows them to be distributed without having to worry about the copyrights associated with TrueType fonts. Also, as SFonts are images, it's possible to apply effects to them that Ren'Py would not otherwise support. The downsides of SFonts come from the fact that Ren'Py doesn't render them, but instead merely copies characters out of them. Because of this, one needs to supply another image to Ren'Py if one wants the font to be scaled, made bold, made italic, or underlined. Ren'Py will recolor the SFont, with white being mapped to the supplied color, and other colors interpolated on a channel-by-channel basis.

For more information about SFonts, see http://www.linux-games.com/sfont/.

To use SFonts, they must first be registered with Ren'Py using the renpy.register_sfont function. They can then be used by setting the font property of a style to the name of the SFont.

renpy.register_sfont (name=None, size=None, bold=False, italics=False, underline=False, filename=None, spacewidth=10, default_kern=0, kerns={}, charset=u'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'):

This registers an SFont with the given details. Please note that size, bold, italic, and underline are all advisory (used for matching), and do not change the appearance of the font.

name - The name of the font being registered. size - The size of the font being registered. bold - The boldness of the font being registered. italics - The italicness of the font being registered. underline - The underline of the font being registered.

filename - The file containing the sfont image. spacewidth - The width of a space character. default_kern - The default kern spacing between characters. kerns - A map from two-character strings to the kern that should be used between those characters. charset - The character set of the font. A string containing characters in the order in which they are found in the image.

The default character set for a SFont is:

! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? 
@ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ 
` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~

Please note that you must register a sfont for each combination of font, size, bold, italic, and underline your game uses.

Displayables

A displayable is a python object implementing an interface that allows it to be displayed to the screen. Displayables can be assigned to an image name using an Image Statement, and can then be shown to the user using the show and hide statements. They can be supplied as an argument to the ui.add function. They are also used as the argument to certain style properties. In this section, we will describe functions that create displayabls.

Image Manipulators

An Image is a type of displayable that contains bitmap data that can be shown to the screen. All images are displayables, but not all displayables are images. Images differ from displayables in that they can be statically computed, and stored in the image cache. This loading occurs sometime before the image is to be used (but not at the time the Image is created). This generally makes Images faster than arbitrary displayables. An image manipulator is a function that returns an Image.

An image manipulator may take an Image as an argument. An Image can be supplied to an image manipulator in two ways:

The image manipulators are:

im.Image (filename, **properties):

This image manipulator loads an image from a file.

filename - The filename that the image will be loaded from.

Image (...):
An alias for im.Image.
im.Alpha (image, alpha, **properties):

Returns an alpha-mapped version of the image. Alpha is the maximum alpha that this image can have, a number between 0.0 (fully transparent) and 1.0 (opaque).

If an image already has an alpha channel, values in that alpha channel are reduced as appropriate.

im.Composite (size, *args, **properties):

This image manipulator composites one or more images together.

This takes a variable number of arguments. The first argument is size, which is either the desired size of the image (in pixels), or None to indicate that the size should be the size of the first image.

It then takes an even number of further arguments. (For an odd number of total arguments.) The second and other even numbered arguments contain position tuples, while the third and further odd-numbered arguments give images (or image manipulators). A position argument gives the position of the image immediately following it, with the position expressed as a tuple giving an offset from the upper-left corner of the image. The images are composited in bottom-to-top order, with the last image being closest to the user.

im.Crop (im, x, y, w, h, **properties):

This crops the image that is its child.

im.Flip (im, horizontal=False, vertical=False, **properties):

This is an image manipulator that can flip the image horizontally or vertically.

im - The image to be rotozoomed.

horizontal - True to flip the image horizontally.

vertical - True to flip the image vertically.

im.Map (im, rmap=im.ramp(0, 255), gmap=im.ramp(0, 255), bmap=im.ramp(0, 255), amap=im.ramp(0, 255), force_alpha=False, **properties):

This adjusts the colors of the image that is its child. It takes as arguments 4 256 character strings. If a pixel channel has a value of 192, then the value of the 192nd character in the string is used for the mapped pixel component.

im.ramp (start, end):

Returns a 256 character linear ramp, where the first character has the value start and the last character has the value end. Such a ramp can be used as a map argument of im.Map.

im.Scale (im, width, height, **properties):

This is an image manipulator that scales another image manipulator to the specified width and height. This scalling is unfiltered, so you can expect your image to look a bit jagged.

im.Recolor (im, rmul=im.ramp(0, 255), gmul=im.ramp(0, 255), bmul=im.ramp(0, 255), amul=im.ramp(0, 255), force_alpha=False, **properties):

This adjusts the colors of the image that is its child. It takes as an argument 4 numbers between 0 and 255, and maps each channel of the image linearly between 0 and the supplied color.

im.Rotozoom (im, angle, zoom, **properties):

This is an image manipulator that is a smooth rotation and zoom of another image manipulator.

im - The image to be rotozoomed.

angle - The number of degrees counterclockwise the image is to be rotated.

zoom - The zoom factor. Numbers that are greater than 1.0 lead to the image becoming larger.

im.Tile (im, size=None, **properties):

This tiles the image, repeating it vertically and horizontally until it is as large as the specified size. If no size is given, then the size defaults to the size of the screen.

Backgrounds

There are two displayables that are eminently suitable for use as backgrounds:

Frame (image, xborder, yborder):

Returns a Displayable that is a frame, based on the supplied image filename. A frame is an image that is automatically rescaled to the size allocated to it. The image has borders that are only scaled in one axis. The region within xborder pixels of the left and right borders is only scaled in the y direction, while the region within yborder pixels of the top and bottom axis is scaled only in the x direction. The corners are not scaled at all, while the center of the image is scaled in both x and y directions.

image - The image (which may be a filename or image object) that will be scaled.

xborder - The number of pixels in the x direction to use as a border.

yborder - The number of pixels in the y direction to use as a border.

For better performance, have the image share a dimension length in common with the size the frame will be rendered at. We detect this and avoid scaling if possible.

Solid (color):

Returns a Displayable that is solid, and filled with a single color. A Solid expands to fill all the space allocated to it, making it suitable for use as a background.

color - An RGBA tuple, giving the color that the display will be filled with.

Text

Text can be used to show text to the user, as a displayable.

Text (text, slow=False, slow_done=None, slow_speed=None, slow_start=0, slow_abortable=False, pause=None, tokenized=False, style='default', **properties):

A displayable that can format and display text on the screen.

text - The text that will be displayed on the screen.

slow - If True, the text will be slowly typed onto the screen.

style - A style that will be applied to the text.

properties - Additional properties that are applied to the text.

pause - If not None, then we display up to the pauseth pause (0-numbered.)

slow_done - A callback that occurs when slow text is done.

slow_speed - The speed of slow text. If none, it's taken from the preferences.

slow_offset - The offset into the text to start the slow text.

slow_abortable - If True, clicking aborts the slow text.

tokenized - True if the text is already tokenized.

Ren'Py also supports a parameterized text object, which shows text as if it was an image on the screen. But care should be taken, as it's almost always better to use a Character object to show text. By default there is one ParameterizedText image, named text declared, but the user can declare more than one to show multiple text blocks on the screen at once.

ParameterizedText (style='default', **properties):

This can be used as an image. When used, this image is expected to have a single parameter, a string which is rendered as the image.

init:
    image text1 = renpy.ParameterizedText(ypos=0.25)

show text "centered."
show text1 "1/4 of the way down the screen."

Dynamic

DynamicDisplayable can be used in styles to change the displayable shown over the course of the game.

DynamicDisplayable (expression):

expression is expected to be a python expression evaluating to a displayable. While the DynamicDisplayable is shown, it evaluates the python expression, and renders the value of that expression. The expression is evaluated at least once per interaction.

One use of this is to change the background of (say) the game menu screen over the course of the game. For example:

init:
     $ gm_background = "gmbg1.png"
     $ style.gm_root.background = DynamicDisplayable("Image(gm_background)")

label start:

     "Here, we'll show the game menu with background 1."

     $ gm_background = "gmbg2.png"

     "Now, we're showing it with background 2."

Animations

Ren'Py provides several kinds of animation displayables.

These animation functions take an anim_timebase parameter, that determines which timebase to use. The animation timebase, used when anim_timebase is True, starts at the instant of the first frame from which the tag of the image containing this animation has been shown on the screen. This can be used to switch between two animations, in a way that ensures they are synchronized to the same timebase. The displayable timebase, used when anim_timebase=False, starts at the first frame after the displayable is shown, and can be used to ensure the entire animation is seen, even if an image with the same tag was already on the screen.

The animation functions are:

Animation (*args, **properties):

A Displayable that draws an animation, which is a series of images that are displayed with time delays between them.

Odd (first, third, fifth, etc.) arguments to Animation are interpreted as image filenames, while even arguments are the time to delay between each image. If the number of arguments is odd, the animation will stop with the last image (well, actually delay for a year before looping). Otherwise, the animation will restart after the final delay time.

anim_timebase - If True, the default, use the animation timebase. Otherwise, use the displayable timebase.

init:
    image animation = Animation("frame_1.png", 0.25,
                                "frame_2.png", 0.25,
                                "frame_3.png", 0.25)
anim.Blink (image, on=0.5, off=0.5, rise=0.5, set=0.5, high=1.0, low=0.0, offset=0.0, anim_timebase=False, **properties):

This takes as an argument an image or widget, and blinks that image by varying its alpha. The sequence of phases is on - set - off - rise - on - ... All times are given in seconds, all alphas are fractions between 0 and 1.

image - The image or widget that will be blinked.

on - The amount of time the widget spends on, at high alpha.

off - The amount of time the widget spends off, at low alpha.

rise - The amount time the widget takes to ramp from low to high alpha.

set - The amount of time the widget takes to ram from high to low.

high - The high alpha.

low - The low alpha.

offset - A time offset, in seconds. Use this to have a blink that does not start at the start of the on phase.

anim_timebase - If True, use the animation timebase, if false, the displayable timebase.

anim.Filmstrip (image, framesize, gridsize, delay, frames=None, loop=True, **properties):

This creates an animation from a single image. This image must consist of a grid of frames, with the number of columns and rows in the grid being taken from gridsize, and the size of each frame in the grid being taken from framesize. This takes frames and sticks them into an Animation, with the given delay between each frame. The frames are taken by going from left-to-right across the first row, left-to-right across the second row, and so on until all frames are consumed, or a specified number of frames are taken.

image - The image that the frames must be taken from.

framesize - A (width, height) tuple giving the size of each of the frames in the animation.

gridsize - A (columns, rows) tuple giving the number of columns and rows in the grid.

delay - The delay, in seconds, between frames.

frames - The number of frames in this animation. If None, then this defaults to colums * rows frames, that is, taking every frame in the grid.

loop - If True, loop at the end of the animation. If False, this performs the animation once, and then stops.

Other keyword arguments are as for anim.SMAnimation.

anim.SMAnimation (initial, *args, **properties):

This creates a state-machine animation. Such an animation is created by randomly traversing the edges between states in a defined state machine. Each state corresponds to an image shown to the user, with the edges corresponding to the amount of time an image is shown, and the transition it is shown with.

Images are shown, perhaps with a transition, when we are transitioning into a state containing that image.

initial - The name (a string) of the initial state we start in.

showold - If the keyword parameter showold is True, then the old image is shown instead of the new image when in an edge.

anim_timebase - If True, we use the animation timebase. If False, we use the displayable timebase.

This accepts as additional arguments the anim.State and anim.Edge objects that are used to make up this state machine.

anim.State (name, image, *atlist, **properties):

This creates a state that can be used in a SMAnimation.

name - A string giving the name of this state.

image - The displayable that is shown to the user while we are in (entering) this state. For convenience, this can also be a string or tuple, which is interpreted with Image.

image should be None when this State is used with motion, to indicate that the image will be replaced with the child of the motion.

atlist - A list of functions to call on the image. (In general, if something can be used in an at clause, it can be used here as well.)

If any keyword arguments are given, they are used to construct a Position object, that modifies the position of the image.

anim.Edge (old, delay, new, trans=None, prob=1):

This creates an edge that can be used with a SMAnimation.

old - The name (a string) of the state that this transition is from.

delay - The number of seconds that this transition takes.

new - The name (a string) of the state that this transition is to.

trans - The transition that will be used to show the image found in the new state. If None, the image is show immediately.

When used with an SMMotion, the transition should probably be move.

prob - The number of times this edge is added. This can be used to make a transition more probable then others. For example, if one transition out of a state has prob=5, and the other has prob=1, then the one with prob=5 will execute 5/6 of the time, while the one with prob=1 will only occur 1/6 of the time. (Don't make this too large, as memory use is proportional to this value.)

We present two examples of this in action. The first shows how one can create a character that ocassionally, randomly, performs a 3-frame blink about once a minute.

init:
    image blinking = anim.SMAnimation("a",
        anim.State("a", "eyes_open.png"),

        # This edge keeps us showing the eyes open for a second.
        anim.Edge("a", 1.0, "a", prob=60),

        # This edge causes the eyes to start closing...
        anim.Edge("a", 0.25, "b"),

        # ..because it brings us here.
        anim.State("b", "eyes_half.png"),

        # And so on...
        anim.Edge("b", 0.25, "c"),
        anim.State("c", "eyes_closed.png"),
        anim.Edge("c", 0.25, "d"),
        anim.State("d", "eyes_half.png"),

        # And back to a.
        anim.Edge("d", 0.5, "a")
        )

Remember, State can take a Position, and Edge can take a transition. This lets you move things around the screen, dissolve images into others, and do all sorts of complicated, unexpected, things. (But be careful... not all transitions do what you'd expect when used with SMAnimation.)

Layout

These displayables are used to layout multiple displayables at once.

LiveComposite (size, *args, **properties):

This is similar to im.Composite, but can be used with displayables instead of images. This allows it to be used to composite, for example, an animation on top of the image.

This is less efficient then im.Composite, as it needs to draw all of the displayables on the screen. On the other hand, it allows displayables to change while they are on the screen, which is necessary for animation.

This takes a variable number of arguments. The first argument is size, which must be a tuple giving the width and height of the composited widgets, for layout purposes.

It then takes an even number of further arguments. (For an odd number of total arguments.) The second and other even numbered arguments contain position tuples, while the third and further odd-numbered arguments give displayables. A position argument gives the position of the displayable immediately following it, with the position expressed as a tuple giving an offset from the upper-left corner of the LiveComposite. The displayables are drawn in bottom-to-top order, with the last being closest to the user.

Fixed (*args, **properties):

A layout that expands to take the size allotted to it. Each displayable is allocated the entire size of the layout, with the first displayable further from the user than the second, and so on. Within

This function takes both positional and keyword arguments. Positional arguments should be displayables or images to be laid out. Keyword arguments are interpreted as style properties, except for the style keyword argument, which is the name of the parent style of this layout.

HBox (*args, **properties):

A layout that lays out displayables from left to right.

This function takes both positional and keyword arguments. Positional arguments should be displayables or images to be laid out. Keyword arguments are interpreted as style properties, except for the style keyword argument, which is the name of the parent style of this layout.

VBox (*args, **properties):

A layout that lays out displayables from top to bottom.

This function takes both positional and keyword arguments. Positional arguments should be displayables or images to be laid out. Keyword arguments are interpreted as style properties, except for the style keyword argument, which is the name of the parent style of this layout.

Particle Motion

Ren'Py supports particle motion. Particle motion is the motion of many particles on the screen at once, with particles having a lifespan that is shorter than a single interaction. Particle motion can be used to have multiple things moving on the screen at once, such as snow, cherry blossoms, bubbles, fireflies, and more. There are two interfaces we've provided for the particle motion engine. The SnowBlossom function is a convenience constructor for the most common cases of linearly falling or rising particles, while the Particles function gives complete control over the particle engine.

SnowBlossom is a function that can be used for the common case of linearly rising or falling particles. Some cases in which it can be used are for falling snow, falling cherry blossoms, and rising bubbles.

SnowBlossom (image, count=10, border=50, xspeed=(20, 50), yspeed=(100, 200), start=0):

This implements the snowblossom effect, which is a simple linear motion up or down the screen. This effect can be used for falling cherry blossoms, falling snow, and rising bubbles, along with other things.

image - The image that is to be used for the particles. This can actually be any displayable, so it's okay to use an Animation as an argument to this parameter.

count - The number of particles to maintain at any given time. (Realize thant not all of the particles may be on the screen at once.)

border - How many pixels off the screen to maintain a particle for. This is used to ensure that a particle is not displayed on the screen when it is created, and that it is completely off the screen when it is destroyed.

xspeed - The horizontal speed of the particles, in pixels per second. This may be a single integer, or it may be a tuple of two integers. In the latter case, the two numbers are used as a range from which to pick the horizontal speed for each particle. The numbers can be positive or negative, as long as the second is larger then the first.

yspeed - The vertical speed of the particles, in pixels per second. This may be a single integer, but it should almost certainly be a pair of integers which are used as a range from which to pick the vertical speed of each particle. (Using a single number will lead to every particle being used in a wave... not what is wanted.) The second number in the tuple should be larger then the first. The numbers can be positive or negative, but you shouldn't mix the two in the same tuple. If positive numbers are given, the particles fall from the top of the screen to the bottom, as with snow or cherry blossoms. If negative numbers are given, the particles rise from the bottom of the screen to the top, as with bubbles.

start - This is the number of seconds it will take to start all particles moving. Setting this to a non-zero number prevents an initial wave of particles from overwhelming the screen. Each particle will start in a random amount of time less than this number of seconds.

The result of SnowBlossom is best used to define an image, which can then be shown to the user.

init:
    image blossoms = SnowBlossom(Animation("sakura1.png", 0.15,
                                           "sakura2.png", 0.15))

It may make sense to show multiple snowblossoms at once. For example, in a scene with falling cherry blossoms, one can have small cherry blossoms falling slowly behind a character, while having larger cherry blossoms falling faster in front of her.

If SnowBlossom does not do what you want, it may make sense to define your own particle motion. This is done by calling the Particles function.

Particles (factory, style='default', **properties):

Supports particle motion.

factory - A factory object.

The particles function expects to take as an argument a factory object. This object (which should be pickleable) must support two methods.

The create method of the factory object is called once per frame with two arguments. The first is either a list of existing particles, or None if this is the first time this Particles is shown (and hence there are no particles on the screen). The second argument is the time in seconds from some arbitrary point, increasing each time create is called. The method is expected to return a list of new particles created for this frame, or an empty list if no particles are to be created this frame.

The predict method of the factory object is called when image prediction is requested for the Particles. It is expected to return a list of displayables and/or image filenames that will be used.

Particles are represented by the objects returned from each factory function. Each particle object must have an update method. This method is called once per frame per particle, usually with the time from the same arbitrary point as was used to create the object. (The arbitrary point may change when hidden and shown, so particle code should be prepared to deal with this.) The update method may return None to indicate that the particle is dead. Nothing is shown for a dead particle, and update is never called on it. The update method can also return an (xpos, ypos, time, displayable) tuple. The xpos and ypos parameters are a position on the screen to show the particle at, interpreted in the same way as the xpos and ypos style properties. The time is the time of display. This should start with the time parameter, but it may make sense to offset it to make multiple particle animations out of phase. Finally, the displayable is a displayable or image filename that is shown as the particle.

Position and Motion Functions

Position (**properties):

Position, when given position properties as arguments, returns a callable that can be passed to the "at" clause of a show or scene statement to display the image at the given location. See the section below on position properties to get a full explanation of how they are used to lay things out, but hopefully this example will show how Position can be used:

init:
    left = Position(xpos=0.0, xanchor='left')
    center = Position(xpos=0.5, xanchor='center')
    right = Position(xpos=1.0, xanchor='right')

    top = Position(xpos=0.5, xanchor='center', ypos=0.0,
                   yanchor='top')

show eileen happy at left
Motion (function, period, repeat=False, bounce=False, **properties):

Motion, when given the appropriate arguments, returns an object that when given as the at clause of an image causes an image to be moved on the screen. Function is a function that, when given a number between 0 and 1, returns two or four values. The first two values are interpreted as the xpos and the ypos of the motion. (Please note that if these values are floating point numbers, they are interpreted as a fraction of the screen. If they are integers, they are interpreted as the absolute position of the anchor of the motion.) If four values are returned, the third and fourth values are interpreted as an xanchor and yanchor.

Please note that the function may be pickeled, which means that it cannot be an inner function or a lambda, but must be a function defined in an init block of your script. In general, it's better to use a Pan or a Move, rather than defining your own motion.

Period is the time, in seconds, it takes to complete one cycle of a motion. If repeat is True, then the cycle repeats when it finishes, if False, the motion stops after one period. If bounce is True, the argument to the function goes from 0 to 1 to 0 in a single period, if False, it goes from 0 to 1.

Pan (startpos, endpos, time, repeat=False, bounce=False, **properties):

Pan, when given the appropriate arguments, gives an object that can be passed to the at clause of an image to cause the image to be panned on the screen. The parameters startpos and endpos are tuples, containing the x and y coordinates of the upper-left hand corner of the screen relative to the image. Time is the time it will take this position to move from startpos to endpos. Repeat and bounce are as for Motion.

As the current implementation of Ren'Py is quite limited, there are quite a few restrictions that we put on pan. The big one is that there always must be a screen's worth of pixels to the right and below the start and end positions. Failure to ensure this may lead to inconsistent rendering.

Hopefully, an example will demonstrate how Pan is used. For this example, assume that the screen is 800 x 600, and that the image marspan is 2400 x 600 pixels in size. We want to take 10 seconds to pan from left to right on the image.

scene marspan at Pan((0, 0), (1600, 0), 10.0)

Please note that the pan will be immediately displayed, and that Ren'Py will not wait for it to complete before moving on to the next statement. This may lead to the pan being overlayed with text or dialogue. You may want to use a call to renpy.pause to delay for the time it will take to complete the pan.

Finally, also note that when a pan is completed, the image locks into the ending position.

Move (startpos, endpos, time, repeat=False, bounce=False, **properties):

Move is similar to Pan, insofar as it involves moving things. But where Pan moves the screen through an image, Move moves an image on the screen. Specifially, move changes the position style of an image with time.

Move takes as parameters a starting position, an ending position, the amount of time it takes to move from the starting position to the ending position, and extra position properties. The positions are given as tuples containing xpos and ypos properties. The positions may be integer or floating point, but it's not permissable to mix the two. Repeat and bounce are as for Motion.

The following example moves a ball from the upper-left to the lower-right of the screen, taking 10 seconds to do so.

show ball at Move((0.0, 0.0), (1.0, 1.0), 10.0,
                  xanchor="center", yanchor="center")

In general, one wants to use Pan when an image is bigger than the screen, and Move when it is smaller. Both Pan and Move are special cases of Motion.

anim.SMAnimation can also be used to declare complicated motions. Use None instead of an image in States, and supply a move transition when moving between states. A SMAnimation so created can be passed in to the at clause of an image, allowing it to move things around the screen.

These movement clauses can also be used as transitions, in which case they affect the position of a single layer or the entire screen, as appropriate.

Zoom (size, start, end, time, after_child=None, **properties):

This displayable causes a zoom to take place, using image scaling. The render of this displayable is always of the supplied size. The child displayable is rendered, and a rectangle is cropped out of it. This rectangle is interpolated between the start and end rectangles. The rectangle is then scaled to the supplied size. The zoom will take time seconds, after which it will show the end rectangle, unless an after_child is given.

The algorithm used for scaling does not perform any interpolation or other smoothing.

size - The size that the rectangle is scaled to, a (width, height) tuple.

start - The start rectangle, an (xoffset, yoffset, width, height) tuple.

end - The end rectangle, an (xoffset, yoffset, width, height) tuple.

time - The amount of time it will take to interpolate from the start to the end rectange.

after_child - If present, a second child widget. This displayable will be rendered after the zoom completes. Use this to snap to a sharp displayable after the zoom is done.

Transitions

By default, Ren'Py displays each scene by replacing the old scene with a new one. This is appropriate in general (such as for emotion changes), but it may be boring for large changes, such as a change in location or a character entering or leaving the scene. Ren'Py supports transitions that control how changes to the scene lists are exposed to the user.

Transitions occur between the last scene that was shown to the user, and the current scene that has been updated using the scene, show, or hide statements. A transition takes both lists as input, and is responsible for displaying the transition between them to the user. Each transition runs for a given amount of time, but may be dismissed early by the user. Once a transition is shown, the scene is considered shown for the purposes of future transitions.

with_statement -> "with" simple_expression

Transitions are introduced with the with statement. The with statement takes an expression that is suitable for use with the with statement (that is, a callable that takes as input two scene lists), and runs that transition. Alternatively, if the expression is None, then the with statement has the effect of showing the scene to the user, and returning instantly. This is useful in conjunction with a future with statement, so that only some changes to the scene list will be transitioned in.

An example is in order. First, let us define a few objects that can be passed in as the argument to a with statement:

init:
    # Fades to black, then to the new scene.
    fade = Fade(0.5, 0, 0.5)

    # Dissolves between old and new scenes.
    dissolve = Dissolve(0.5)

A simple use of with would be to place it after a series of show and hide statements of the program. As an example:

scene bg whitehouse
show eileen happy
with fade

This series of statements will cause the old scene (displayed before these statements started) to fade to black, and be replaced with the new scene all at once. This is a useful behavior, for example, when we are replacing a scene with a new one, such as when the story changes locations.

scene bg whitehouse
with None
show eileen happy
with dissolve

The "with None" statement is useful to break changes to the scene list into parts, as in the example above. When run, the background will be instantly shown, and then the character image will be dissolved in over the background.

Another use of the "with None" statement is to remove transient elements before a transition begins. By default, the scene list includes transient elements like dialogue, thoughts, and menus. "with None" always executes without these elements, and so gets rid of them.

The "show", "hide", and "scene" statements all take a with clause. One of these statement with a with clause associated with it is actually converted into three statements: A "with None" statement, the original statement sans the with clause, and the with clause as a with statement. For example:

scene bg whitehouse with fade
show eileen happy at left with dissolve
show lucy happy at right with dissolve

becomes

with None
scene bg whitehouse
with fade
with None
show eileen happy at left
with dissolve
with None
show lucy happy at right
with dissolve

This has the effect of fading out the old scene and fading in the new background, then dissolving in the characters one after the other.

We also allow with clauses to be supplied for say and menu statements. When a with clause is supplied on one of these statements, the transition is used to introduce the say or menu element. For example,

e "How are you doing?" with dissolve

Will dissolve in a line of dialogue. The line of dialogue will be dismissed immediately, unless it is followed by a with statement or clause that causes it to transition to something else.

There is one variable that controls transitions:

default_transition = None

If not none, specifies a default transition that is applied to all say and menu statements that are not provided a with clause. This is only considered if the transitions preference is set to "All".

The following are functions that return things useful as transitions. The user should not supply the new_widget or old_widget parameters, as these are supplied by Ren'Py when a transition begins.

Fade (out_time, hold_time, in_time, old_widget=None, new_widget=None, color=None, widget=None):

This returns an object that can be used as an argument to a with statement to fade the old scene into a solid color, waits for a given amount of time, and then fades from the solid color into the new scene.

out_time - The amount of time that will be spent fading from the old scene to the solid color. A float, given as seconds.

hold_time - The amount of time that will be spent displaying the solid color. A float, given as seconds.

in_time - The amount of time that will be spent fading from the solid color to the new scene. A float, given as seconds.

color - The solid color that will be fade to. A tuple containing three components, each between 0 or 255. This can also be None.

widget - This is a widget that will be faded to, if color is None. This allows a fade to be to an image rather than just a solid color.

If both color and widget are None, then the fade is to black.

Dissolve (time, old_widget=None, new_widget=None):

This dissolves from the old scene to the new scene, by overlaying the new scene on top of the old scene and varying its alpha from 0 to 255.

time - The amount of time the dissolve will take.

ImageDissolve (image, time, ramplen=8, ramptype='linear', ramp=None, reverse=False, old_widget=None, new_widget=None):

This dissolves the old scene into the new scene, using an image to control the dissolve process.

A list of values is used to control this mapping. This list of values consists 256 fully transparent values, a ramp (of a specified number of steps) from full transparency to full opacity, and 256 fully opaque values. A 256 entry window is slid over this list, and the values found within are used to map the red channel of the image onto the opacity of the new scene.

Basically, this means that while pixels come in first, black last, and the ramp controls the sharpness of the transition.

image - The image that will be used to control this transition. The image should be the same size as the scene being dissolved.

time - The amount of time the dissolve will take.

ramplen - The number of pixels of ramp to use. This defaults to 8.

ramptype - Type of alpha ramp. Possible types are: linear, cube, dcube, mcube. Default is linear. Non-linear types must have ramplen >= 8. "cube": Ease in, sharp out. "dcube": Sharp in, sharp out. "mcube": Ease in, ease out.

ramp - If given, this is expected to be a sequence of integers in the range 0 to 255. This sequence explicitly gives the ramp to be used. If given, this overrides ramplen and ramptype.

reverse - This reverses the ramp and the direction of the window slide. When True, black pixels dissolve in first, and while pixels come in last.

CropMove (time, mode='fromleft', startcrop=(0.0, 0.0, 0.0, 1.0), startpos=(0.0, 0.0), endcrop=(0.0, 0.0, 1.0, 1.0), endpos=(0.0, 0.0), topnew=True, old_widget=None, new_widget=None):

The CropMove transition works by placing the old and the new image on two layers, called the top and the bottom. (Normally the new image is on the top, but that can be changed in some modes.) The bottom layer is always drawn in full. The top image is first cropped to a rectangle, and then that rectangle drawn onto the screen at a specified position. Start and end crop rectangles and positions can be selected by the supplied mode, or specified manually. The result is a surprisingly flexible transition.

This transition has many modes, simplifying its use. We can group these modes into three groups: wipes, slides, and other.

In a wipe, the image stays fixed, and more of it is revealed as the transition progresses. For example, in "wiperight", a wipe from left to right, first the left edge of the image is revealed at the left edge of the screen, then the center of the image, and finally the right side of the image at the right of the screen. Other supported wipes are "wipeleft", "wipedown", and "wipeup".

In a slide, the image moves. So in a "slideright", the right edge of the image starts at the left edge of the screen, and moves to the right as the transition progresses. Other slides are "slideleft", "slidedown", and "slideup".

There are also slideaways, in which the old image moves on top of the new image. Slideaways include "slideawayright", "slideawayleft", "slideawayup", and "slideawaydown".

We also support a rectangular iris in with "irisin" and a rectangular iris out with "irisout". Finally, "custom" lets the user define new transitions, if these ones are not enough.

time - The time that this transition will last for, in seconds.

mode - One of the modes given above.

The following parameters are only respected if the mode is "custom".

startcrop - The starting rectangle that is cropped out of the top image. A 4-element tuple containing x, y, width, and height.

startpos - The starting place that the top image is drawn to the screen at, a 2-element tuple containing x and y.

startcrop - The starting rectangle that is cropped out of the top image. A 4-element tuple containing x, y, width, and height.

startpos - The starting place that the top image is drawn to the screen at, a 2-element tuple containing x and y.

topnew - If True, the top layer contains the new image. Otherwise, the top layer contains the old image.

Pixellate (time, steps, old_widget=None, new_widget=None):

This pixellates out the old scene, and then pixellates in the new scene, taking the given amount of time and the given number of pixellate steps in each direction.

MoveTransition (delay, old_widget=None, new_widget=None):

This transition attempts to find images that have changed position, and moves them from the old position to the new transition, taking delay seconds to complete the move.

Images are considered to be the same if they have the same tag, in the same way that the tag is used to determine which image to replace or to hide.

If you use this transition to slide an image off the side of the screen, remember to hide it when you are done.

Some transitions can also be applied to specific layers, using the renpy.transition function (documented below). Only transitions that are not completely opaque can be used in this way.

Interaction Functions

The following functions either implement new game behavior that didn't merit its own statement, or complement the behavior of statements.

init:
    $ e = Character("Eileen", color=(200, 255, 200, 255))

e "My name is shown in full, and in green."
renpy.display_say (who, what, who_style='say_label', what_style='say_dialogue', window_style='say_window', who_prefix='', who_suffix=': ', what_prefix='', what_suffix='', interact=True, slow=True, slow_speed=None, slow_abortable=True, image=False, afm=True, ctc=None, ctc_position='nestled', all_at_once=False, what_properties={}, window_properties={}, show_function=..., show_args={}, **properties):

who - Who is saying the dialogue, or None if it's not being said by anyone.

what - What is being said.

afm - If True, the auto-forwarding mode is enabled. If False, it is disabled.

all_at_once - If True, then the text is displayed all at once. (This is forced to true if interact=False.)

For documentation of the other arguments, please read the documentation for Character.

renpy.show_display_say (who, what, who_args={}, what_args={}, window_args={}, image=False, **kwargs):

This is called (by default) by renpy.display_say to add the widgets corresponding to a screen of dialogue to the user. It is not expected to be called by the user, but instead to be called by display_say, or by a function passed as the show_function argument to Character or display_say.

who - The name of the character that is speaking, or None to not show this name to the user.

what - What that character is saying. Please not that this may not be a string, as it can also be a list containing both text and displayables, suitable for use as the first argument of ui.text().

who_args - Additional keyword arguments intended to be supplied to the ui.text that creates the who widget of this dialogue.

what_args - Additional keyword arguments intended to be supplied to the ui.text that creates the what widget of this dialogue.

window_args - Additional keyword arguments intended to be supplied to the ui.window that creates the who widget of this dialogue.

image - If True, then who should be interpreted as an image or displayable rather than a text string.

kwargs - Additional keyword arguments should be ignored.

This function is required to return the ui.text() widget displaying the what text.

renpy.predict_display_say (who, what, window_style='say_window', window_properties={}, image=False, ctc=None, show_args={}, **kwargs):

This is the default function used by Character to predict images that will be used by display_say. It's called with more-or-less the same parameters as display_say, and is expected to return a list of images used by display_say.

renpy.display_menu (items, window_style='menu_window', interact=True):

Displays a menu containing the given items, returning the value of the item the user selects.

items - A list of tuples that are the items to be added to this menu. The first element of a tuple is a string that is used for this menuitem. The second element is the value to be returned if this item is selected, or None if this item is a non-selectable caption.

interact - If True, then an interaction occurs. If False, no suc interaction occurs, and the user should call ui.interact() manually.

renpy.pause (delay=None, music=None):

When called, this pauses and waits for the user to click before advancing the script. If given a delay parameter, the Ren'Py will wait for that amount of time before continuing, unless a user clicks to interrupt the delay.

delay - The number of seconds to delay.

music - If supplied, and music is playing, this takes precedence over the delay parameter. It gives a time, in seconds, into the playing music track. Ren'Py will pause until the music has played up to that point..

Returns True if the pause was interrupted by the user hitting a key or clicking a mouse, or False if the pause was ended by the appointed time being reached.

renpy.input (prompt, default='', allow=None, exclude='{}', length=None):

This pops up a window requesting that the user enter in some text. It returns the entered text.

prompt - A prompt that is used to ask the user for the text.

default - A default for the text that this input can return.

length - If given, a limit to the amount of text that this function will return.

allow - If not None, then if an input character is not in this string, it is ignored.

exclude - If not None, then if an input character is in this set, it is ignored.

$ name = renpy.input("What is your name?", "Joe User", length=20)

e "Pleased to meet you, %(name)s."
renpy.imagemap (ground, selected, hotspots, unselected=None, overlays=False, style='imagemap', **properties):

Displays an imagemap. An image map consists of two images and a list of hotspots that are defined on that image. When the user clicks on a hotspot, the value associated with that hotspot is returned.

ground - The name of the file containing the ground image. The ground image is displayed for areas that are not part of any hotspots.

selected - The name of the file containing the selected image. This image is displayed in hotspots when the mouse is over them.

hotspots - A list of tuples defining the hotspots in this image map. Each tuple has the format (x0, y0, x1, y1, result). (x0, y0) gives the coordinates of the upper-left corner of the hotspot, (x1, y1) gives the lower-right corner, and result gives the value returned from this function if the mouse is clicked in the hotspot.

unselected - If provided, then it is the name of a file containing the image that's used to fill in hotspots that are not selected as part of any image. If not provided, the ground image is used instead.

overlays - If True, overlays are displayed when this imagemap is active. If False, the overlays are suppressed.

    $ result = renpy.imagemap("ground.png", "selected.png", [
        (100, 100, 300, 400, "eileen"),
        (500, 100, 700, 400, "lucy")
        ])


    if result == "eileen":
        e "You picked me!"

    elif result == "lucy":
        e "It looks like you picked Lucy."
renpy.transition (trans, layer=None, always=False):

Sets the transition that will be used for the next interaction. This is useful when the next interaction doesn't take a with clause, as is the case with pause, input, and imagemap.

layer - If the layer setting is not None, then the transition will be applied only to the layer named. Please note that only some transitions can be applied to specific layers.

renpy.checkpoint ():

This creates a checkpoint that the user can rollback to. The checkpoint is placed at the statement after the last statement that interacted with the user. Once this function has been called, there should be no more interaction with the user in the current statement.

renpy.block_rollback ():

Prevents the game from rolling back to before the current statement.

renpy.restart_interaction ():

Calling this restarts the current interaction. This will immediately end any ongoing transition, and will call all of the overlay functions again.

This should be called whenever widgets are added or removed over the course of an interaction, or when the information used to construct the overlay changes.

renpy.full_restart ():

This causes a full restart of Ren'Py. This clears the store and configuration, and re-runs init before branching off to start. It's very close to what happens when we quit out and re-run the interpreter, save for some caches not being cleared.

renpy.quit ():

This causes Ren'Py to exit entirely.

renpy.loadable (filename):

Returns True if the given filename is loadable, meaning that it can be loaded from the disk or from inside an archive. Returns False if this is not the case.

renpy.exists (filename):

Returns true if the given filename can be found in the searchpath. This only works if a physical file exists on disk. It won't find the file if it's inside of an archive.

renpy.clear_game_runtime ():

Resets the game runtime timer down to 0.

The game runtime counter counts the number of seconds that have elapsed while waiting for user input in the current context. (So it doesn't count time spent in the game menu.)

renpy.get_game_runtime ():

Returns the number of seconds that have elapsed in gameplay since the last call to clear_game_timer, as a float.

The game runtime counter counts the number of seconds that have elapsed while waiting for user input in the current context. (So it doesn't count time spent in the game menu.)

renpy.choice_for_skipping ():

This is called to indicate to the skipping code that we have reached a choice. If we're skipping, and if the skip after choices preference is not True, then this disables skipping.

color (s):

This function converts a hexcode into a color/alpha tuple. Leading # marks are ignored. Colors can be rgb or rgba, with each element having either one or two digits. (So the strings can be 3, 4, 6, or 8 digits long, not including the optional #.) A missing alpha is interpreted as 255, fully opaque.

For example, color('#123a') returns (17, 34, 51, 170), while color('c0c0c0') returns (192, 192, 192, 255).

Contexts store the current scene lists and execution location. Ren'Py supports a stack of contexts, but only the top-level context is saved to the save file.

renpy.context ():

Returns an object that is unique to the current context, that participates in rollback and the like.

renpy.call_in_new_context (label):

This code creates a new context, and starts executing code from that label in the new context. Rollback is disabled in the new context. (Actually, it will just bring you back to the real context.)

Use this to begin a second interaction with the user while inside an interaction.

renpy.invoke_in_new_context (callable, *args, **kwargs):

This pushes the current context, and invokes the given python function in a new context. When that function returns or raises an exception, it removes the new context, and restores the current context.

Additional arguments and keyword arguments are passed to the callable.

Please note that the context so created cannot execute renpy code. So exceptions that change the flow of renpy code (like the one created by renpy.jump) cause this context to terminate, and are handled by the next higher context.

If you want to execute renpy code from the function, you can call it with renpy.call_in_new_context.

Use this to begin a second interaction with the user while inside an interaction.

renpy.jump_out_of_context (label):

Causes control to leave the current context, and then to be transferred in the parent context to the given label.

renpy.log (msg):

If config.log is not set, this does nothing. Otherwise, it opens the logfile (if not already open), formats the message to 70 columns, and prints it to the logfile.

renpy.watch (expression, style='default', **properties):

This watches the given python expression, by displaying it in the upper-left corner of the screen (although position properties can change that). The expression should always be defined, never throwing an exception.

A watch will not persist through a save or restart.

renpy.get_filename_line ():

Returns a pair giving the filename and line number of the current statement.

renpy.image (name, img):

This is used to execute the image statment. It takes as arguments an image name and an image object, and associates the image name with the image object.

Like the image statment, this function should only be executed in init blocks.

name - The image name, a tuple of strings.

img - The displayable that is associated with that name. If this is a string or tuple, it is interpreted as an argument to Image.

renpy.scene (layer='master'):

This clears out the master layer. This is used in the execution of the scene statment, but only to clear out the layer. If you want to then add something new, call renpy.show after this.

renpy.show (name, at_list=[], layer='master'):

This is used to execute the show statement, adding the named image to the screen as part of the master layer.

name - The name of the image to add to the screen. This is a tuple of strings, one string for each component of the image name.

at_list - The at list, a list of functions that are applied to the image when shown. The members of the at list need to be pickleable if sticky_positions is True.

renpy.hide (name, layer='master'):

This finds items in the master layer that have the same name as the first component of the given name, and removes them from the master layer. This is used to execute the hide statement.

name - The name of an image. A tuple of strings, but only the first component of this tuple is ever accessed.

Finally, there exists an object named renpy.random. This object is a random number generator that implements the Python random number generation interface. However, unlike the standard random number generator, this object cooperates with rollback, generating the same numbers regardless of how many times we rollback. It should be used instead of the standard Python random module.

Overlays

Overlays are used to display information above the scene currently displayed. The overlay is regenerated each time an interaction with the user begins, making it suitable for displaying to the user things like statistics or dates. The overlay is generally displayed whenever transient things (like dialogue, thoughts and menus) are.

Overlays are set up by adding to the config.overlay_functions list a python function which, when called, uses the ui functions to add widgets to the screen. By default, such widgets are added to the 'overlay' layer, but a call to ui.layer() can change the layer to any of the layers listed in library.overlay_layers. These functions are called for each interaction, which allows the overlay to change to reflect the status of game variables. If a variable affecting the overlay changes during an interaction, renpy.restart_interaction() should be called to regenerate the overlay.

As an example, take the following code fragement. When added to a program, this displays a date image in the upper-right corner of the screen (as is done in Kanon). The image shown is based on the variable date. If date is None, then no date is shown. Otherwise, a png file beginning with the value of date is shown.

init:
    $ date = "mar25"

    python hide:
        def date_overlay():
            if date:
                ui.image(date + ".png",
                         xpos=1.0, xanchor="right",
                         ypos=0.0, yanchor="top") ]

        config.overlay_functions.append(date_overlay)

Like all config variables, config.overlay_functions should only be changed in an init block. If you need to toggle an overlay on and off, then the overlay function should be conditioned on some normal variable, returning an empty list if it is false. This is done in the example above when date is None.

Multimedia: Sound, Music, and Movies

Sound

Ren'py supports playing sounds in the background, using the renpy.play function. These sounds must be in wav files, but may live in an archive file.

renpy.play (filename, channel=0, fadeout=0, fadein=0, tight=False):

Plays the named file once on the given channel. This will cause any playing sound effect to be stopped (after the given fadeout number of seconds, if necessary), and the new sound to be played in its place. The sound is faded in for the given number of seconds.

The filename may be that of a file in an archive.

If tight is True, then a fadeout of this sound will continue into the next-queued sound.

$ renpy.play("quindar.wav")
e "Ground control to Major Tom."

Sounds can also be associated with buttons, menu choices, and imagemaps becoming hovered and activated. See the section on sound properties in styles for how to used this.

Music

Ren'Py supports playing music in the background of your game. Theoretically, Ren'Py should support any format SDL_mixer supports (mp3, ogg, midi, mod, and more), but we've only tested mp3 and ogg support. The music that is currently playing is kept as part of the interpreter state, and is restored when a player loads a game or rolls back the game state, automatically.

Music must exist in real files (not archive files), named with paths starting at the game directory. The filename that the music is stored in is saved with the game state. If the filename changes between game releases, the game will still proceed, but music that was playing when the game was saved may be absent when the game is loaded.

The playing of music is controlled by a pair of Python function calls:

renpy.music_start (filename, loops=True, fadeout=None, fadein=0):

Deprecated music start function, retained for compatibility. Use renpy.music.play() or .queue() instead.

renpy.music_stop (fadeout=None):

Deprecated music start function, retained for compatibility. Use renpy.music.play() or .queue() instead.

Here's an example of a script fragment that comes with musical accompaniment.

e "Lemma kept asking for support for playing music."

# Loads game/music/taps.mp3
$ renpy.music_start("music/taps.mp3")

show eileen flaming mad

e "Well, we'll show him."

$ renpy.music_stop()

show eileen wink

e "Just kidding."

The config.fade_music variable is used to control the fading out of old music when a new track is started.

Movies

As of version 4.5, Ren'Py is capable of playing MPEG-1 movies. This allows you to include video as part of your game. There are two ways that this can be done. Displaying video in fullscreen mode allows video to be scaled up to very large sizes, while displaying video in a displayable allows it to be blended with images and text.

Displaying a video fullscreen allows it to take advantage of hardware decode and scaling support. The downside of fullscreen mode is that nothing else can be displayed while the movie is being displayed.

The easiest way to display a movie fullscreen is to display it using the renpy.cutscene function. This function displays a movie for a specified length of time. When that time has elapsed, or when the user clicks to dismiss the movie, the movie ends and the function returns.

renpy.movie_cutscene (filename, delay, loops=0):

This displays an MPEG-1 cutscene for the specified number of seconds. The user can click to interrupt the cutscene. Overlays and Underlays are disabled for the duration of the cutscene.

filename - The name of a file containing an MPEG-1 movie.

delay - The number of seconds to wait before ending the cutscene. Normally the length of the movie, in seconds.

loops - The number of extra loops to show, -1 to loop forever.

Returns True if the movie was terminated by the user, or False if the given delay elapsed uninterrupted.

Displaying a movie in a displayable is more difficult, but it allows the movie to be mixed with rendered text and graphics. A downside of this method is that the screen needs to be re-rendered with each frame, a process that may be unacceptibly slow when the screen is large. We don't recommend this when the game window is larger that 640x480.

To display a movie in a displayable, we must start the movie and show a Movie displayable on the screen. The movie is then displayed on the screen along with any other widget. When we no longer want to show it, we need to stop the decoding of the movie and hide the displayable.

Movie (fps=24, style='default', **properties):

This is a displayable that displays the current movie. In general, a movie should be playing whenever this is on the screen. That movie should have been started using movie_start_displayable before this is shown on the screen, and hidden before this is removed.

fps - The framerate that the movie should be shown at.

renpy.movie_start_displayable (filename, size, loops=0):

This starts a MPEG-1 movie playing in displayable mode. One or more Movie() widgets must be displayed if the movie is to be shown to the user.

filename - The filename of the MPEG-1 move that we're playing.

size - A tuple containing the size of the movie on the screen. For example, (640, 480).

loops - The number of additional times the movie should be looped. -1 to loop it forever.

renpy.movie_stop (clear=True):

This stops the currently playing movie.

init:
    image movie = Movie()

$ renpy.movie_start_displayable("bg.mpg", (640, 480), -1)
scene movie
show eileen happy

e "I'm standing in front of a movie."

e "Isn't that keen?"

hide movie
$ renpy.movie_stop()

Whenever a movie is playing, it is expected to provide all sound that the user hears. Ren'Py disables sound hardware for the duration of the movie.

$ renpy.cutscene("On_Your_Mark.mpg", 394)

Configuration Variables

Much of the the configuration of Ren'Py is done using configuration variable. These variable, when assigned in a python block, change the behavior of the interpreter. As configuration variables aren't saved, and many need to be set before the GUI initializes, it makes sense to set all configuration variable inside init blocks. An example setting of variables is:

init:
    $ config.screen_width = 640
    $ config.screen_width = 480

config.screen_width = 800

This sets the width of the screen.

config.screen_height = 600

This sets the height of the screen.

config.window_icon = None

If not None, this is expected to be the filename of an image giving an icon that is used for the window.

config.sound = True

If True, sound works. If False, the sound/mixer subsystem is completely disabled.

config.debug = False

Enables some minor debugging functionality (mostly by turning some missing files into errors.) This should always be turned off in a release.

config.debug_sound = False

Enables debugging of sound functionality. This disables the supression of errors when generating sound. However, if a sound card is missing or flawed, then such errors are normal, and enabling this may prevent Ren'Py from functioning normally. This should always be False in a released game.

config.rollback_enabled = True

Should the user be allowed to rollback the game? If set to False, the user cannot interactively rollback. (The feature still works for loading savegames when the script changes.)

config.rollback_length = 128

When there are more than this many statements in the rollback log, Ren'Py will consider trimming the log.

config.hard_rollback_limit = 10

This is the number of steps that Ren'Py will let the user interactively rollback. Set this to 0 to disable rollback entirely, although we don't recommend that, as rollback is useful to let the user see text he skipped by mistake.

config.profile = False

If set to True, some profiling information will be output to stdout (wherever that may go to).

config.image_cache_size = 8

This is used to set the size of the image cache, as a multiple of the screen size. This is mostly a suggestion, as if Ren'Py ever needs to display more than this amount of images at once, it will cache them all. But it will stop predictively loading images when the cache is filled beyond this, and it will try to drop images from the cache until it shrinks below this size. If this is too small, there will be more disk access as images are loaded and re-loaded. If this is too large, memory usage will be increased as images are kept in memory.

config.predict_statements = 10

This is the number of statements, including the current one, to consider when doing predictive image loading. A breadth-first search from the current statement is performed until this many statements is considered, and any image referenced in those statements is potentially predictively loaded. Setting this to 0 will disable predictive loading of images.

config.debug_image_cache = False

If True, Ren'Py will print the contents of the image cache to standard output (wherever that goes) whenever the contents of the image cache change.

config.load_before_transitions = True

If True, the start of transitions will be delayed until the images used by said transitions have finished loading.

config.allow_skipping = True

If set to False, the user is not able to skip over the text of the game.

config.fast_skipping = False

Set this to True to allow fast skipping outside of developer mode.

config.skip_delay = 75

The amount of time that dialogue will be shown for, when skipping statements using ctrl, in milliseconds. (Although it's nowhere near that precise in practice.)

config.archives = [ ]

A list of archive files that will be searched for images.

config.searchpath = [ 'common', 'game' ]

A list of directories that are searched for images, music, archives, and other media, but not scripts. This is initialized to a list containing "common" and the name of the game directory, which changes depending on the name of the exe file. This variable is not used to load scripts, as scripts will be loaded before it can be set.

config.mouse = None

This variable controls the user of user-defined mouse cursors. If None, the system mouse is used, which is usually a black-and-white mouse cursor. Otherwise, this should be a dictionary giving the mouse animations for various mouse types. Keys used by the default library include "default", "say", "with", "menu", "prompt", "imagemap", "pause", "mainmenu", and "gamemenu". The "default" key should always be present. The values in the dictionary should be list of frames making up the mouse cursor. Each frame is an (image, x-offset, y-offset) tuple. Image is a filename of an image, while x- and y- offset are the offsets of the hotspot within the image. The frames are played back at 20hz, and the animation loops after all frames have been shown. Please note that to show a frame more than once, it must be repeated in a frame list. That is implemented efficiently.

config.focus_crossrange_penalty = 1024

This is the amount of penalty to apply to moves perpendicular to the selected direction of motion, when moving focus with the keyboard.

config.sound_sample_rate = 44100

The sample rate that the sound card will be run at. If all of your wav files are of a lower rate, changing this to that rate may make things more efficent.

config.overlay_functions = [ ]

A list of functions. When called, each function is expected to return a list of displayables, which are added to the overlay list. See the section on overlays for more.

config.fade_music = 0.0

This is the amount of time in seconds to spend fading the old track out before a new music track starts. This should probably be fairly short, so the wrong music doesn't play for too long.

config.keymap = dict(...)

This variable contains a keymap giving the keys and mouse buttons assigned to each possible operation. Please see the section on keymaps for more information.

config.joystick = True

Governs if joystick support is enabled. If False, Joystick detection is disabled.

config.sticky_positions = False

Sticky positions causes the at clause of a show or scene statement to be remembered for as long as that character is on the screen. Future show statements without at clauses will be given the remembered at clause. This lets us easily change the character's expression without changing their position on the screen. Sticky positions does not interact well with multiple layers, when they are used with the show, hide, and scene statements via an onlayer clause.

config.layers = [ 'master', 'transient', 'overlay' ]

This variable gives a list of all of the layers that Ren'Py knows about, in the order that they will be displayed to the screen. (The lowest layer is the first entry in the list.) Ren'Py uses the layers "master", "transient", and "overlay" internally, so they should always be in this list.

config.transient_layers = [ 'transient' ]

This variable gives a list of all of the transient layers. Transient layers are layers that are cleared after each interaction. "transient" should always be in this list.

config.overlay_layers = [ 'overlay' ]

This is a list of all of the overlay layers. Overlay layers are cleared before the overlay functions are called. "overlay" should always be in this list.

config.top_layers = [ ]

This is a list of names of layers that are displayed above all other layers, and do not participate in a transition that is applied to all layers. If a layer name is listed here, it should not be listed in config.layers.

config.overlay_during_with = True

True if we want overlays to be shown during with statements, or False if we'd prefer that they be hidden during the with statements.

config.with_callback = None

If not None, this should be a function that is called when a with statement occurs. This function can be responsible for putting up transient things on the screen during the transition. The function is called with a single argument, which is the transition that is occuring. It is expected to return a transition, which may or may not be the transition supplied as its argument.

config.enable_fast_dissolve = True

Setting this to False can fix a potential bug in the dissolve transition when used with an overlay layer that has an alpha channel that is not fully transparent or opaque, at the cost of 25% of the performance of dissolve. It usually can be kept at True with no ill effects.

config.text_tokenizer = ...

This functions is used to tokenize text. It's called when laying out a Text widget, and is given the string that is the text of the widget, and the style associated with the widget.

It's expected to yield some number of pairs. In each pair, the first element is the kind of token found, and the second element is the text corresponding to that token. The following token types are defined:

config.afm_characters = 250

The number of characters in a string it takes to cause the amount of time specified in the auto forward mode preference to be delayed before auto-forward mode takes effect.

config.afm_bonus = 25

The number of bonus characters added to every string when auto-forward mode is in effect.

config.afm_callback = None

If not None, a python function that is called to determine if it is safe to auto-forward. The intent is that this can be used by a voice system to disable auto-forwarding when a voice is playing.

config.auto_choice_delay = None

If not None,this variable gives a number of seconds that Ren'Py will pause at an in-game menu before picking a random choice from that menu. We'd expect this variable to always be set to None in released games, but setting it to a number will allow for automated demonstrations of games without much human interaction.

config.font_replacement_map = { }

This is a map from (font, bold, italics) to (font, bold, italics), used to replace a font with one that's specialized as having bold and/or italics. For example, if you wanted to have everything using an italic version of "Vera.ttf" use "VeraIt.ttf" instead, you could write config.font_replacement_map["Vera.ttf", False, True] = ("VeraIt.ttf", False, False). Please note that these mappings only apply to specific variants of a font. In this case, requests for a bold italic version of vera will get a bold italic version of vera, rather than a bold version of the italic vera.

config.interact_callbacks = ...

A list of functions that are called (without any arguments) when an interaction is started or restarted.

config.start_interact_callbacks = ...

A list of functions that are called (without any arguments) when an interaction is started. These callbacks are not called when an interaction is restarted.

config.say_sustain_callbacks = ...

A list of functions that are called, without arguments, before the second and later interactions caused by a line of dialogue with pauses in it. Used to sustain voice through pauses.

config.editor = None

If not None, this is expected to be a command-line for an editor that is invoked when the launch_editor (normally shift-E) key is pressed. There are two subsitutions that make sense here. %(filename)s is replaced with the filename of the currently-executing line of Ren'Py code. %(line)d is replaced with the line number of the currently-executing line of Ren'Py code.

config.log = None

If not None, this is expected to be a filename. Much of the text shown to the user by say or menu statements will also be logged to this file.

config.developer = False

If set to True, developer mode is enabled.

config.lint_hooks = ...

This is a list of functions that are called, with no arguments, when lint is run. The functions are expected to check the script data for errors, and print any they find to standard output (using the python print statement is fine in this case).

config.hyperlink_callback = ...

A function that is called with the argument to a hyperlink when that hyperlink is clicked. Defaults to a function that inteprets the argument as a label, which is called in a new context when the hyperlink is clicked.

config.periodic_callback = None

If not None, this should be a function. The function is called, with no arguments, at around 20hz.

library.script_version = None

If not None, this is interpreted as a script version. The library will use this script version to enable some compatibility features, if necessary. If None, we assume this is a latest-version script.

library.file_page_cols = 2

This is the number of columns of save slots that are show in the picker that's used in the load and save screens of the game menu.

library.file_page_rows = 5

This is the number of rows of save slots that are show in the picker that's used in the load and save screens of the game menu.

library.file_quick_access_pages = 5

The number of pages of the file picker to provide quick access to. Quick access is provided by number buttons which are at the top of the file picker.

library.thumbnail_width = 100

The width of the thumbnails that are taken when the game is saved. These thumbnails are shown when the game is loaded. Please note that the thumbnail is shown at the size it was taken at, rather than the value of this setting when the thumbnail is shown to the user.

library.thumbnail_height = 75

The width of the thumbnails that are taken when the game is saved. These thumbnails are shown when the game is loaded. Please note that the thumbnail is shown at the size it was taken at, rather than the value of this setting when the thumbnail is shown to the user.

library.main_menu = [ ( "Start Game", "start", "True" ), ("Continue Game", ... ), ("Preferences", ... ), ("Quit Game", ...) ]

This is used to give the main menu that is shown to the user when the game first starts. It is a list of tuples, where the first element of each tuple is the title of the menu button, and the second element is a label that we jump to when that button is selected. (This jump exits the context in which the start menu executes.) The second element may also be a function, in which case it is called when the item is selected, in the menu context. The third element in each tuple is an expression, which is evaluated each time the main menu is displayed. If the expression evaluates to false, the menu choice is disabled.

library.game_menu = [ ... ]

Thi is used to customize the choices on the game menu. Please read the section on customizing the main and game menus for more details on the contents of this variable.

library.main_menu_positions = None

If not None, this is a map between the default label for buttons on the main menu, and a dictionary containing properties that are applied to that button. This provides a simple way of customizing the main menu by changing where buttons are located on the screen. Please note that this disables the usual button-placement algorithm, so if one button is positioned this way, all must be.

library.game_menu_positions = None

If not None, this is a map between the default label for buttons on the game menu, and a dictionary containing properties that are applied to that button. This provides a simple way of customizing the game menu by changing where buttons are located on the screen. Please note that this disables the usual button-placement algorithm, so if one button is positioned this way, all must be.

library.preferences = { ... }

This is used to customize the preferences. Please read the section on customizing the main and game menus for more details on the contents of this variable.

library.all_preferences = { ... }

This is a map from preference name to the preference object implementing that preference. This variable shouldn't be modified by the user directly, but instead provides a stable source of preferences that can be added to library.preferences.

library.joystick_keys = [ ... ]

This is a listing of all the joystick synthetic keys known to Ren'Py. It's a list of visible name, keysym pairs. Ren'Py uses this to populate the joystick preferences.

library.has_music = True

If True, the preference for enabling and disabling music will be presented to the user. This should be set to False if the game does not play any music.

library.has_sound = True

If True, the preference for enabling and disabling sound effects is presented to the user. This should be set to False if the game does not have any sound effects.

library.has_cps = True

If True, the preference for changing the text speed is shown to the user.

library.has_afm = True

If True, the preference for auto-forward mode is shown to the user.

library.has_transitions = True

If True, the preference for enabling and disabling transitions is presented to the user. This should be set to False if the game does not have any transitions (that is, never uses the with statement or clause).

library.has_skipping = True

If True, the preference controlling what TAB and CTRL skip will be shown to the user.

library.has_skip_after_choices = True

If True, the preference enabling skip after choices will be shown to the user.

library.hbox_pref_choices = False

If True, the choice buttons in a preference will be placed together in an hbox.

library.enter_sound = None

If not None, this is a sound file that is played when entering the game menu without clicking a button. (For example, when right-clicking during the game.)

library.exit_sound = None

If not None, this is a sound file that is played when exiting the game menu without clicking a button. (For example, when right-clicking inside the game menu.)

library.skip_indicator = True

If True, the library will display a skip indicator when skipping through the script.

library.enter_transition = None

If not None, this variable should give a transition that will be used when entering the game menu.

library.exit_transition = None

If not None, this variable should give a transition that will be performed when exiting the game menu.

library.sample_sound = None

If not None, this variable should give a sample sound that is played when the "Test" button on the volume slider is clicked. If None, then the "Test" button is not shown.

library.main_menu_music = None

If not None, a music file to play when at the main menu.

library.game_menu_music = None

If not None, a music file to play when at the game menu.

library.always_has_joystick = False

If True, the joystick interface is always available. This may be used by people without joysticks to see the joystick interface for themeing purposes.

Properties and Styles

Ren'Py includes a style system that allows the user to control the styles of text and windows (including things that inherit from window, like buttons). A style inheritance mechanism allows a single change to (for example) font size to affect the entire game, while at the same time allowing fine-grained control when it is desired.

A large number of styles are built into Ren'Py. It is possible to use style.create to make your own styles.

style.create (self, name, parent, description=None):

Creates a new style.

name - The name of the new style, as a string.

parent - The parent of the new style, as a string. This is either 'default' or something more specific.

description - A description of the style, for documentation purposes.

There are two families of style properties. Text properties are used to control the font, size, and color of text, while window properties are used to control the layout, background, and padding of windows. If a widget displays text inside a window (as a textbutton does), then it respects both text and window properties. A widget is a Displayable that can accept properties.

Many style properties take as an argument RGBA tuples. These are python tuples containing four values, representing the red, green, blue, and alpha components of a color. Each of these values is a number between 0 and 255. Alpha is used to control how opaque the thing should be, with 0 being transparent, and 255 being fully opaque. It's probably easiest to show an example of RGBA tuples being used as part of styles.

init:

    # Selected menu choices should be yellow and solid.
    $ style.menu_choice.hover_color = (255, 255, 0, 255)

    # Unselected menu choices should be cyan and translucent.
    $ style.menu_choice.idle_color = (0, 255, 255, 128)

Text Properties

The following are properties that can be applied to Displayables that take text styles.

font --- The font that will be used to render text. This is either the name of a file containing a truetype font, or the name of a font. In the former case, the font is loaded from the file. In the latter case, the filename is used to search SFonts registered with register_sfont, and truetype fonts found on the system font directory.

size --- The size of the font that is used to display the text on the screen. Please note that the meaning of this can vary from font to font, and bears only a weak relationship with the number of pixels high that the font will be on the screen.

color --- The color in which the text will be displayed on the screen, as an RGBA tuple. This is ignored when an SFont is used.

bold --- If True, then this text will be rendered in bold.

italic --- If True, then this text will be rendered in italics.

underline --- If true, then this text will be rendered with an underline.

antialias --- If True, the text will be antialiased. Otherwise, it will be left jagged.

drop_shadow --- This is used to control the generation of a drop shadow on text. It's either a 2-element tuple, or None. If it's a tuple, then the 2 elements control the drop shadow offsets in X and Y, respectively. (Both numbers should be positive for best results.) If None, then no drop shadow is created for the text. Example: (2, 3)

drop_shadow_color --- An RGBA tuple that's used to give the color of the drop shadow. Example: (0, 0, 0, 128)

minwidth --- The minimum width in pixels of this text. If the rendered text is smaller than this, it is right-padded with whitespace until it is at least this many pixels long.

line_spacing --- This is used to increase or decrease the spacing between lines of text by a constant number of pixels. A positive value increases, while a negative value decreases the spacing.

text_y_fudge --- This fudges the y position of a block of text by adding whitespace above the first line.

textalign --- This is used to control the horizontal alignment of the lines of text in the area allocated to the Text widget containing that text. It only really has any effect if the text is more than one line long. It's a number between 0 and 1, which gives the fraction of empty space that should be to the left of each line of text. (To center text, it should be 0.5.)

first_indent --- This is used to give, in pixels, the indentation of the first line of text in the text widget. It can be used to indent the first line of a paragraph of text. (Not that that's a good idea on a computer monitor, better to leave a blank line between paragraphs.)

rest_indent --- This is used to give, in pixels, the indentation of the second and later lines of a text widget. It can be used to give a hanging indent to quoted dialogue.

Window Properties

Window properties are used to control the display of windows, and other widgets that involve a rectangular area with a background being displayed on the screen.

background --- A Displayable that is used as the background for the window. This needs to be a Displayable that always draws exactly the size requested of it, which usually means either a Solid or a renpy.Frame. This can also be None, which means that there is no background on this window. (All the other window properties that refer to a background still work. Just think of them as if their background was transparent.) Example: Solid((0, 0, 128, 128))

left_margin --- The amount of transparent space left to the left of this window. If a floating point number, it is scaled to the available width.

right_margin --- The amount of transparent space left to the right of this window. If a floating point number, it is scaled to the available width.

top_margin --- The amount of transparent space left to the top of this window. If a floating point number, it is scaled to the available height.

bottom_margin --- The amount of transparent space left to the bottom of this window. If a floating point number, it is scaled to the available height.

xmargin --- This is a convenient (and backwards compatible) way of setting left_margin and right_margin to the same value.

ymargin --- This is a convenient (and backwards compatible) way of setting top_margin and bottom_margin to the same value.

left_padding --- The amount of space left between the edge of the border and the left side of the contents of the window. If a float, it is scaled to the width of the window.

right_padding --- The amount of space left between the edge of the border and the right side of the contents of the window. If a float, it is scaled to the width of the window.

top_padding --- The amount of space left between the edge of the border and the top side of the contents of the window. If a float, it is scaled to the height of the window.

bottom_padding --- The amount of space left between the edge of the border and the bottom side of the contents of the window. If a float, it is scaled to the height of the window.

xpadding --- A convenient (and backwards compatible) way of setting left_padding and right_padding to the same value.

ypadding --- A convenient (and backwards compatible) way of setting top_padding and bottom_padding to the same value.

xfill --- If True, the window will expand to fill all available space in the x direction. If False, it will shrink to fit its contents.

yfill --- If True, the window will expand to fill all available space in the y direction. If False, it will shrink to fit its contents.

xminimum --- The minimum size of this window in the x direction, including margins and padding. If the window would be smaller than this, it is grown to be at least this size. If a floating point number, it is scaled to the available width.

yminimum --- The minimum size of this window in the y direction, including margins and padding. If the window would be smaller than this, it is grown to be at least this size. If a floating point number, it is scaled to the available height.

Position Properties

Position properties are applied to widgets that are smaller than the space allocated to them. They apply to all widgets, and control the placement of the widget in the space. For example, position properties can be used to control the placement of a dialogue window on the screen.

Position properties work best when a small widget is placed into empty space. This is the case for say windows, and the menus that are displayed as part of the main menu. Position properties work on many updates, but the vagaries of how space is allocated by widgets may make some of the results counterintuitive.

Positioning is done by specifying the placement of an anchor that is part of a widget within the space allocated to that widget. The position is either specified as an absolute number of pixels or a fraction of the available space, while the position of the anchor within the widget is done by selecting one of three settings for each dimension.

xpos --- Controls the positioning of the widget anchor in the x dimension. If an integer, this is taken as the number of pixels to the left of the anchor. If a float, this is taken as a fraction of the available space in the x direction.

xanchor --- Controls the placement of the anchor within the widget, in the x dimension. This can be one of 'left', 'center', or 'right', or a number between 0 and 1, where 0 is the left edge and 1 is the right edge.

xalign --- This can be used as a shortcut for setting xpos and xanchor to the same value. This is expected to be used with floats between 0.0 and 1.0.

ypos --- Controls the positioning of the widget anchor in the y dimension. If an integer, this is taken as the number of pixels to the left of the anchor. If a float, this is taken as a fraction of the available space in the y direction.

yanchor --- Controls the placement of the anchor within the widget, in the y dimension. This can be one of 'top', 'center', or 'bottom', or a number between 0 and 1, where 0 is the top edge and 1 is the bottom edge.

yalign --- This can be used as a shortcut for setting ypos and yanchor to the same value. This is expected to be used with floats between 0.0 and 1.0.

xmaximum --- If not None, this property gives the maximum width of this widget. (Most widgets respect this, but some have a fixed size which this does not change.)

ymaximum --- If not None, this property gives the maximum height of this widget. (Most widgets respect this, but some have a fixed size which this does not change.)

Sound Properties

Some widgets can take sound style properties. These widgets can cause a sound to play when they become hovered (see below), and also when they are selected. Currently, the styles that can take sound properties belong to buttons, imagemaps, and menu choices. Sound style properties are either the name of a wav file which is played with renpy.play when appropriate event occurs, or None to disable sound playback.

hover_sound --- The sound to play when this widget becomes hovered.

activate_sound --- The sound to play when the widget is activated, by clicking on or otherwise selecting it.

Bar Properties

The ui.bar() widget has a few properties that are specific to it, that control the look of the bars. The bar has gutters on the left and the right. The remaining space is the space in which the bar can change, with the division of the bar being the fraction of this space representing the bar's value as a fraction of the range.

When the bar is drawn, the thumb's shadow is drawn first, followed by the left and right sides of the bar, followed by the thumb.

left_gutter --- The size of the left gutter of the bar, in pixels.

right_gutter --- The size of the right gutter of the bar, in pixels.

left_bar --- A Displayable that is used to draw the left side of the bar. This displayable is first rendered at the full size of the bar, and then cropped so only the left side is visible.

right_bar --- A Displayable that is used to draw the right side of the bar. This displayable is first rendered at the full size of the bar, and then cropped so only the right side is visible.

thumb --- If not None, this is a thumb image that is drawn near the break between the left and right side of the bar.

thumb_shadow --- If not None, a shadow of the thumb that is drawn underneath the break between the left and right side of the bar.

thumb_offset --- The horizontal update between the division in the bar and the left side of the thumb, in pixels. This will often be negative, so that the thumb overlaps the division to some extent.

Box Properties

Horizontal and Vertical boxes have a number of properties that can be used to control how they are laid out. By changing these properties, one can control the spacing between elements in a box, and even turn a box from horizontal to vertical (or vice versa).

box_spacing --- The spacing between elements in the box.

box_first_spacing --- If not None, the spacing between the first two elements in the box.

box_layout --- If "horizontal", the box is laid out in a horizontal manner. If "vertical", the box is laid out in a vertical fashion. If None, the layout of the box is controlled by the function that created the box, with ui.hbox and ui.vbox making horizontal and vertical boxes, respectively.

xfill --- If True, the box will expand to fill all available space in the x direction. If False, it will shrink to fit its contents.

yfill --- If True, the box will expand to fill all available space in the y direction. If False, it will shrink to fit its contents.

Hovering

In Ren'Py, buttons and their contents support the idea of hovering: using different sets of properties for different states of the widget. If the widget cannot be given focus, it is considered to be insensitive. If the widget has been selected by the user, it is considered to be activated. Otherwise, if the widget has focus, then that widget is hovered, else it is idle. On these widgets, Ren'Py will look up a property prefixed with "insensitive_", "activate_", "hover_", or "idle_" (as appropriate) in a style, before looking up an unprefixed property. If neither form is found on a style, the process is repeated again on the parent style. (The search pattern for background on a hovered button goes: button.hover_background, button.background, default.hover_background, default.background.)

The only time an activated widget will be seen by the user is if a transition occurs immediately after the widget has been activated.

As an example, take assigning a background to buttons that changes when the button is hovered over.

init:
    style.button.hover_background = Solid((255, 255, 255, 255))
    style.button.idle_background = Solid((0, 0, 0, 255))

enable_hover --- This property must be set to True (the default) on the style of a hoverable widget (like a button) for hovering to be enabled. Setting it to False speeds up Ren'Py, at the cost of making the widget not respond to hovering.

Using Properties and Styles

For properties to be useful, there needs to be a way to change the properties associated with a given widget. Ren'Py provides several ways to do this.

The most common way to do this is to change the definition of one of the standard styles. Widgets that use this style, or one of the styles that inherits from it, will pick up the change and change how they are displayed.

The following example code ensures that the label of a button is colored light green and aligned to the left. It also changes the background images that are used when the button is idled and hovered.

init:
    $ style.button.color = (128, 255, 128, 255)
    $ style.button.xpos = 0
    $ style.button.idle_background = \
          renpy.Frame(renpy.Image("button_idled.png"),
                      xborder=10, yborder=10)
    $ style.button_hover.background = \
          renpy.Frame(renpy.Image("button_hover.png"),
                      xborder=10, yborder=10)

This is the only way to change the look of widgets that are automatically generated, such as those used to implement the interface of the say and menu statements, except for say statements that are routed through an object, like a character object.

The second way to change the look of a widget is to change the name of the style associated with that widgets. All widgets have one or more parameters that take styles that the widget take on. One can define a new style using style.new_style, and modify that style, and tell widgets to use that style when appropriate.

While normally new styles can only be assigned to widgets constructed by the user, there are some exceptions to this rule. The Character object takes as optional arguments styles that are given to the say window, character name, and dialogue text.

The final way of assigning properties is to list them as keyword arguments on a constructor that takes properties. (Indicated by having **properties in its argument list.) Properties that are given in this way take precedence over all other properties. The Character argument also takes properties that are applied to the window and the label.

Standard Styles

In this section find a list of the standard styles that come with Ren'Py, either built-in or in the standard library. Before each in parentheses, we list the types of properties that are used on the style, and "hover" if the default use of the style supports hovering.

default:
The default style that all styles inherit from.
hbox:
(inherits from default)
(box) The base style for hboxen.
vbox:
(inherits from default)
(box) The base style for vboxen.
window:
(inherits from default)
(window) The base style for the windows that contain dialogue, thoughts, and menus.
frame:
(inherits from default)
(window) The base style for frames.
image_placement:
(inherits from default)
This style is used to control the default placement of images on the screen.
image:
(inherits from default)
This is the style of images themselves. Don't change this, change image_placement instead.
animation:
(inherits from default)
This is the default style of animations. Don't change this, change image_placement instead.
say_label:
(inherits from default)
(text) The style that is used by default for the label of dialogue. The label is used to indicate who is saying something.
say_dialogue:
(inherits from default)
(text) The style that is used by default for the text of dialogue.
say_thought:
(inherits from default)
(text) The label that is used by default for the text of thoughts or narration, when no speaker is given.
say_window:
(inherits from window)
(window) The default style for windows containing dialogue and thoughts.
say_vbox:
(inherits from vbox)
(box) The vbox containing the label (if present) and the body of dialogue and thoughts.
menu:
(inherits from default)
(position) The style that is used for the vbox containing a menu.
menu_caption:
(inherits from default)
(text) The style that is used to render a menu caption.
menu_choice:
(inherits from default)
(text, hover) The style that is used to render the text of a menu choice.
menu_choice_button:
(inherits from default)
(window, hover, sound) The style that is used to render the button containing a menu choice.
menu_choice_chosen:
(inherits from menu_choice)
(text, hover) The style that is used to render the text of a menu choice that has been chosen by the user sometime in the past.
menu_choice_chosen_button:
(inherits from menu_choice_button)
(window, hover, sound) The style that is used to render the button containing a menu choice that has been chosen by the user sometime in the past.
menu_window:
(inherits from window)
(window) The default style for windows containing a menu.
input_text:
(inherits from default)
(text) The style used for the text of an input box.
input_prompt:
(inherits from default)
(text) The style used for the prompt of an input box.
input_window:
(inherits from window)
(window) The style used for the window of an input box.
centered_window:
(inherits from default)
(window) The style that is used for a "window" containing centered text.
centered_text:
(inherits from default)
(text) The style used for centered text.
imagemap:
(inherits from image_placement)
The style that is used for imagemaps.
imagemap_button:
(inherits from default)
(window, sound, hover) The style that is used for buttons inside imagemaps.
image_button:
(inherits from default)
(window, sound, hover) The default style used for image buttons.
image_button_image:
(inherits from default)
The default style used for images inside image buttons.
button:
(inherits from default)
(window, sound, hover) The default style used for buttons in the main and game menus.
button_text:
(inherits from default)
(text, hover) The default style used for the label of a button.
selected_button:
(inherits from button)
(window, hover) The style that is used for a selected button (for example, the active screen or a chosen preference).
selected_button_text:
(inherits from button_text)
(text, hover) The style that is used for the label of a selected button.
bar:
(inherits from default)
(bar) The style that is used by default for bars.
thin_hbox:
(inherits from hbox)
(box) A hbox with a small amount of spacing.
thick_hbox:
(inherits from hbox)
(box) A hbox with a large amount of spacing.
thin_vbox:
(inherits from vbox)
(box) A vbox with a small amount of spacing.
thick_vbox:
(inherits from vbox)
(box) A vbox with a large amount of spacing.
hyperlink:
(inherits from default)
The style of a hyperlink button.
hyperlink_text:
(inherits from default)
The stype of hyperlink button text.
gm_root:
(inherits from default)
(window) The style used for the root window of the game menu. This is primarily used to change the background of the game menu.
gm_nav_frame:
(inherits from default)
(window) The style used by a window containing buttons that allow the user to navigate through the different screens of the game menu.
gm_nav_vbox:
(inherits from thin_vbox)
(box) The style that is used by the box inside the gm_nav_frame
gm_nav_button:
(inherits from button)
(window, hover) The style of an unselected game menu navigation button.
gm_nav_button_text:
(inherits from button_text)
(text, hover) The style of the text of an unselected game menu navigation button.
gm_nav_selected_button:
(inherits from selected_button)
(window, hover) The style of a selected game menu navigation button.
gm_nav_selected_button_text:
(inherits from selected_button_text)
(text, hover) The style of the text of a selected game menu navigation button.
file_picker_entry:
(inherits from button)
(window, hover) The style that is used for each of the slots in the file picker.
file_picker_entry_box:
(inherits from thin_hbox)
(box) The style that is used for the hbox inside of a file picker entry.
file_picker_text:
(inherits from default)
(text) A base style for all text that is displayed in the file picker.
file_picker_new:
(inherits from file_picker_text)
(text) The style that is applied to the number of the new slot in the file picker.
file_picker_old:
(inherits from file_picker_text)
(text) The style that is applied to the number of the old slot in the file picker.
file_picker_extra_info:
(inherits from file_picker_text)
(text) The style that is applied to extra info in the file picker. The extra info is the save time, and the save_name if one exists.
file_picker_empty_slot:
(inherits from file_picker_text)
(text) The style that is used for the empty slot indicator in the file picker.
file_picker_frame:
(inherits from default)
(window) A window containing the file picker that is used to choose slots for loading and saving.
file_picker_frame_vbox:
(inherits from thin_vbox)
(box) The vbox containing both the nav and the grid in the file picker.
file_picker_navbox:
(inherits from thick_hbox)
(box) The box containing the naviation (next/previous) buttons in the file picker.
file_picker_nav_button:
(inherits from button)
(window, hover) The style that is used for enabled file picker navigation buttons.
file_picker_nav_button_text:
(inherits from button_text)
(text) The style that is used for the label of enabled file picker navigation buttons.
file_picker_grid:
(inherits from default)
The style of the grid containing the file picker entries.
yesno_frame:
(inherits from default)
(window) The style of a window containing a yes/no prompt.
yesno_frame_vbox:
(inherits from thick_vbox)
(box) The style of a box containing the widgets in a yes/no prompt.
yesno_label:
(inherits from default)
(text) The style used for the prompt in a yes/no dialog.
yesno_button:
(inherits from button)
(window, hover) The style of yes/no buttons.
yesno_button_text:
(inherits from button_text)
(window, hover) The style of yes/no button text.
error_root:
(inherits from default)
(window) The style of the window containing internal error messages.
error_title:
(inherits from default)
(text) The style of the text containing the title of an error message.
error_body:
(inherits from default)
(text) The style of the body of an error message.
skip_indicator:
(inherits from default)
(text) The style and placement of the skip indicator.
stybrow_button:
(inherits from default)
The style of buttons in the style browser.
stybrow_button_text:
(inherits from default)
The style of button text in the style browser.
mm_root:
(inherits from default)
(window) The style used for the root window of the main menu. This is primarily used to set a background for the main menu.
mm_menu_frame:
(inherits from default)
(window) A window that contains the choices in the main menu. Change this to change the placement of these choices on the main menu screen.
mm_menu_frame_vbox:
(inherits from thin_vbox)
(box) The vbox containing the main menu choices.
mm_button:
(inherits from button)
(window, hover) The style that is used on buttons that are part of the main menu.
mm_button_text:
(inherits from button_text)
(text, hover) The style that is used for the labels of buttons that are part of the main menu.
prefs_frame:
(inherits from default)
(window) A window containing all preferences.
prefs_pref_frame:
(inherits from default)
(window) A window containing an individual preference.
prefs_pref_vbox:
(inherits from thin_vbox)
(box) The style of the vbox containing a preference.
prefs_label:
(inherits from default)
(text) The style that is applied to the label of a block of preferences.
prefs_hbox:
(inherits from default)
If library.hbox_pref_choices is True, the style of the hbox containing the choices.
prefs_button:
(inherits from button)
(window, hover) The style of an unselected preferences button.
prefs_button_text:
(inherits from button_text)
(text, hover) The style of the text of an unselected preferences button.
prefs_selected_button:
(inherits from selected_button)
(window, hover) The style of a selected preferences button.
prefs_selected_button_text:
(inherits from selected_button_text)
(text, hover) The style of the text of a selected preferences button.
prefs_volume_slider:
(inherits from prefs_slider)
(bar) The style that is applied to volume sliders.
soundtest_button:
(inherits from prefs_button)
(window, hover) The style of an unselected preferences button.
soundtest_button_text:
(inherits from prefs_button_text)
(text, hover) The style of the text of an unselected preferences button.
prefs_slider:
(inherits from bar)
(bar) The style that is applied to preference sliders.
prefs_spinner:
(inherits from default)
The position of the prefs spinner.
prefs_spinner_label:
(inherits from prefs_label)
(text) This is the style that displays the value of a preference spinner.
prefs_spinner_button:
(inherits from prefs_button)
(window, hover) The style of the + or - buttons in a preference spinner.
prefs_spinner_button_text:
(inherits from prefs_button_text)
(text, hover) The style of the text of the + and - buttons in a preference spinner.
prefs_js_frame:
(inherits from prefs_pref_frame)
(window) The window containing a joystick mapping preference.
prefs_js_vbox:
(inherits from prefs_pref_vbox)
(box) A vbox containing a joystick mapping preference.
prefs_js_button:
(inherits from prefs_button)
(window, hover) The style of buttons giving a joystick mapping.
prefs_js_button_text:
(inherits from prefs_button_text)
(text, hover) The style of the text in buttons giving a joystick mapping.
js_frame:
(inherits from prefs_frame)
(window) The window containing the joystick message.
js_frame_vbox:
(inherits from thick_vbox)
(window) The vbox containing the joistick mapping message.
js_function_label:
(inherits from prefs_label)
(text, position) The style of the joystick mapping function name.
js_prompt_label:
(inherits from prefs_label)
(text, position) The style of the joystick mapping prompt message.
prefs_jump:
(inherits from prefs_pref_frame)
(window) The style of a window containing a jump preference.
prefs_jump_button:
(inherits from prefs_button)
(window, hover) The style of a jump preference button.
prefs_jump_button_text:
(inherits from prefs_button_text)
(text, hover) The style of jump preference button text.
prefs_column:
(inherits from default)
The style of a vbox containing a column of preferences.
prefs_left:
(inherits from prefs_column)
The position of the left column of preferences.
prefs_center:
(inherits from prefs_column)
The position of the center column of preferences.
prefs_right:
(inherits from prefs_column)
The position of the right column of preferences.
prefs_joystick:
(inherits from prefs_center)
The position of the column of joystick preferences.

Text Tags

Styles are useful if you want to change the look of entire blocks of text in the game. But what if you only want to change the look of a small amount of text, or if you want to only change the look of entire blocks of text. Text tags let you change the look of text within a single text widget.

Text tags work wherever text can be placed. This means that they can be used inside text widgets, text buttons, and menu and say statements. But please note that say statement protect from subsituting in a text tag, as that would most likely be an error. Generally, though, if Ren'Py shows text to the user, that text can be formatted through the use of text tags.

As an aside, let me point out that if you're using a text tag on every line of a script, or even many lines, you're probably doing something wrong. That's what styles are for.

Text tags start with a left brace, and continue to the matching right brace. We chose to use braces because they do not require quoting in HTML or BBCode. An open text tag may take a parameter, and then continues until a closing tag, which is a tag that has a slash immediately after the opening brace. Please note that text tags are sensitive to both case and whitespace.

Some example tags are {b}, {i}, {color=#f88}, {size=+16}, and {font=VeraIt.ttf}. The matching closing tags are {/b}, {i}, {/color}, {/size}, and {/font}. Tags must be properly nested: "{b}{i}bold + italic{/i}{/b}" is okay, but "{b}{i}this is wrong{/b}{/i}". Right now, improper nesting won't cause an error but it probably won't do what you want. All open tags must be closed by the end of the string.

There are two tags, {w} and {p}, that can only be used in dialogue. These tags cause a pause in the display of text, until the user clicks to continue, or an auto-forward occurs. This allows text to be displayed incrementally. The difference between {w} and {p} is that {p} adds a line break at the pause point. They do not use a closing tag.

There is a tag, {fast}, that only has an effect if the text speed is not infinite. This tag specifies where slow text should begin displaying from. Use this if you have two lines of dialogue where the second is an extension of the first. (This is an alternate way of achieving the pause effect.) This tag does not take a closing tag.

There is also an image tag {image=filename}, where filename is the name of an image file. The image tag does not take a closing tag. Images so including are placed as if they were text, and should be no larger than a single line of text.

If you, for some reason, want to include a left brace, just write two left braces ({{) instead.

Supported Text Tags

The following are supported text tags:

Here's an example of a say statement that uses many of the text tags. If you actually use this many text tags in a real game, you'll probably drive your users mad.

"Using text tags, we can make text {size=+12}bigger{/size} or
 {size=-8}smaller{/size}. We can make it {b}bold{/b}, {i}italic{/i},
 or {u}underlined{/u}. We can even change its {color=#f88}color{/color}."

SFonts

Ren'Py supports rendering text using SFonts as well as TrueType fonts. An SFont is a properly prepared image file, usually a PNG, containing images of the character in the font. Ren'Py has its own implementation of SFonts that supports an arbitrary unicode character set and kerning.

SFonts have several advantages and several disadvantages. One of the advantages is that SFonts are bitmap-based. This allows them to be distributed without having to worry about the copyrights associated with TrueType fonts (consult your lawyer!). Also, as SFonts are images, it's possible to apply effects to them that Ren'Py would not otherwise support. The downsides of SFonts come from the fact that Ren'Py isn't rendering. Because of this, one needs to supply another image to Ren'Py if one wants the font to be scaled, made bold or italic, underlined, or colorized.

To use SFonts, they must first be registered with Ren'Py using the renpy.register_sfont function. They can then be used by setting the font property of a style to the name of the SFont.

renpy.register_sfont (name=None, size=None, bold=False, italics=False, underline=False, filename=None, spacewidth=10, default_kern=0, kerns={}, charset=u'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'):

This registers an SFont with the given details. Please note that size, bold, italic, and underline are all advisory (used for matching), and do not change the appearance of the font.

name - The name of the font being registered. size - The size of the font being registered. bold - The boldness of the font being registered. italics - The italicness of the font being registered. underline - The underline of the font being registered.

filename - The file containing the sfont image. spacewidth - The width of a space character. default_kern - The default kern spacing between characters. kerns - A map from two-character strings to the kern that should be used between those characters. charset - The character set of the font. A string containing characters in the order in which they are found in the image.

The default character set for the font is:

! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~

Please note that you must register a sfont for each combination of font, size, bold, italic, and underline your game uses. Also note that since SFonts can't be recolored, one must register under a separate font name for each color. (Especially important when SFonts are used for button labels, to ensure that selected buttons look distinct from unselected ones.)

Obfuscating your Game

For some reason, many people seem to want to distribute their games in an obfuscated form, making it difficult to read the script, or to view the images associated with a game. Ren'Py supports this, to a point, by compiling scripts and allowing images to be archived. While a moderately skilled programmer could easily crack this obfuscation, it should be enough to protect a game from casual browsing.

Obfuscating the script is practically automatic. Every time the game runs, any .rpy file in the game directory is written out as an .rpyc file. These .rpyc files are enough to run the game, so simply running the game once (to create the .rpyc files) and then deleting (or more appropriately, moving away) the .rpy files will leave you with a runnable game with an obfuscated script. As a bonus, the .rpyc files are already parsed, improving game load time. (If a directory contains .rpy and .rpyc files with the same stem, the newer one of them is chosen, meaning all games get this performance improvement.)

Running Ren'Py with the --lock key command-line option will produce .rpyc files that are locked. These files will refuse to operate if a .rpyc file locked with a different key, or any .rpy file, would be loaded. Please note that this feature is discouraged, as it prevents the easy production of patches that work around issues in your game.

Images can be archived using the tools/archiver program that ships as part of Ren'Py. To use this, one can change into the game directory and run a command like:

../tools/archiver images *.png *.jpg

Alternatively on Windows, one can run tools/game_archive_images.bat directly, which will do the same thing.

This will create the file images.rpa in the game directory. One can then add to the script a line like:

init:
    $ config.archives = [ 'images' ]

Then, delete the .jpg and .png files from the game directory. Ren'Py will look in the images archive to find images that need to be loaded.

Localizing Ren'Py

While Ren'Py is by default set up to operate in an English speaking environment, it is not limited to such settings. Assuming a proper font is loaded, Ren'Py scripts can contain any language expressible in Unicode.

There are two things in the Ren'Py library that may need to be translated into a user's language. The first is the main menu. There is no explicit support for doing this, but as the library.main_menu variable supports changing the text of the main menu, it also supports translating said text.

The second thing that needs to be translated is the game menu. The library.translations dictionary is used to translate text in the game menu into your language. If a key in this map corresponds to the English text that would be displayed, the value corresponding to that key is displayed again. For example:

init:
    $ library.translations = {
        "Yes" : u"HIja'",
        "No" : u"ghobe'",
        # etc.
        }

The u characters prefixed to the strings on the right, while not strictly necessary in this case, are used to tell Python that the string is in Unicode rather than ASCII. This is useful if your language uses non-ascii characters.

Changing the Keymap

The variable config.keymap contains a map from functions that can be performed by the various user-interface elements of Ren'Py to a list of keysyms that actually perform those functions. Modifying the contents of the keymap can change the keys and mouse buttons that cause things to happen.

While this functionality has been added to Ren'Py at a user's request (and because it simplifies the Ren'Py code), it's not altogether clear that it should be used. Having a common set of keybindings makes games easier to play, by reducing the learning curve of users. It's probably better to build consensus around a change in keybindings, rather than unilaterally making something different from everyone else.

Anyway, in Ren'Py keysyms are strings. The first kind of keysym is of the form 'mouseup_#' or 'mousedown_#', for a number between 1 and 5. These keysyms are generated by mouse button presses, releases, or turns of the mouse wheel. For example, "mousedown_1" is generally a press of the left mouse button, "mouseup_1" is a release of that button, and "mousedown_4" is a turn of the the mouse wheel to the top.

A second kind of keysym is a joystick keysym. These begin with joy_. They are defined in library.joystick_keys, and mapped to actual joystick events by the user.

A third kind of keysym is a string containing a character that is generated when a key is pressed. This is useful for binding alphabetic keys and numbers. Examples of these keysyms include "a", "A", and "7".

The final kind of keysym is the symbolic name for the key. This can be any of the K_ constants taken from pygame.constants This type of keysym looks like "K_BACKSPACE", "K_RETURN", and "K_TAB".

To change a binding, update the appropriate list in config.keymap. The following code adds the 't' key to the list of keys that dismiss a say statement, and removes the space key from that list.

init:
    $ config.keymap['dismiss'].append('t')
    $ config.keymap['dismiss'].remove('K_SPACE')

The default keymap is contained inside the python code implementing Ren'Py, and as of version 5.3.1 is as follows:

config.keymap = dict(
    
    # Bindings present almost everywhere, unless explicitly
    # disabled.
    rollback = [ 'K_PAGEUP', 'mousedown_4', 'joy_rollback' ],
    screenshot = [ 's' ],
    toggle_fullscreen = [ 'f' ],
    toggle_music = [ 'm' ],
    game_menu = [ 'K_ESCAPE', 'mouseup_3', 'joy_menu' ],
    hide_windows = [ 'mouseup_2', 'h' ],
    launch_editor = [ 'E' ],
    dump_styles = [ 'Y' ],


    # Say.
    rollforward = [ 'mousedown_5', 'K_PAGEDOWN' ],
    dismiss = [ 'mouseup_1', 'K_RETURN', 'K_SPACE', 'K_KP_ENTER', 'joy_dismiss' ],

    # Focus.
    focus_left = [ 'K_LEFT', 'K_KP_LEFT', 'joy_left' ],
    focus_right = [ 'K_RIGHT', 'K_KP_RIGHT', 'joy_right' ],
    focus_up = [ 'K_UP', 'K_KP_UP', 'joy_up' ],
    focus_down = [ 'K_DOWN', 'K_KP_DOWN', 'joy_down' ],
        
    # Button.
    button_select = [ 'mouseup_1', 'K_RETURN', 'K_KP_ENTER', 'joy_dismiss' ],

    # Input.
    input_backspace = [ 'K_BACKSPACE' ],
    input_enter = [ 'K_RETURN', 'K_KP_ENTER' ],

    # These keys control skipping.
    skip = [ 'K_LCTRL', 'K_RCTRL' ],
    toggle_skip = [ 'K_TAB', 'joy_skip' ],
    fast_skip = [ '>' ],

    # These control the bar.
    bar_activate = [ 'mousedown_1', 'K_RETURN', 'K_KP_ENTER', 'joy_dismiss' ],
    bar_deactivate = [ 'mouseup_1', 'K_RETURN', 'K_KP_ENTER', 'joy_dismiss' ],
    bar_decrease = [ 'K_LEFT', 'joy_left' ],
    bar_increase = [ 'K_RIGHT', 'joy_right' ],
    )

UI Functions

While it's hoped that Ren'Py say and menu statements will be appropriate for much of the user interaction that goes on in a visual novel, we recognize that not all games can be fit in such a mold. To allow other, similar, games to be built, we've exposed the functions that we use to build the Ren'Py user interface. These functions are used both for normal gameplay, and to build the main and game menus. While these functions won't be enough for all games (Ren'Py will never be a RPG engine), hopefully these will allow the creation of, for example, schedule-management dating-simulation games.

To start, let's give a script snippet that uses the UI functions. The following displays a window containing three buttons, arraigned horizontally. The string assigned to choice varies depending on which of the three is picked.

$ ui.window()
$ ui.hbox()

$ ui.textbutton("A", clicked=ui.returns("A"))
$ ui.textbutton("B", clicked=ui.returns("B"))
$ ui.textbutton("C", clicked=ui.returns("C"))

$ ui.close()
$ choice = ui.interact(suppress_overlay=True)

To understand the ui functions, you must first understand the three kinds of widgets that Ren'Py supports. The first kind of widget (of which window is one), takes a single child widget. When this kind of widget is open, the next widget to be created is added to it, and it then closes automatically.

A second kind of widget can take an arbitrary number of child widgets. This kind of widget is exemplified by the layout widgets: vbox, hbox, and fixed. New widgets are added to this kind of widget until a matching call to ui.close() occurs, unless they are instead added to an open child of this widget.

The final kind of widget cannot take any children. This kind of widget is exemplified by textbutton.

Nothing is displayed on the screen until ui.interact() is called. Once it has been called, Ren'Py displays the screen to the user. It then waits for a widget to return a value. In the example given above, when a textbutton is clicked, the function returned by ui.returns is called, which in turn causes ui.interact to return the same value. When ui.interact returns, the screed is cleared of all transient ui elements, and control proceeds with the next statement. The ui functions must be called again if we want to show the same user interface to the user again.

It's important to ensure that, if a lambda or nested function is used as an argument to one of these ui functions, ui.interact() is called in the same python block. Failure to do this will prevent your game from saving, and that's probably a bad thing. ui.returns doesn't suffer from this problem, and so should probably be used in preference to lambda.

By default, widgets are added to the 'transient' layer. This can be changed by a call to ui.layer(), followed by a matching call to ui.close() when done adding widgets to the new layer.

Widgets can be added to a focus group by supplying the name of the focus group as the focus parameter to a ui widget. If the same focus group exists on two interactions, Ren'Py will ensure that if the nth widget is selected in the first interaction, the nth widget will be given focus at the start of the second interaction. If no widget is given focus in this way, then Ren'Py looks for one that has had the default=True argument supplied to it. If it finds such a widget, then it focuses it. Otherwise, it uses fallback rules to determine if a widget should be given focus.

The following are the functions available in the ui module, which is automatically present in the game namespace.

Single-Child Widgets

ui.window (**properties):

A window contains a single widget. It draws that window atop a background and with appropriate amounts of margin and padding, taken from the window properties supplied to this call. The next widget created is added to this window.

ui.frame (**properties):

A frame contains a single widget. This is similar to a window, but may be styled differently.

ui.button (clicked=None, **properties):

This creates a button that can be clicked by the user. When this button is clicked or otherwise selected, the function supplied as the clicked argument is called. If it returns a value, that value is returned from ui.interact().

Buttons created with this function contain another widget, specifically the next widget to be added. As a convenience, one can use ui.textbutton to create a button with a text label.

clicked - A function that is called when this button is clicked.

hovered - A function that is called when this button gains focus.

unhovered - A function that is called when this button loses focus.

ui.sizer (maxwidth=None, maxheight=None, **properties):

This is a widget that can shrink the size allocated to the next widget added. If maxwidth or maxheight is not None, then the space allocated to the child in the appropriate direction is limited to the given amount.

Please note that this only works with child widgets that can have a limited area allocated to them (like text), and not with ones that use a fixed area (like images).

maxwidth - The maximum width of the child widget, or None to not affect width.

maxheight - The maximum height of the child widget, or None ot not affect height.

Multiple-Child Widgets

ui.vbox (spacing=None, style='vbox', **properties):

This creates a layout that places widgets next to each other, from top to bottom. New widgets are added to this vbox until ui.close() is called.

spacing - The number of pixels to leave between widgets. If None, take the amount of spacing from the style.

ui.hbox (spacing=None, style='hbox', **properties):

This creates a layout that places widgets next to each other, from left to right. New widgets are added to this hbox until ui.close() is called.

spacing - The number of pixels to leave between widgets. If None, take the amount of spacing from the style.

ui.grid (cols, rows, padding=0, transpose=False, **properties):

This creates a layout that places widgets in an evenly spaced grid. New widgets are added to this grid unil ui.close() is called. Widgets are added by going from left to right within a single row, and down to the start of the next row when a row is full. All cells must be filled (that is, exactly col * rows widgets must be added to the grid.)

The children of this widget should have a fixed size that does not vary based on the space allocated to them. Failure to observe this restriction could lead to really odd layouts, or things being rendered off screen. This condition is relaxed in the appropriate dimension if xfill or yfill is set.

Each cell of the grid is exactly the same size. By default, the grid is the smallest size that can accommodate all of its children, but it can be expanded to consume all available space in a given dimension by setting xfill or yfill to True, as appropriate. (Otherwise, xfill and yfill are inherited from the style.)

cols - The number of columns in this grid. rows - The number of rows in this grid. padding - The amount of space to leave between rows and columns. xfill - True if the grid should consume all available width. yfill - True if the grid should consume all available height. transpose - If True, grid will fill down columns before filling across rows.

ui.fixed (**properties):

This creates a layout that places widgets at fixed locations relative to the origin of the enclosing widget. The layout takes up the entire area allocated to it. New widgets are added to this widget.

No-Child Widgets and Psuedo-Widgets

ui.text (label, **properties):

This creates a widget displaying a text label.

label - The text that will be displayed on the screen. It uses font properties. The label can also be a list containing both text strings in widgets, in the case of a widget, the widget is displayed as if it was text of the enclosing font. The height of the area allocated is that of the font, with the width being taked from a render of the widget.

slow - If True, text is displayed slowly, controlled by the appropriate preference.

slow_speed - If slow is True, then this is the number of cps the text is displayed at, overriding the preference.

slow_done - If not None and slow is True, this is a callback that is called when we're done displaying text on the screen.

ui.image (im, **properties):

This loads an image, and displays it as a widget. The image may be the name of a file containing the image, or an object constructed with one of the im methods.

ui.textbutton (text, clicked=None, text_style='button_text', **properties):

This creates a button that is labelled with some text. When the button is clicked or otherwise selected, the function supplied as the clicked argument is called. If it returns a value, that value is returned from ui.interact().

text - The text of this button.

clicked - A function that is called when this button is clicked.

text_style - The style that is used for button text.

ui.imagebutton (idle_image, hover_image, clicked=None, image_style='image_button_image', **properties):

This creates a button that contains two images. The first is the idle image, which is used when the mouse is not over the image, while the second is the hover image, which is used when the mouse is over the image. If the button is clicked or otherwise selected, then the clicked argument is called. If it returns a value, that value is returned from ui.interact().

idle_image - The file name of the image used when this button is idle.

hover_image - The file name of the image used when this button is hovered.

clicked - The function that is called when this button is clicked.

image_style - The style that is applied to the images that are used as part of the imagebutton.

ui.imagemap (ground, selected, hotspots, unselected=None, style='imagemap', button_style='imagemap_button', **properties):

This is called to create imagemaps. Parameters are roughtly the same as renpy.imagemap. The value of the hotspot is returned when ui.interact() returns.

ui.menu (menuitems, style='menu', caption_style='menu_caption', choice_style='menu_choice', choice_chosen_style='menu_choice_chosen', choice_button_style='menu_choice_button', choice_chosen_button_style='menu_choice_chosen_button', location=None, **properties):

This creates a new menu widget. Unlike the menu statement or renpy.menu function, this menu widget is not enclosed in any sort of window. You'd have to do that yourself, if it is desired.

menuitems - A list of tuples that are the items to be added to this menu. The first element of a tuple is a string that is used for this menuitem. The second element is the value to be returned from ui.interact() if this item is selected, or None if this item is a non-selectable caption.

location - Some serializable and hashable object that represents the location of this menu in the game. (Normally, this is the name of the statement executing the menu.) If provided, then this logs which menuitems have been chosen, and changes the style of those menuitems to the choice_seen_style.

ui.bar (*args, **properties):

This creates a bar widget. The bar widget can be used to display data in a bar graph format, and optionally to report when the user clicks on a location in that bar.

width - The width of the bar. If clicked is set, this includes the gutters on either side of the bar.

height - The height of the bar.

range - The range of values this bar can undertake. The bar is completely full when its value is this number.

value - The value of this bar. It must be between 0 and range, inclusive.

@clicked clicked: This is called when the mouse is clicked in this widget. It is called with a single argument, which is the value corresponding to the location at which the mouse button was clicked. If this function returns a value, that value is returned from ui.interact().

For best results, if clicked is set then width should be at least twice as big as range.

ui.null (**properties):

This widget displays nothing on the screen. Why would one want to do this? If a widget requires contents, but you don't have any contents to provide it.

ui.saybehavior (afm=None):

This is a psuedo-widget that adds the say behavior to the screen. The say behavior is to return True if the left mouse is clicked or enter is pressed. It also returns True in various other cases, such as if the current statement has already been seen. This widget should not be added to any other widget, but should instead be only added to the screen itself.

If afm is present, it is a block of text, that's given to the auto forwarding mode algorithm to determine the auto-forwarding timeout.

ui.pausebehavior (delay, result=False):

This is a psuedo-widget that adds the pause behavior to the screen. The pause behavior is to return the supplied result when the given number of seconds elapses. This widget should not be added to any other widget, but should instead be only added to the screen itself.

Please note that this widget will always pause for the given amount of time. If you want a pause that can be interrupted by the user, add in a saybehavior.

delay - The amount of time to pause, in seconds.

result - The result that will be retuned after the delay time elapses.

Functions

ui.add (w, make_current=False, once=False):

This is used to add a displayable to the current widget. If make_current is True, then the widget is made the current widget. If once is True, then the displayable will be made the current widget, but only for the next widget to be added.

ui.clear ():

Clears the current layer of widgets.

ui.interact (**kwargs):

Displays the current scene to the user, waits for a widget to indicate a return value, and returns that value to the user. As a side-effect, disables fast skip mode when executed.

Some useful keyword arguments are:

show_mouse - Should the mouse be shown during this interaction? Only advisory, as this doesn't work reliably.

suppress_overlay - This suppresses the display of the overlay during this interaction.

ui.layer (name):

This causes widgets to be added to the named layer, until a matching call to ui.close().

ui.close ():

This closes the currently open widget or layer. If a widget is closed, then we start adding to its parent, or the layer if no parent is open. If a layer is closed, we return to the previously open layer. An error is thrown if we close the last open layer.

ui.returns (value):

This function returns a function that, when called, returns the supplied value. It's best used to supply the clicked argument to the various button widgets.

ui.jumps (label):

This function returns a function that, when called, jumps the game to the given label, ending the current interaction in the process. It's best used to supply the clicked argument to the various button widgets.

ui.jumpsoutofcontext (label):

This function returns a function that, when called, exits the current context, and in the parent context jumps to the named label. It's intended to be used as the clicked argument to a button.

Image Manipulators

Image manipulators are objects that can return images. Every image manipulator can be used as a widget, but the opposite is not true. Image manipulators are used to implement the Image function, but constructing them directly can give you finer control.

When an image manipulator requires another as input, the second image manipulator can be specified in any of a number of ways. The first way is as a string, which is turned into an im.Image. The second is a tuple, which is turned into an im.Composite using the rules for tuples given in Image. The third is that an image manipulator can be specified directly, in which case it is passed through unchanged.

Widgets may not be used as arguments to image manipulators. This is because image manipulators are very efficent, caching the computed images on their first load.

The image manipulators are:

im.Image (filename, **properties):

This image manipulator loads an image from a file.

filename - The filename that the image will be loaded from.

im.Crop (im, x, y, w, h, **properties):

This crops the image that is its child.

im.Scale (im, width, height, **properties):

This is an image manipulator that scales another image manipulator to the specified width and height. This scalling is unfiltered, so you can expect your image to look a bit jagged.

im.Rotozoom (im, angle, zoom, **properties):

This is an image manipulator that is a smooth rotation and zoom of another image manipulator.

im - The image to be rotozoomed.

angle - The number of degrees counterclockwise the image is to be rotated.

zoom - The zoom factor. Numbers that are greater than 1.0 lead to the image becoming larger.

im.Recolor (im, rmul=im.ramp(0, 255), gmul=im.ramp(0, 255), bmul=im.ramp(0, 255), amul=im.ramp(0, 255), force_alpha=False, **properties):

This adjusts the colors of the image that is its child. It takes as an argument 4 numbers between 0 and 255, and maps each channel of the image linearly between 0 and the supplied color.

im.Alpha (image, alpha, **properties):

Returns an alpha-mapped version of the image. Alpha is the maximum alpha that this image can have, a number between 0.0 (fully transparent) and 1.0 (opaque).

If an image already has an alpha channel, values in that alpha channel are reduced as appropriate.

im.Map (im, rmap=im.ramp(0, 255), gmap=im.ramp(0, 255), bmap=im.ramp(0, 255), amap=im.ramp(0, 255), force_alpha=False, **properties):

This adjusts the colors of the image that is its child. It takes as arguments 4 256 character strings. If a pixel channel has a value of 192, then the value of the 192nd character in the string is used for the mapped pixel component.

im.ramp (start, end):

Returns a 256 character linear ramp, where the first character has the value start and the last character has the value end. Such a ramp can be used as a map argument of im.Map.

im.Tile (im, size=None, **properties):

This tiles the image, repeating it vertically and horizontally until it is as large as the specified size. If no size is given, then the size defaults to the size of the screen.

im.Composite (size, *args, **properties):

This image manipulator composites one or more images together.

This takes a variable number of arguments. The first argument is size, which is either the desired size of the image (in pixels), or None to indicate that the size should be the size of the first image.

It then takes an even number of further arguments. (For an odd number of total arguments.) The second and other even numbered arguments contain position tuples, while the third and further odd-numbered arguments give images (or image manipulators). A position argument gives the position of the image immediately following it, with the position expressed as a tuple giving an offset from the upper-left corner of the image. The images are composited in bottom-to-top order, with the last image being closest to the user.

Low-Level Audio Functions

Here, we give functions that allow for low-level control of the audio subsystem. There are two kinds of audio that we can play. The sound subsystem plays audio, but doesn't attempt in any way to make the audio that is played persistent. The music subsystem, on the other hand, handles saving and restoring the music as the game's situation changes. Use the sound functions to play sound effects, or to implement your own method of playing music. Use the music functions when you want music to be restored after playing and loading.

Ren'Py supports 8 channels of audio. The first three channels (0-2) are dedicated to sound effects, while the rest (3-7) are intended for music. When voice is used, channel 2 is reserved for voice. All channels support playing compressed waveform audio. We support wav, mp3, ogg vorbis, ogg speex, and various mod formats, including xm. We also support midi, but impose that the requirement that only one channel can be playing midi at a time.

Both sound and music functions deal with a queue of audio files. This queue contains the files that will be played after the currently playing file finishes. When looping, if the queue becomes empty the last-queued file is added to the queue.

When synchro-start is enabled on two or more channels, the system waits for all of the channels to stop playing before playing the new files on those channels. All of the channels are started simultaneously, in a sample-accurate manner.

Sound Functions

renpy.sound.play (filename, channel=0, fadeout=0, fadein=0, tight=False):

Plays the named file once on the given channel. This will cause any playing sound effect to be stopped (after the given fadeout number of seconds, if necessary), and the new sound to be played in its place. The sound is faded in for the given number of seconds.

The filename may be that of a file in an archive.

If tight is True, then a fadeout of this sound will continue into the next-queued sound.

renpy.sound.queue (filename, channel=0, clear_queue=True, fadein=0, tight=False):

This causes the named file to be queued to be played on the given channel. If clear_queue is True, the queue will be cleared before playback, so this sound is played immediately after the currently playing sound. If False, the channel's queue will not be cleared, and the sound will only be played after every other playing sound. If no sound is currently playing, then the sound will be played immediately.

renpy.sound.stop (channel=0, fadeout=0):

This dequeues everything from the given channel, and stops the currently playing sound. If fadeout is 0, the sound is stopped immediately. Otherwise, it is interpreted as a number of seconds to fadeout for.

renpy.sound.is_playing (channel=0):

Returns True if the channel is currently playing a sound, False if it is not, or if the sound system isn't working.

This works with both sound and music channels, although it's intended for the former.

renpy.sound.set_volume (volume, channel=0):

Sets the volume of this channel, as a fraction of the volume of the mixer controlling the channel.

This volume is not persisted or rolled-back, as are volumes set with renpy.music.set_volume for music channels.

renpy.sound.set_mixer (channel, mixer):

This sets the name of the mixer associated with a given channel. By default, there are two mixers, 'sfx' and 'music'. 'sfx' is on channels 0 to 3, and 'music' on 3 to 7. The voice module calls this function to set channel 2 to voice. You can create your own mixer, but will need to add a preference if you wish to allow the user to set it.

This function should only be called in an init block.

renpy.sound.set_queue_empty_callback (callback, channel=0):

This sets a callback that is called when the queue is empty. This callback is called when the queue first becomes empty, and at least once per interaction while the queue is empty.

The callback is called with no parameters. It can queue sounds by calling renpy.sound.queue with the appropriate arguments. Please note that the callback may be called while a sound is playing, as long as a queue slot is empty.

Music Functions

The music functions persists the information about playing music, allowing the music to be restored after a rollback, return from a menu, or load. What is saved is the time of the last change of music, and the last queued file or files. If the persistent time of last music change is different than what is currently playing, the system dequeues all queued music. It then check to see if the playing music is not one of the from the persisted last queued music filenames. If so, it stops the playing music. It then plays in a loop the last queued music, and sets the currently known last change time to the persisted last change time.

renpy.music.play (filenames, channel=7, loop=True, fadeout=None, synchro_start=False, fadein=0, tight=False, if_changed=False):

This stops the music currently playing on the numbered channel, dequeues any queued music, and begins playing the specified file or files. If loop is True, the tracks will loop while they are the last thing in the queue. If fadeout is None, the fadeout time is taken from config.fade_music, otherwise it is a time in seconds to fade for.

Filenames may be a single file, or a list of files.

Fadein is the number of seconds to fade the music in for, on the first loop only.

If synchro_start is given, all the channels that have had play called on them with synchro_start set to True will be started at the same time, in a sample accurate manner.

The filenames given becomes the last queued files if loop is True. If loop is False, then there are no last queued files.

If tight is True, then fadeouts will span into the next-queued sound.

If if_changed is True, and the music file is currently playing, then it will not be stopped/faded out and faded back in again, but instead will be kept playing. (This will always queue up an additional loop of the music.)

renpy.music.queue (filenames, channel=7, loop=True, clear_queue=True, fadein=0, tight=False):

This queues the given filenames on the specified channel. If clear_queue is True, then the queue is cleared, making these files the files that are played when the currently playing file finishes. If it is False, then these files are placed at the back of the queue. In either case, if no music is playing these files begin playing immediately.

Filenames may either be a single filename, or a list of filenames.

Fadein is the number of seconds to fade the music in for, on the first loop only.

If loop is True, then this music will repeat as long as it is the last element of the queue.

The filenames given becomes the last queued file if loop is True. If loop is False, then the last queued file is set to None.

If tight is True, then fadeouts will span into the next-queued sound.

renpy.music.stop (channel=7, fadeout=None):

This stops the music that is currently playing, and dequeues all queued music. If fadeout is None, the music is faded out for the time given in config.fade_music, otherwise it is faded for fadeout seconds.

This sets the last queued file to None.

renpy.music.set_volume (volume, channel=7):

This sets the volume of the given channel. The volume is a number between 0 and 1.0, and is interpreted as a fraction of the mixer volume for the channel.

This value is persisted, and takes effect immediately. It also participates in rollback.

renpy.music.set_music (channel, flag):

This should be called to indicate if the given channel should be treated as a music channel. If the flag is True, the channel will be treated as a music channel, if False, the channel will be treated as a sound effects channel. Please note that this will not change the mixer controlling the channel. Use renpy.sound.set_mixer to do that.

By default, channels 3-7 are considered music channels.

Themes

Themes provide a simple way of changing the look of the main and game menus. A single function call applies styles to many of the elements of the main and game menus, giving a consistent look to the interface. These colors, and the background images used, can be changed by supplying parameters to the theme functions.

Theme functions should be called after the config.screen_width, config.screen_height, and library.script_version variables have been set. They should be called before any style is changed by hand.

Roundrect themes. Roundrect themes turn buttons and windows into rounded rectangles, giving a fairly modern look. (Albeit one inspired by the original Macintosh.)

theme.roundrect (widget=(0, 60, 120, 255), widget_hover=(0, 80, 160, 255), widget_text=(200, 225, 255, 255), widget_selected=(255, 255, 200, 255), disabled=(64, 64, 64, 255), disabled_text=(200, 200, 200, 255), label=(255, 255, 255, 255), frame=(100, 150, 200, 255), window=(0, 0, 0, 192), mm_root=..., gm_root=..., centered=False, button_menu=True):

This enables the use of the roundrect theme. By default, this theme styles the game in a blue color scheme. However, by supplying one or more of the parameters given below, the color scheme can be changed.

widget - The background color of non-focued buttons and sliders.

widget_hover - The background color of focused buttons and sliders.

widget_text - The text color of non-selected buttons.

widget_selected - The text color of selected buttons.

disabled - The background color of disabled buttons.

disabled_text - The text color of disabled buttons.

label - The text color of non-selected labels.

frame - The background color of frames.

mm_root - A displayable (such as an Image or Solid) that will be used as the background for the main menu.

gm_root - A displayable (such as an Image or Solid) that will be used as the background for the game menu.

centered - If True, the buttons and sliders will be centered in the frames or windows that contain them. If False, the default, they will be pushed to the right side.

theme.roundrect_red (**params):

This sets up a red/pink variant of the roundrect theme.

Customizing the Main and Game Menus

This section describes how the content of the various menus can be customized. If you just want to change the look of the menus (to the extent made possible by the style system), use styles. To change just the text of menu items, consider using library.translations. To change just the position of buttons in a menu, use library.game_menu_positions and library.main_menu_positions.

Main Menu

The main menu can be customized by setting the library.main_menu variable. This variable should be a list of pairs. The first element of each pair is the name of the button on the main menu. The second item can be one of three things. It can be a string, in which case it is a label at which the game execution starts (after a jump out of the menu context). It can be a function, in which cas the function is called when the button is clicked. Finally, it can be None, which causes the button to be insensitive.

If one wants to change the main menu each time it is invoked, but keep the look of it the same, then the thing to do is to provide a main_menu label. The code after this main_menu label should set library.main_menu, and then jump to _library_main_menu. This is useful, for example, if there are some items in the main menu that should be absent or disabled until some condition is met. (Say, the user reaching an ending for the first time.)

Finally, it may be desirable to write your own menu from scratch. This is done by creating the menu using ui functions called from code invoked through the main_menu label. To start the game, the code should jump out of the context, using ui.jumpsoutofcontext() or renpy.jump_out_of_context(). The code can also jump to any of the game menu screens, which can be reached at the labels "_load_screen", "_save_screen" and "_prefs_screen", to display the appropriate screen. When interacting with the user, ui.interact() should be called with suppress_overlay=True, suppress_underlay=True, and perhaps mouse="mainmenu".

The functions that are used to make a game menu screen, _game_nav() and _game_interact(), should also work with the main menu screen. When necessary, renpy.context().main_menu can be checked to see if we are in the main menu (it is True) or game menu (it is False).

Game Menu

The first thing one may wish to do when modifying the game menu is to add a screen to it. This is done in two steps. The first is to create the screen, and the second is to add it to the library.game_menu list so that it can be reached from the game menu.

Each screen is represented in the code as a label that is jumped to to display the screen. There are five steps that this label should do in order to display the screen. First, it should call _game_nav(screen), where screen is the name of the screen (the first component of the tuples in library.game_menu, described below). Second, it should call the ui functions to actually draw the screen. Third, it should call _game_interact, instead of ui.interact, to interact with the user. This ensures that the game menu interaction is handled properly. Fourth, it should examine the results of _game_interact, and react appropriately. Finally, it should jump back up to the screen label, showing the screen again after each interaction.

So that the user can see it, the screen should be added to library.game_menu. This is a list of four-component tuples. The first is the name of the screen. It's used to determine if the button used to reach that screen should be indicated as selected. The second component is the text used for that button. The third component is a function that executes when the button is clicked. Normally, an appropriate function is ui.jumps('label'), where label is the name of the label under which your screen was defined above. Finally, the fourth parameter is a string containing a python expression. If the expression is not true, the button is insensitive.

To customize the game menu navigation buttons, one can customize _game_nav(). This takes one parameter, the screen we're at. Default parameters for this are "restart", "load", "save", "prefs", "quit".

game_nav = "_load_screen"

One can customize the screen the game menu jumps to by default by changing the value of _game_menu_screen. For example, one could set this to "_load_screen" for the first few interactions, and then set it to "_save_screen" for the rest of the game. This is especially useful for a game with no main menu.

There is a convenience function for prompting the user for their response to a yes and no question.

_yesno_prompt (screen, message):

screen - The screen button that should be highlighted when this prompt is shown. If None, then no game menu navigation is shown.

message - The message that is shown to the user to prompt them to answer yes or no.

This function returns True if the user clicks Yes, or False if the user clicks No.

Preferences

Finally, it is possible to customize the preferences. This is done by modifying library.preferences, which is a dictionary mapping from vbox style to a list of preferences to be placed in that vbox. Modifying this dictionary and lists can move preferences around, and eliminate preferences entirely. It may be desirable to create new vbox styles, by using style.create().

To create an entirely new preference, create it with _Preference, _SliderPreference, or _VolumePreference, and then add it to an appropriate list in library.preferences.

_Preference (name, field, values, base=...):

This is a class that's used to represent a multiple-choice preference.

name - The name of this preference. It will be displayed to the user.

variable - The field on the base object that will be assigned the selected value. This field must exist.

values - A list of value name, value, condition triples. The value name is the name of this value that will be shown to the user. The value is the literal python value that will be assigned if this value is selected. The condition is a condition that will be evaluated to determine if this is a legal value. If no conditions are true, this preference will not be displayed to the user. A condition of None is always considered to be True.

base - The base object on which the variable is read from and set. This defaults to _preferences, the user preferences object.

_SliderPreference (name, range, get, set, enable='True'):

A class that represents a preference that is controlled by a slider.

set - The name of this preference, that is shown to the user.

range - An integer giving the maximum value of this slider. The slider goes from 0 to range.

get - A function that's called to get the initial value of the slider. It's called with no arguments, and should return an integet between 0 and range, inclusive.

set - A function that's called when the value of the slider is set by the user. It is called with a single integer, in the range 0 to range, inclusive.

enable - A string giving a python expression. If the expression is evaluates to false, this preference is not shown.

_VolumePreference (name, mixer, enable='True', sound='None', channel=0):

This represents a preference that controls one of the volumes in the system. It is represented as a slider bar, and a button that can be pushed to play a sample sound on a channel.

name - The name of this preference, as shown to the user.

mixer - The mixer this preference controls.

enable - A string giving a python expression. If the expression is evaluates to false, this preference is not shown.

sound - A string that is evaluated to yield another string. The yielded string is expected to give a sound file, which is played as the sample sound. (We apologize for the convolution of this.)

channel - The number of the channel the sample sound is played on.

_remove_preference (name):

Removes the preference with the given name from the preferences menu.

Developer Tools

Ren'Py includes a number of features to make a developer's life easier. Many of them need the variable config.developer to be set to True to operate.

Editor Support

The config.editor variable allows a developer to specify an editor command that is run when the launch_editor keypress (by default, shift-E) occurs.

Please see http://www.bishoujo.us/renpy/scite.html for information about how to integrate Ren'Py with the SciTE text editor.

Style Dumping

When config.developer is True, pressing the dump_styles key (by default, shift-Y), will write a description of every style Ren'Py knows about to the file styles.txt. This description includes every property that is part of the style, the value of that property, and the style the property is inherited from.

Fast Skipping

When config.developer is True, pressing the fast_skip key (by default, '>') causes the the game to immediately skip to the next important interaction. For this purpose, an important interaction is one that is not caused by a say statement, transition, or pause command. Usually, this means skipping to the next menu, but it will also stop when user-defined forms of interaction occur.

Warping to a Line

Ren'Py supports warping to a line in the script, without the developer to play through the entire game to get there. While this warping technique has a number of warnings associated with it, it still may be useful in providing a live preview.

To invoke warping, run Ren'Py with the --warp command-line argument followed by a filename:line combination, to specify where you would like to warp to. For example:

run_game --warp script.rpy:458

When warping is invoked, Ren'Py does a number of things. It first finds all of the scene statements in the program. It then tries to find a path from the scene statements to every reachable statement in the game. It then picks the reachable statement closest to, but before or at, the given line. It works backwards from that statement to a scene statement, recording the path it took. Ren'Py then executes the scene statement and any show or hide statements found along that path. Finally, it transfers control to the found statement.

There are a number of fairly major caveats to the warp feature. The first is that it only examines a single path, which means that while the path may be representative of some route of execution, it's possible that there may be a bug along some other route. In general, the path doesn't consider game logic, so it's also possible to have a path that isn't actually reachable. (This is only really a problem on control-heavy games, espcially those that use alot of python code.

The biggest problem, though, is that no python code is executed before the statement that is warped to. This means that all variables will be uninitalized, which can lead to crashes when they are used. To overcome this, one can define a label 'after_warp', which is called after a warp but before the warped-to statement executes. The code reached by this label can set up variables in the program, and then return to the preview.

The warp feature requires config.developer to be True to operate.

Default Definitions

This section documents a number of definitions that are found in the Ren'Py standard library. These include default instatiations of the various transitions and placements, and even one image.

These definitions are found in common/definitions.rpy. You shouldn't change them there, but should instead copy the corresponding line into your script file, and change that instead.

Positions

left
A Position in which the left side of the image is aligned with the left side of the screen.
right
A position in which the right side of the image is aligned with the right side of the screen.
center
A position in which the image is centered horizontally on the screen.
offscreenleft
A position in which the image is placed just off the left side of the screen. Please note that an image placed in this position, while not visible to the user, still consumes resources, and so images should be hidden when not visible. This position is intended to be used with the move transition.
offscreenright
A position in which the image is placed just off the right side of the screen. Please note that an image placed in this position, while not visible to the user, still consumes resources, and so images should be hidden when not visible. This position is intended to be used with the move transition.

Transitions

fade
An instance of the Fade transition that takes 0.5 seconds to fade to black, and then 0.5 seconds to fade to the new screen.
dissolve
An instance of the Dissolve transition that takes 0.5 seconds to complete.
pixellate
An instance of the Pixellate transition, which takes 1 second to complete, and creates pixels as big as 32x32 over the course of 5 steps in either direction.
move
An instance of the MoveTransition transition, this takes 0.5 seconds to move images that changed position to their new locations.
vpunch
When invoked, this transition shakes the screen vertically for a quarter second.
hpunch
When invoked, this transition shakes the screen horizontally for a quarter second.
blinds
Transitions the screen in a vertical blinds effect lasting 1 second.
squares
Transitions the screen in a vertical blinds effect lasting 1 second.
wiperight
An instance of CropMove that takes 1 second to wipe the screen right.
wipeleft
An instance of CropMove that takes 1 second to wipe the screen left.
wipeup
An instance of CropMove that takes 1 second to wipe the screen up.
wipedown
An instance of CropMove that takes 1 second to wipe the screen down.
slideright
An instance of CropMove that takes 1 second to slide the screen right.
slideleft
An instance of CropMove that takes 1 second to slide the screen left.
slideup
An instance of CropMove that takes 1 second to slide the screen up.
slidedown
An instance of CropMove that takes 1 second to slide the screen down.
slideawayright
An instance of CropMove that takes 1 second to slide the screen away and to the right.
slideawayleft
An instance of CropMove that takes 1 second to slide the screen away and to the left.
slideawayup
An instance of CropMove that takes 1 second to slide the screen away and to the up.
slideawaydown
An instance of CropMove that takes 1 second to slide the screen away and to the down.
irisout
An instance of CropMove that irises the screen out for 1 second.
irisin
An instance of CropMove that irises the screen in for 1 second.

Images

black
This is a predefinition of a Solid black image. It's here to serve as a reasonable default image, for use in tutorials and incomplete games.

Function Index

Variable Index

Property Index

Style Index

Style Hierarchy

This shows the inheritance relationship between styles.

Definition Index

Example Script

For your browsing pleasure, we present a syntax-highlighted version of the demo that ships with Ren'Py. The start of this script has been commented to make it easier to understand.