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-02-12 20:09

  1. A Simple Ren'Py Script
  2. The Structure of a Ren'Py Script
  3. Lexical Structure of Statements
  4. Grammar Rules
  5. Dialogue: The Say Statement
  6. Menus
  7. Displaying Images
  8. Image and Scene Functions
  9. Transitions
  10. Control Statements
  11. Python Statements
  12. Starting a Game
  13. Saving, Loading, and Rollback
  14. Persistent Data
  15. Interaction Functions
  16. Overlays
  17. Multimedia: Sound, Music, and Movies
  18. Configuration Variables
  19. Properties and Styles
  20. Text Tags
  21. Obfuscating your Game
  22. Localizing Ren'Py
  23. Changing the Keymap
  24. UI Functions
  25. Image Manipulators
  26. Low-Level Audio Functions
  27. Customizing the Main and Game Menus
  28. Developer Tools
  29. Default Definitions
  30. Function Index
  31. Variable Index
  32. Property Index
  33. Style Index
  34. Style Hierarchy
  35. Definition Index
  36. 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 = Image("whitehouse.jpg")
    image eileen happy = Image("eileen_happy.png")
    image eileen upset = Image("eileen_upset.png")

label start:
    $ e = Character('Eileen')

    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 Structure of a Ren'Py Script

The largest division of a Ren'Py script is into files. By default, Ren'Py reads the script from all files ending in .rpy found in the game underneath the directory in which Ren'Py is installed. These script files may be read in any order, and all of them together make up a Ren'Py script.

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:

These rules should be the same as for Python.

Ren'Py also supports 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. In the following example:

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

There 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. Other blocks may contain menu entries 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.

Lexical Structure of Statements

Before we can discuss statements, however, we must first discuss the tokens statements are built up out of. So here's a short list of all the tokens we use.

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

at
call
hide
if
image
init
jump
menu
onlayer
python
return
scene
set
show
with
while

A names consist of an alphabetic character or number, followed by zero or more alphabetic characters or underscores, so long as the string isn't a keyword. For our purpose, unicode characters between 00a0 and fffd are considered to be alphabetic characters.

An image_name is a list of one or more names, separated by a space.

A string begins with a " or a ', and continues until a matching unescaped " or ' is reached. Runs of whitespace inside a string are collapsed into a single space character, allowing strings to span multiple lines. The \ character is used inside the string to escape special characters, such as whitespace, quotes, and (as \n) to include a newline.

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:

In general, simple expressions are strings, names, or method calls. They are not expected to contain operators.

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.

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. Parenthesis are used to group things together, but they don't correspond to anything in the source code. 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 (->).

Dialogue: The Say Statement

As the bulk of the content of a visual novel is presented to the user in the form of dialogue or thoughts, it's important that the ability to display text to the user be as convenient as possible. In Ren'Py, both actions are done through the say statement. The say statement doesn't require a keyword to introduce it. Instead, it consists of either a single string, or a simple_expression followed by a string.

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

We can distinguish two forms of the say statement, depending on if the simple_expression is provided. The single-argument form of say consists only of a single string. This form causes the string to be displayed to the user without any label as to who is saying it. Conventionally, this is used to indicate to the user 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 first evaluates the expression to see what its value is. If the expression returns a string, that string is used as a character name to indicate who is saying the dialogue. If it returns an object, that object is responsible for displaying the dialogue to the user.

The most common type of object used in a dialogue statement is a Character object. Character objects have associated with them a name and a color. When a character object is asked to display a line of dialogue, it labels it with the character name in the character's signature color. In general, strings are used to indicate the names of lesser characters or ones who we have not discovered the name of yet, while character objects are used to indicate important characters.

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

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

Finally, the string in a dialogue is subject to interpolation of variables. A string variable can be interpolated with %(name)s, while a number requires %(name)d. The interpolated value is quoted so that a text tag cannot be interpolated in by mistake. For example:

e "I know all about you."

e "I know that you're %(player_age)d years old, and your zodiac
   sign is %(player_sign)s."

