Text
This section covers aspects of text in Ren'Py. It first covers interpolation, supported by the say and menu statements, which allows values to be substituted into text. It next discusses text tags, which allow the style of portions of strings of text to be customized. Finally, it covers how Ren'Py handles fonts.
Interpolation
Interpolation is supported by the say and menu statements. These statements support python string interpolation over the contents of the store. The strings used by the statements support conversion specifiers of the form %(variable)s, where variable is the name of a variable and s is a conversion. Useful conversions include 's', which interpolates a string; 'd', which interpolates an integer; and 'f', which interpolates a floating point number. Conversions may also include characters that modify how the string is converted. More information about conversions can be found at the Python string formatting operations reference.
In strings where interpolation is supported, percent characters (%) must be duplicated (to %%) to prevent them from being interpreted as introducing interpolation.
$ name = 'Samantha' $ age = 19 $ withyou = 110 girl "My name is %(name)s, and I am %(age)d years old. I'm with you %(withyou)d%%"
When interpolation is not supported, the effect can often be faked by formatting a string against the result of calling the globals() function.
ui.text("%(name)s's Vital Statistics" % globals())
Text tag processing is performed after interpolation, so it's important to ensure interpolation does not introduce text tags.
Text Tags
Text displayed by Ren'Py supports text tags. While styles can only be applied to an entire Text displayable, allow only a portion of the text in the displayable to be customized. As text tags are part of the Text displayable, they may be used in any string that is displayed on the screen. However, some of the text tags will only have effect if used in the appopriate context.
Text tags should be used fairly sparingly. If you find you're using text tags on every line of the game, it's quite possible text tags are not the right solution for the problem at hand. Investigate text styles as a possible alternative to text tags.
Text tags start with a left brace ({), and continue to the matching right brace (}). Immediately following the left brace is the tag name. The name may be followed by an argument, which is separated from the tag name by an equals sign (=). Some tags require an argument, while others require that the argument be omitted. Text tags are sensitive to case and white space.
Some tags require a corresponding closing tag. A closing tag is any text tag where the name begins with a slash (/). Closing tags should be properly nested: "{b}{i}this is okay{/i}{/b}", while "{b}{i}this is wrong{/b}{/i}". While improper nesting of text tags will generally not cause an error, this problem may cause undesirable rendering results. The text between a tag and the corresponding closing tag is called the enclosed text. All tags must be closed by the end of the text string.
To include a single left brace in text, two left braces ({{) musty be included instead.
Ren'Py supports the following text tags:
-
{a=argument} and {/a} cause their enclosed text to be rendered as a hyperlink. The enclosed text may contain text tags, but may not contain another hyperlink. A hyperlink is rendered as a button containing the enclosed text. The text in the button does not participate in line-breaking. Rather, if the text grows too big for the line it is on, the whole button is moved to the start of the next line.
When a a hyperlink is clicked, the callback function defined in config.hyperlink_callback is called with the text of the argument of the hyperlink. The default hyperlink handler interprets argument as a label, and calls this label in a new context. This is an appropriate behavior when using hyperlinks to definitions of unfamiliar terms. Hyperlinks should not be used as a general control-flow tool, as they transfer control to a new context when clicked. If the user saves while inside that context, when he loads the game he will be returned to the screen containing the hyperlink.
init: $ definition = Character(None, window_yfill=True, window_xmargin=20, window_ymargin=20, window_background=Solid((0, 0, 0, 192))) label start: "A game that instructs on how to make a game? Isn't that a sort of {a=define_quine}Quine{/a}?" # ... label define_quine: definition "Quine:\n\nA program that prints itself to its output." return
- {b}text{/b} renders the enclosed text in a bold font.
- {color=spec}text{/color} changes the color of the enclosed text. The color may be a hex triple or a hex sextuple, optionally preceded by a hash mark. (The same format that color() accepts. f00, ff0000, #f00, and #ff0000 are all valid representations of red.)
- {fast} causes the immediated display of text before it. It can be used to specify where slow text shold begin to display from. It only has an effect if the text speed preference is not infinite. Use this if you have two lines of dialogue where the second is an extension of the first, as a variant of the pause effect that allows for changes to occur while paused. This tag does not take a closing tag.
- {i}text{/i} makes the enclosed text in an italic font.
- {image=filename} causes the supplied image to be loaded and included into text. The image should are treated as if they were text, and should not be taller than a single line of text. {image} does not take a closing tag.
- {p} causes the display of text to be paused until the user clicks to continue, or until an auto-forward occurs. This allows text to be displayed incrementally. {p} does not take a closing tags, and causes a newline to be interted after the given text. The logic to handle pausing is implemented in the Character object, and may not work for other text widgets.
- {plain}text{/plain} makes the enclosed text plain, eliminating bold, italic, and underline styles
- {size=spec}text{/size} changes the size of the text. The supplied spec may be a number, in which case it is the number of pixels high that the text will be. If it is a number preceded by a plus (like "+10"), it means to increase the size by that number of pixels, while if it is preceded by a minus it means to decrease.
- {u}text{/u} renders the enclosed text with an underline.
- {w} is similar to {p}, except that it does not cause a newline.
The following is an example of a say statement that uses many text tags. Use of this many text tags is not recommended in a high-quality game.
"Using text tags, we can make text {size=+12}bigger{/size} or
{size=-8}smaller{/size}. We can make it {b}bold{/b}, {i}italic{/i},
or {u}underlined{/u}. We can even change its {color=#f88}color{/color}."
Fonts and SFonts
The Text displayable attempts to find an an appropriate font using information about the font name, boldness, italics, underline and size. This information is supplied to the Text displayable using style properties, but may then be modified using text tags. Ren'Py translates this into a font using the following algorithm.
-
A (name, boldness, italics) triple is looked up in config.font_replacement_map . If present, it is expected to map to a triple giving replacement values for name, boldness, and italics. This lookup is not recursive, so only one lookup is performed. This lookup allows specific bold or italic font shapes to be used.
- If a SFont has been registered with the same name, size, boldness, italics, and underline, that SFont is used.
- Otherwise, Ren'Py interprets the font name as the filename of a truetype font. This filename is searched for in the searchpath and archives. If found, it is used as the font file.
- Otherwise, Ren'Py searches for a font with the given filename in the system font directory. If found, that file is used.
- Otherwise, Ren'Py interprets the filename as the name of a truetype font, which is loaded if found.
The truetype font loading code will automatically scale and underline the font as required. If you have not provided bold and italic font mappings, it will also artificially thicken and slant the font when necessary.
For best results, fonts should be truetype files that ship with the game. This ensures that required fonts are always present on the user's system.
SFonts
Ren'Py supports rendering text using SFonts as well as TrueType fonts. An SFont is a properly prepared image file, usually a PNG, containing images of the character in the font. Ren'Py has its own implementation of SFonts that supports an arbitrary unicode character set and kerning.
SFonts have several advantages and several disadvantages. One of the advantages is that SFonts are bitmap-based, which means it is easy to create custom fonts and to find free examples (in contrast, the licenses of high quality TrueType fonts rarely permit redistribution). Also, as SFonts are images, it's possible to apply effects to them that Ren'Py would not otherwise support. The downsides of SFonts come from the fact that Ren'Py doesn't render them, but instead merely copies characters out of them. Because of this, one needs to supply another image to Ren'Py if one wants the font to be scaled, made bold, made italic, or underlined. Ren'Py will recolor the SFont, with white being mapped to the supplied color, and other colors interpolated on a channel-by-channel basis.
For more information about SFonts, see http://www.linux-games.com/sfont/.
To use SFonts, they must first be registered with Ren'Py using the renpy.register_sfont function. They can then be used by setting the font property of a style to the name of the SFont. The default character set for a SFont is:
! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
Please note that you must register a sfont for each combination of font, size, bold, italic, and underline your game uses.
Legal issues regarding the use of copyrighted outline fonts in creating SFonts are discussed in Bitmap Fonts and Copyright