When the first object is a character object, that character object is given given complete control over how text is displated. As an example of this, the standard library includes a character object called "centered", which displays the text centered on the screen, without any background window.

centered "American Bishoujo presents..."
centered "The Ren'Py Demo Game"

The way this is done is that the character object is called with the string to display. The character object doesn't actually have to be a Character object, it can be any python callable. It's responsible for displaying the dialogue to the user. In the case of a thought, the contents of the narrator variable is used to display the text to the user.

narrator = ...
A function that expects a single string as input, that is called to display narration to the user.

The say statement also takes a with clause that is used to control the transition that is used to introduce the dialogue or thought. Please see the section on transitions for details on how to use the with clause.

Menus

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

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

A menu statement consists simply of the word 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. (See the section on control flow for details about the label statement.)

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

caption_menuitem -> string

The first kind of menuitem is simply 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 the choice. 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. The terminating colon is what indicates that this menuitem is a choice.

set_menuitem -> "set" simple_expression

The third kind of menuitem gives an expression that yields a set. There may only be one of this kind of menuitem per menu. If present, it's used to filter the list of choices shown to the user.

with_menuitem -> "with" simple_expression

The final kind of menuitem is a with clause. This is used to specify the transition that introduces this menu. Please see the section on transitions for a discussion of this.

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 it evaluates to false, that choice is removed from the list. Finally, if a set is present, it is checked to see if the text of a choice is in the set. If the text is found, the 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 is presented to the user. When the user makes a choice, the text of that choice is added to the set (if one is present), and execution continues with the block associated with the choice. When that block finishes, execution continues with the statement after the menu.

Here's a fairly complicated menu that uses all three kinds of menuitems. Most menus in actual games will not be this complicated.

menu what_to_do:

    # Ensure that we can only do a given thing once.
    set what_to_do_set

    "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."

This menu will only allow a given activity to be chosen once, and will allow the user to chose to go to the beach only if the user has chosen to go shopping.

menu = ...
The menu variable contains the function that is called to display the menu to the user. By default, this variable contains a function that passes its only argument to renpy.display_menu. You can read the documentation of that function to find out what menu expects as input.
predict_menu =
A function that is called with no arguments sometime before a menu is displayed. It should return a list of widgets, which will then have images they use preloaded.

Displaying Images

Without the ability to display images to the user, a visual novel would be a text adventure. Ren'Py controls image display by using layers, each comprising a list of things to be displayed to the user. By default, there are three layers. The master layer is manipulated using the various image display statement defined in this section. The transient layer is used to display ui widgets, like windows containing dialogue and menus. Finally, an overlay layer exists to allow things to be overlaid on top of the screen.

Every time an interaction starts (for example, a line of dialogue or a menu is displayed), the contents of each of the layers is drawn to the screen, with the first being in the back and the last being in the front. A number of statements manipulate the contents of the master layer. Before we can explain them, however, we should first define a few terms.

An image_name is a space-separated list of names that's used to refer to an image. This list of names may not include keywords in it. The first element of the image name is known as the image tag, and is treated specially.

A Displayable is a python object implementing an interface that allows it to be displayed to the screen. A transform is a function that, when applied to a Displayable, returns a new Displayable. Transforms are used to change the way an image is displayed to the user. A transform_list is a comma-separated list of transforms. Display lists are applied from left to right.

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

An image_spec is an image name, an optional layer that the image will be displayed on or hidden from, an optional at list of transformers, and an optional with clause giving a transition. The image name is used to specify an image that will be shown. The at clause is a list of transformations that are applied to that image, which can control things like the placement of the image on the screen. The with clause is used to specify the transition that the image is being shown or hidden with. It will be discussed more in the section on transitions.

image_statement -> "image" image_name "=" python_expression

The first display statement is the image statement, which does binds an image name with a displayable defining that image. As the list of image to name bindings is never saved, the image statement can only appear inside of an init block. The argument given here is passed to Image in loose mode. Among other things, this means that if the argument is a single string, it is interpreted as the filename of an image. If another displayable (such as Animation) is given, it is passed through unchanged.

An example of image in use is:

init:
    image eileen happy = "eileen/happy.png"
    image eileen upset = "eileen/upset.png"
show_statement -> "show" image_spec

The next display statement is the show statement, which takes an image specifier and displays it on the layer specified, or the "master" layer if no layer is given. If an image with the same tag as the image given in the spec already exists in the layer, it is replaced with the newly displayed Displayable. Otherwise, the new one is added to the end of the master layer (that is, closest to the user).

If an at list is present, the image is transformed with the at list before being added to the master layer.

Automatically replacing an image with the same tag is a useful feature that allows characters to change expression without having to explicitly hide the old image.

scene_statement -> "scene" ("onlayer" layer)? ( image_spec )?

The scene statement first clears the layer. If the optional image_spec is present, it is shown as if it was shown with the show statement. The best use for the image_spec on a scene command is show a background for the scene. The layer chosen is the layer in the image_Spec if the image spec is present, the layer given in the onlayer clause if no image spec is present, and the "master" layer otherwise.

By default, no background is added to the screen. (See config.background to change this.) Without such a background, Ren'Py will produce odd results if there is not at least one image in the scene list that is the full size of the screen. So we strongly advise that the scene statement always be used with an image, and that image be one that takes up the full width and height of the screen.

We can put together the scene and show statements to get the following example:

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."
hide_statement -> "hide" image_spec

The hide statement is used to remove an image from the layer. The image spec is parsed for a tag, and any image matching that tag is remove from the scene. The at list is ignored (but should be valid or omitted), and transitions associated with the image spec are run. The onlayer clause in the image spec chooses the layer the image is hidden from, with "master" being the default.

Hide is a rarely used display statement. The show statement automatically replaces an old image when a character changes emotion, and the scene image removes all images when the scene changes. Hide is generally only used for when a character leaves in the middle of a scene.

e "Well, I'll be going now."

hide eileen

"And with that, she left."

These four statements, along with the library of Displayables and transforms provided with Ren'Py, should be enough to render most scenes needed in a visual novel type game.

Programmatic Equivalents

Each of the four statements given above has an equivalent python function, documented below.

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.

Parameterized Images

Show and scene statements may also take parameterized images. If a name of an image is a prefix of the name given in a scene or show statement, the rest of the name is considered to be parameters. Parameters may be names, but they may also be simple_expressions, which includes strings. Parameters are handed off to the object that the prefix is defined to, and that object is responsible for returning a displayable that can be shown to the user.

An example of this is the pre-defined text displayable, which displays text as if it was an image. For example, the following code:

show text "American Bishoujo Presents..."

Will display the given text as if it was an image. The game will not pause while the text is being displayed. Such an image can also be processed through an at clause, as in the following code which moves the text down from the top of the screen, while waiting 10 seconds or until the user makes some input.

show text "A PyTom Game" \
        at Move((0.5, 0.0), (0.5, 0.5), 4.0,
                xanchor='center', yanchor='bottom')

$ renpy.pause(10)

Please note that parameterized images are replaced in the same way that normal images are. (So you can only have one image created with text on the screen at a time, without creating a second ParameterizedText object.)

Image and Scene Functions

This section includes functions that are useful when defining images or composing scenes.

Image (arg, loose=False, **properties):

This takes as input one of a number of ways of specifying an image, and returns the Displayable image object that has been so specified. Specifically, this can take as input:

If the loose argument is False, then this will report an error if an arbitrary argument is given. If it's True, then the argument is passed through unchanged.

The Image function is generally used in conjunction with the image statement. For example:

init:
    image eileen happy = Image("9a_happy.png")
    image eileen vhappy = Image("9a_vhappy.png")
    image eileen concerned = Image("9a_concerned.png")
ImageReference (name, **properties):

ImageReference objects are used to reference images by their name, which is a tuple of strings corresponding to the name used to define the image in an image statment.

name - A tuple of strings, the name of the image.

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.

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.

init:
    style.window.background = Frame("frame.png", 125, 25)

Frames are normally used in conjunction with styles, to provide the displayable that is the background for a window containing a menu or dialogue.

renpy.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.

This is used to implement the text image. The user may also want to instantiate their own ParameterizedText object (in an init block) if they want to have more than one bit of text on the screen at once, or if they want to change the style (and therefore the position) of that text.

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

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

Animation Functions

Occasionally, one will want an image that changes while on the screen. Ren'Py provides three ways of doing this. The Animation function creates an animation from a simple list of images, anim.Blink blinks an image in and out, anim.Filmstrip creates an animation from an image, and anim.SMAnimation function creates a more complex, state-machine controlled animation.

Animation and motion functions take a parameter, anim_timebase, that chooses which timebase is used. 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.

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.)

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.

Particle Motion

Ren'Py also 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 function 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.

Layout Functions

These functions allow one to layout multiple displayables on the screen. They let multiple displayables be used when only a single displayable is expected.

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.

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.

Control Statements

Control statements change the order in which statements in a Ren'Py script execute. These statements allow for control transfers, conditional execution, and procedure calls.

label_statement -> "label" name ":"

The label statements assigns a name to a point in the program, allowing control to be transfered to this point by the jump or call statements. The label statement may have a block associated with it. If it does, the statement executed after the label is the first statement in the block. Otherwise, the next statement to be executed is the first statement after the label.

jump statement -> "jump" name
jump statement -> "jump" "expression" simple_expression

The jump statement unconditionally transfers control to the statement with the given name. If the name does not exist, an error is raised.

label loop_start:

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

jump loop_start

A second form of the jump statement is invoked if the expression keyword is in the statement. In this form, the supplied simple expression is evaluated to get a string, and control is transferred to the label given by that string.

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

The call statement transfers control to the location given. It also pushes the name of the return site onto the return stack, allowing the return statement to return to the statement after the call site.

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. On the other hand, 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.

A second form of the call statement is invoked if the expression keyword is in the statement. In this form, the supplied simple expression is evaluated to get a string, and control is transferred to the label given by that string, in a manner similar to a normal call.

return_statement -> "return"

If the return stack is not empty, the return statement pops the top return site off of it and transfers control there. Otherwise, it performs a full restart of Ren'Py.

e "First, we will call a subroutine."

call subroutine from _call_site_1

e "Finally, we will exit the program."

return

label subroutine:

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

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

The if statement is used to conditionally execute a block of statements. It is the only statement that 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."
while_statement -> "while" python_expression ":"

The while statement executes its block while the expression is true. Specifically, each time the while statement executes, it evaluates the expression. If the expression is true, control is transferred to the first statement of the block associated with the while loop. If it is false, then control is transferred to the next statement. The while statement is the statement that normally executes after the last statement in the block, causing the condition to be evaluated again and the loop to repeat.

This definition of a while loop means that it would be hard to implement statements like python's "continue" or "break". These statements can be easily faked with labels in the right places and jumps to those labels. This definition also means that it's possible to jump into the middle of the block associated with a while loop and, if at the end of the block the condition is true, have the while loop repeat the block.

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."
pass_statement -> "pass"

The pass statement can be used where a block is required, but there's no statement that can be placed in that block. When executed, pass has no effect.

For example, pass can be used in a menu if we don't want to take any action when a choice is selected.

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."
init_statement -> "init" ":"

The init statement is used to introduce a block of code that should be run when the game first starts. When the game is first loaded, the script is scanned for init blocks, and code in init blocks is run in an arbitrary order. An init statement encountered during execution, however, is treated as a pass statement, and the block is not executed.

Python Statements

python_statement -> "$" python_code

There are two Ren'Py statements that allow python statements to be mixed with Ren'Py code. Any statement beginning with a dollar-sign ('$') will be interpreted as python code extending to the end of the logical line. This form can only include a python statement containing a single logical line. (So python control constructs cannot be used.)

python_block_statement -> "python" ( "hide" )? ":"

The other way to introduce python statements is with a python block statement. The block associated with this statement, along with any block inside those blocks, is interpreted as python code that is passed to the python interpreter. The block nesting structure is reflected in the python code that is interpreted, so that python control structures will work as advertised.

If the optional hide keyword is added to a python block statements, local variables created in the block will not be added to the store. The variables in the store can be accessed as attributes of the store, however.

$ score += 1

# Pointless python that uses a loop.
python:
    for i in ('e', 'l'):
        globals()[i].points = 0

In general, if a Ren'Py construct exists that does what you want (like while or if), it should be used in preference to a python block, unless a large amount of code is to be executed with no user interaction.

Starting a Game

When Ren'Py is first invoked, it first determines the name of the game directory. It does this by looking at the name of the executable file that is being run. It strips off the extension and any prefix up to and including the first underscore. It looks to see if what's left (the basename) corresponds to a directory, and if so, that is the game directory. Otherwise, Ren'Py looks for the default game directories, "game" and "data", in that order. If the game directory still cannot be found, the directory the executable file is in is used as the game directory.

It 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. We attempt to center this window on the screen, and to show the window without a title bar.

Ren'Py then attempts to add some default archives. There are three archives Ren'Py will add by default. The first is the basename determined from the executable name, and extended with .rpa. (For example, if the executable is "run_en.exe", we will add "en.rpa") The other two are game.rpa and data.rpa. Each archive is only added once.

Ren'Py then tries to process all the .rpy and .rpyc files in the game directory, common directory, and default archives. If a .rpy file exists and is newer than the corresponding .rpyc file, it is loaded, and the script is then written out in a serialized form. If no .rpy files exist, but the serialized script (.rpyc file) does exist, or if the serialized script is newer than the corresponding .rpy file, the serialized script is read back in.

The second step in loading a Ren'Py script is to find or generate bytecode for all of the python blocks in the script. This is first done by loading in the file bytecode.rpyb, if it exists. The file may be loaded from disk, or from inside one of the default archives. For each python block, it is searched for bytecode corresponding to the current version of python. If such bytecode is not found, it is generated. If any python was generated, a new version of bytecode.rpyb is written into the game directory. Please note that the user can cause the generation of a new bytecode.rpyb file by running Ren'Py with an upgraded version of python. To prevent a pause for compilation from occuring when Ren'Py is first run, you'll want to ship bytecode.rpyb as part of your completed game.

Once the script is loaded, the first thing that occurs is that it is scanned for init blocks. These init blocks are then run immediately, in no particular order. The init blocks should do things like loading images and changing Ren'Py configuration. On no account should an init block try to display an image or interact with the user, as the display system is not yet initialized, and so such interaction will not work.

After the last init block has finished running, the display is initialized, and the actual game can begin. If the library is present it looks for a label named "splashscreen", and calls it if it exists and this is not a reset of Ren'Py. It then looks for the label "main_menu". If it exists, then that label is jumped to as the main menu. Otherwise, the library main menu is displayed. While library.main_menu allows this menu to be customized, the default main menu calles the label "start" when the user chooses "Start Game". The library main menu can also be manually accessed by jumping to _library_main_menu, which is useful if you want to display an intro before the menu is shown.

The main menu and game menu execute in their own context, which is a different context from the one in which the game executes in. One should invoke renpy.jump_out_of_context() in order to leave the menu context and start execution at a label. 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

should cause execution to begin immediately, skipping the game menu entirely. You may want to customize _game_menu_screen in order to allow the user to load a new game from the first few screens.

Finally, we should point out here that if the label after_load exists, it is called after loading. When the code returns, execution proceeds at the start of the statement where it was saved at. The after_load label allows data structures to be updated after a load.

Saving, Loading, and Rollback

In Ren'Py, saving, loading, and rollback are three actions that share quite a bit of infrastructure. So, we'll discuss them together in this section. We will pay special attention as to what it takes to support loading of a saved game when the script changes between saving in loading, while running on the same Ren'Py version. Apart from designated bug-fix releases of Ren'Py, we do not plan to support loading a save created on an older version of Ren'Py in a newer release of Ren'Py. Once a game has been released once, it's expected that future releases of that game will use the same release of Ren'Py.

The state of the game in Ren'Py consists of two basic parts. The interpreter state consists of state that the user never manipulates directly, while the user state consists of variables that have been changed by the user, and objects reachable from those variables. Currently, the interpreter state that is saved consists of:

These items are automatically saved, restored, or 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.

There are some important portions of interpreter state that are not saved, and therefore should only be changed in init: blocks. These are:

To deal with this, one should ensure that all images and config variables are set up in init blocks, and then left alone for the life of the game. In addition, as a scene list in a saved game may contain references to image names, once an image name is defined in a released version of the game, the image name should remain defined in all future release of the game.

The other kind of state that Ren'Py can save and restore is user state. User state consists of the values of all variables that are changed after the end of the init phase, as well as all data reachable from those variables.

It's important to clarify what it means for a variable to be changed. In Python and Ren'Py, variable names are bound to objects. The variable changes when a new object is assigned to it. It does not change when the object that is assigned to it changes.

As an example, in the following code:

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

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

The variables a and b are updated after the end of the init: block, while state is not updated. The variable a is assigned a different integer object, while b is assigned a new empty list. While a field in the Character object is changed by the last statement, state still points to the same object, and therefore it is not considered to have changed. (And therefore, the object isn't considered to be part of user state.)

User state is gathered by first finding all variables changed since the end of the init phase. We then find 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 bindings and object values comprises the user state.

It's important that everything that's kept in the user state can be pickled (serialized). Thankfully, most python constructs can be, 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. Things that can't be pickled include strange objects like iterators and files. Usually, you don't have to worry much about this.

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 statement 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. (Such as a label, a menu with a name, or a call with a from clause.) The game will rollback to the start of one of these statements. To ensure that rollback works correctly when the script changes, a label that exists in a released version of the game should continue to exist in all future version of the game.

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 currently-executing 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.

Finally, if allowed, rollback can be invoked explicitly by user input. 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.

The upshot of this is that when a user rollback occurs, the game is reverted to the start of the say or menu statement that executed before the currently executing one.

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.

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.

Persistent Data

Persistent data is data that is saved that is not associated with a single game. One possible use of it is to store information about things that have been unlocked, such as an image gallery that is only unlocked when an ending has been reached.

Persistent data is stored as fields on the "persistent" object. This object is special, as uninitialized fields are forced to take the value None. A change to this object is visible in every game that the player undertakes.

Take as an example an unlockable image gallery. The code to display the gallery look like:

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.

Then, to unlock the gallery, run the following code somewhere in your program.

$ persistent.gallery_unlocked = True

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."

It's probably best to define Character objects in an init block, and not attempt to set attributes on them.

Character (name, who_style='say_label', what_style='say_dialogue', window_style='say_window', function=..., predict_function=..., condition=None, dynamic=False, **properties):

The character object contains information about a character. When passed as the first argument to a say statement, it can control the name that is displayed to the user, and the style of the label showing the name, the text of the dialogue, and the window containing both the label and the dialogue.

name - The name of the character, as shown to the user.

who_style - The name of the style that is applied to the characters name when it is shown to the user.

what_style - The name of the style that is applied to the body of the character's dialogue, when it is shown to the user.

window_style - The name of the style of the window containing all the dialogue.

who_prefix - A prefix that is prepended to the name.

who_suffix - A suffix that is appended to the name. (Defaults to ':')

what_prefix - A prefix that is prepended to the text body.

what_suffix - A suffix that is appended to the text body.

function - The function that is called to actually display this dialogue. This should either be renpy.display_say, or a function with the same signature as it.

predict_function - The function that is called to predict the images from this dialogue. It is called with the same signature as display_say (although some of the parameters, such as what, may be inaccurate), and is expected to return a list of displayables that should be loaded.

condition - A string containing a python expression, or None. If not None, the condition is evaluated when each line of dialogue is said. If it evaluates to False, the dialogue is not shown to the user.

interact - If True (the default), then each line said through this character causes an interaction. If False, then the window is added to the screen, but control immediately proceeds. You'll need to call ui.interact yourself to show it.

properties - Additional style properties, that are applied to the label containing the character's name.

dynamic - If true, the name is interpreted as a python expression, which is evaluated to get the name that will be used by the rest of the code.

image - If true, the name is considered to be the name of an image, which is rendered in place of the who label.

ctc - If present, this is interpreted as a widget that is displayed when all text is shown to the user, prompting the user to click to continue. Animation or anim.Blink is a good choice for this sort of widget, as is Image.

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

interact - If True, the default, an interaction will take place when the character speaks. Otherwise, no such interaction will take place.

In addition, Character objects also take properties. If a property is prefixed with window_, it is applied to the window. If prefixed with what_, it is applied to the text being spoken. Unprefixed properties are applied to the who label, the name of the character speaking.

DynamicCharacter (name_expr, **properties):

A DynamicCharacter is similar to a Character, except that instead of having a fixed name, it has an expression that is evaluated to produce a name before each line of dialogue is displayed. This allows one to have a character with a name that is read from the user, as may be the case for the POV character.

This is now exactly the same as constructing a character with dynamic=True.

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.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={}, **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 various prefixes, suffixes, and styles, please read the documentation for Character.

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.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):

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.

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.background = None
This sets the default background that is shown in areas of the screen where there are no images. If the screen will always be filled with an image, it makes sense to set this to None, which will improve performance by not drawing a default background. Otherwise, this is interpreted as an RGBA tuple, which will be drawn before any image is.
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.
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 callbacks that are called (without any arguments) when an interaction is started or restarted.
config.start_interact_callbacks = ...
A list of callbacks that are called (without any arguments) when an interaction is started. These callbacks are not called when an interaction is restarted.
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.
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.

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 --- This can be either the name of file containing a truetype font that is used to render the text, or a string containing font names, the first found of which will be used to render the text. If the truetype file is not found in the game directory or common directory, it will be searched for in the system's font directory. Examples: "Vera.ttf" or "Arial,Helvetica,FreeSans"

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. Example: 22

color --- The color in which the text will be displayed on the screen, as an RGBA tuple. Due to a limitation of pygame, currently the alpha is ignored. Example: (255, 255, 255, 255)

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.

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.

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_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.

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.
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.
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.
gm_root_window:
(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_window:
(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_window
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_window:
(inherits from default)
(window) A window containing the file picker that is used to choose slots for loading and saving.
file_picker_window_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_window:
(inherits from default)
(window) The style of a window containing a yes/no prompt.
yesno_window_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_window:
(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.
mm_root_window:
(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_window:
(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_window_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_window:
(inherits from default)
(window) A window containing all preferences.
prefs_pref:
(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.
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_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.
joy_window:
(inherits from prefs_window)
(window) The window containing the joystick message.
joy_vbox:
(inherits from thick_vbox)
(window) The vbox containing the joistick mapping message.
joyfunc_label:
(inherits from prefs_label)
(text, position) The style of the joystick mapping function name.
joyprompt_label:
(inherits from prefs_label)
(text, position) The style of the joystick mapping prompt message.
prefs_jump:
(inherits from prefs_pref)
(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.

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}."

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' ],

    # 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.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.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.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 name 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. 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 different from the persisted last queued music. 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 (filename, 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 filename. If loop is True, the track will loop while it is still 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.

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 filename 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.

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 (filename, channel=7, loop=True, clear_queue=True, fadein=0, tight=False):

This queues the given filename on the specified channel. If clear_queue is True, then the queue is cleared, making this file the file that is played when the currently playing music finishes. If it is False, then this file is placed at the back of the queue. In either case, if no music is playing this music begins playing immediately.

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 filename 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.

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.

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.