Skip to content

Tips, Tricks And Lifehacks#

The following lists a few things that can help make your life a little easier while coding. These are specialized functions or shortcuts to do things quickly and only apply to very specific situations. Neverthless it is good to have these in your repertoire when you eventually advance enough to have a need for them.


Positioning can be a bit tricky, which is why a helper function exists to make determining positions on screen easier.


Using placement_of(character), we can get the x and y coordinates of any character on the screen. These can then be used in animations or the positioning of effects and other characters.

Body modification shortcuts#

Switching Bodies#

We have already learned how the body-switcheroo thingies work if you go for the fancy option. However, sometimes you will find that you need to set up a scene and the characters without showing and transforming them for all to see. For this we provide two commands. To change a characters' body without displaying it, you can use

body <character_from> <character_to> [<outfit>]

Note that <outfit> is optional in this case. The following will make john look like katrina in her uniform outfit:

body john katrina uniform

Cloning People#

If you want to copy another characters' appearance, including pose, expressions and accessories, you can use this command:

clone <character_from> <character_to>
In the below example this would copy connies appearance over to john so both characters would look identical when displayed.
clone john connie

Please be aware that both of these functions work "behind the scenes", they will not show anything on the screen until you add an actual show statement afterwards.

Making Phone Calls#

While we added the ability to chat via text messages in the last update, we have now completed that feature-set by adding in the ability to visually show the act of making a phone call.

Making a phone call in Student Transfer

Using the statement below

phone_call john @ bg house_davis bedroom_john day_shut : katrina @ bg house_davis kitchen day
will result in the following visualization: Visualization of a phone call

The whole animation can be triggered via one command, the syntax of which looks like this:

phone_call <character> [<expression>] @ <location> : <character> [<expression>] @ <location>

Here, character is any of the available character names as they appear in the script while location is the same, but for background names. Optionally, expressions can be added after each character name (both or either one individually) to set the expression to a different one than the default a_0.

To get rid of the phone call visualization simply start a new scene like you would do in any other situation as well.

Adding custom Movies#

Student Transfer supports adding animated sprites in the form of what is called "Movies" by Ren'Py but generally refers to any kind of animated image or video. Adding a video is very similar to adding a custom background image, however instead of putting the file into the bg directory you instead put it into the movies directory. Student Transfer will automatically pick it up if it is in a valid video format that the game can understand and will make it available to use in the game with a very similar naming scheme to what custom backgrounds use. Beware though, since the naming differs slightly! While a background might be called example_bg street night a movie will instead replace all spaces in the script name with underscores (_). Additionally, it will use the movie tag instead of the bg tag to indicate its type. So the video file nuclear explosion.mp4 located in the movies folder will end up as example_movie_nuclear_explosion.

Student Transfer makes all your movies available in two ways:

  1. As a variable containing the full path to your movie file
  2. As a Movie displayable which works like any other image

We do this to support different use cases. Most people who want to show cut-scenes, intros, outros or anything of the sort will most likely be interested in Option 1 since that allows you to use your video file in renpy.movie_cutscene like this:

$ renpy.movie_cutscene(example_movie_fire)

Simply use the exact script name of your video file in the movie_cutscene method (without quotes) and Ren'Py will properly detect it, wherever it may reside on disk.

People who want to have more control over what happens with their videos will be interested in Option 2, which loads the video file into something that effectively behaves the same as a regular image. This means that video files can be manipulated via ATL, moved around, rotated and animated, like in this very simple example:

show example_movie_fire:
    size (1280, 720)
    align (0.5, 0.5)
    ease 4.0 rotate 180
    ease 0.5 alpha 0.0

Student Transfer always loads video files in both formats, so you can use both of these options at the same time.

For a more hands-on example with an existing video file, try out the example scenario which already contains a video and uses it at the very end of the scenario. If you want to toy around with an already working example, simply open up the script and take a look around.

Supported Video Formats#

When experimenting with video files in Student Transfer you will likely at some point run into the problem that your videos won't show up in the game. This is due to the fact that Ren'Py only supports a limited number of formats across all platforms. Generally, Student Transfer will always try to load video files from the movies folder and only if they have one of the following extensions:

  • .mp4
  • .webm
  • .mkv
  • .3gp

However, a correct extensions does not mean that your video will automatically work. You have to take care that it is in the correct codec, too. From our testing, we recommend that you use the VP9 codec with the .mkv file extension as that seems to work most of the time and produces the smallest file size for a given quality. Alternatively use the MPEG-4 codec with the .mp4 extension.

There are several programs out there to convert video files into different formats but we recommend Handbrake as it is free, relatively easy to use and very performant.

For more information about supported video formats please reference the original Ren'Py documentation.

Alpha Masks#

Ren'Py supports alpha masks for videos in the form of a separate video files which will be used exclusively as the alpha channel of the main video file. To add such an alpha channel, simply add it as a new file next to the full video file and append the suffix _alpha. For example, if you had the video fire.mkv and wanted to add an alpha channel, you'd save it next to that file as fire_alpha.mkv.

Helper Characters#

Sometimes you just need a character for one or two lines, most likely without a sprite. This is supported in two distinct ways which are explained below.

Changing the name of an existing Character#

This method is very simple to use but also has the potential to mess with the game beyond a specific scenario as name changes are retained until a specific reset function is called (resetstate) or the names are manually reset. As such we discourage use of this technique unless done very carefully.

To change the name of an existing character, you can simply do the following:

$ <character_to_change:character>.name = <name:string>
$ = "Jacob"

From this point onward, whenever john speaks, he will show up as Jacob instead of John. Keep in mind that his name will stay that way until you change it back!

Creating a temporary character#

It is possible to create an entirely new speaker-character which can be used in the script as if it were a full-fledged character, with the exception that this "fake" character will not have any sprites. It purely exists to speak dialogue. This is the recommended way of creating new speakers or changing the name of existing ones by having the fake character speak the lines of the existing one.

When creating a FakePerson, please prefix them with your scenario prefix to avoid name collisions!

A fake character (or rather, "fake person" as they are called in Student Transfer) can be created and used like this:

define <script_name> = FakePerson(<display_name:string>, <body_with_voice:body>)
# Define the fake person
define example_secretary = FakePerson("Secretary", 'donna')

# Use them in the script
example_secretary "Hey, listen!"

# Note that you can not do this:
show example_secretary a_0 at center
# Fake persons do not have any sprites associated with them!

Repositioning the text box#

You may move the textbox around the screen using the property gui.textbox_yalign.

For example, to move the textbox to the top of the screen (with a little bit of margin), you may do the below at any point in your script:

$ gui.textbox_yalign = 0.1

Don't forget to reset it back to 1.0 when you're done, which is the default position.

Changing the color of the text box#

This is possible by creating a custom character and referring it to custom sprites for a text box of your choosing. Since the is just an image, you can make it look however you want.

define my_character = Character(window_background=Frame(
    "<prefix>_asset <asset_name>",

Find below a selection of text-box templates that are ready to use, provided by CREAM, author of Empyrée, Never and some other scenarios.

Text Box Templates (by CREAM)

Template A Template B Template C Template D Template E Template F Template G Template H

To use these templates, simply download the one you want, put it in your assets folder and set it up in the script like shown above.

Auto-Reloading the Game#

A very nice feature for anyone working on scripts in Ren'Py is the auto-reload functionality. It can be enabled at any point in the game with the key combination Shift+R. Once enabled, the game will reload once (without closing) and from that point onward it will reload everytime a script file on disk changes (normally when you save new changes). Auto-Reload can be turned off with the same key combination, which will stop the game from reloading when modifying files. Watch out though, because if you make a script change that breaks the game, Student Transfer will crash during the next auto-reload.

Direct Paths to Images#

Scenarios can now access the full path of any image they contain via the direct_path method. Given the script name of the image, it will return the direct path of the file on disk:

direct_path("example_asset arrow")
Return Value: "/Users/Username/Downloads/Student Transfer/game/scenario/example/assets/arrow.png"

This is the recommended way to obtain direct paths to files (if they are necessary at all) as this method will always work, even when the scenario is installed somewhere other than the default location in the game's folder.

Hooking into the main storyline#

For scenarios that extend the main storyline we support hooking them into the main game. Making use of this feature will enable your scenario to pop up in the main game at a point of your choosing and present the player with the option to either seamlessly transition to your story or continue on their merry way.

The only thing you have to do to make this feature work is to add/modify a single field to/in your scenario.yml file:

hook_hash: a757c4bc

The string next to hook_hash is a unique identifier for every piece of dialogue in the game. This includes scenarios as well, so in theory you could hook into other peoples' scenarios, too! Don't do that though, that's uncharted territory. Anyway, in this case 0d1fe1f4 refers to a very early piece of dialogue in John's room with him saying "Of course!" we don't expect you to know how to compute this yourself, so instead you can simply press Shift + H while in-game and you'll see that in the top-right corner a small string of characters will appear. To make your life even easier, you can simply click on it to directly copy it to your clipboard. The only thing you have to do is go to the position in the game where you want to hook into, copy the corresponding code, and paste it into the hook_hash field of your scenario. If the field does not exist in your original scenario.yml file, you can simply add it, making it look something like this:

author: Jcjace45, CobaltCore
title: Writing Scenarios in Ren'Py
description: A quick and dirty guide to creating scenarios. For more information,
  read the official {a=}guide{/a}.
label: scenario_example
- official
- tutorial
- guide
version: 2.0.0
prefix: example
hook_hash: 0d1fe1f4

Once that is done, everything else will be taken care of automagically. As a convenience function we also expose the boolean variable _scenario to your code, which you can use to determine if the player came from the main storyline or started it through the scenario mode. That way you have the chance to do some additional setup for players starting your scenario normally or insert some glue-narrative for people coming directly from the story, which you can do like this:

if _scenario:
    john "Hah! You came from the main storyline!"
    john "Anyways, let's get on with it..."

Advanced Scenario Hooks#

Starting with v4.3 of Student Transfer it is possible to register multiple hooks as well as a add small description for each. This works by supplying a hooks field in the scenario.yml file, like so:

author: Jcjace45, CobaltCore
title: Writing Scenarios in Ren'Py
description: A quick and dirty guide to creating scenarios. For more information,
  read the official {a=}guide{/a}.
label: scenario_example
- official
- tutorial
- guide
version: 2.0.0
prefix: example
  7151120f: Perhaps you should wish to understand your new powers

You can use this functionality to hook into as many different parts of the story as you like. To allow you to tell apart where each player came from, the _scenario variable that is passed to your scenario now contains the original hash value of the block of dialogue the player branched off from.

For reasons of backwards compatibility, both fields (hook_hash and hooks) will work, even simulatenously.

Scenario Banners#

With v6 of Student Transfer, the game now supports the addition of a banner image as the background of the details box on the scenario list screen.

This feature can be enabled by editing the scenario.yml file and adding the banner field:

banner: example_asset banner

In this example, a file called asset.png or asset.jpg inside the scenario's asset directory would be used as the banner. The recommended dimensions for the banner are 422 x 352. If the dimensions do not match exactly, the asset will be scaled to this size and aspect ratio.

The banner field can contain the full in-game name of any asset in the game, so it is very flexible. The rule of thumb is: If you can show it in your script, you can use it as a banner.

Animation Helper: Coordinate Grid#

With v6 of Student Transfer the game now ships with a built-in coordinate grid which shows:

  • A coordinate grid (who'd have thought!) divided along common positional boundaries
  • The exact game coordinates of the current mouse position
  • The center of each sprite (as a blue dot)
  • The anchor point of each sprite (as a red dot)

The grid can be toggled at any time by pressing G. The grid has a bright and a dark variant so it's legible on all backgrounds. Pressing G again will cycle through the various modes in this order:

  • Bright Grid
  • Dark Grid
  • Off

Scenario Statistics#

Student Transfer provides access to several variables that can be used to obtain information about a scenario while it's being played. These are made available on the scenario object which can be accessed as soon as a scenario is started from the Scenario Menu.

  • scenario.reading_time: A human-readable string expressing the reading time, i.e. 1.3 hours
  • scenario.reading_time_minutes: The number of minutes as a floating point value, i.e. 38.5
  • scenario.word_count: The word count of the currently active scenario as an integer value, i.e. 3487

You can access them inside a scenario like shown in the example below, but of course you're free to use this information for other purposes as well.

john "Hey, looks like this scenario is [scenario.word_count] words long."

Recommendations of the Team#

This section will elaborate a bit on our stance on certain things and explain why they are the way that they are. This is something of a please-do and please-don't list, mixed with best practices for scenario authors.

CG Usage#

In short: Don't. The long version is that we'd like to hog the few existing CG's of established characters to ourselves, as egocentric as that may sound. The reason is simple: There are only a limited number of CG's available, even fewer that fit the tone of the game and even then they have to fit the scenes we're writing and the outfits the characters are wearing. As such, and to avoid spoiling the surprise before the main game gets to it, we'd like scenario authors to refrain from using CG's of existing characters, tempting as it might be.

Using CG's of other characters that do not exist in the base game is fine by us. If you're in doubt, just hit up someone from the dev-team to verify whether what you're doing is too close for comfort or not. Generally, you're free to use whatever CG's you like as long as they don't show any of the characters from the base game.

Best Practices#

  • Character images should be in PNG or WebP format.
  • While characters can work without their character.yml being given, it is advisable to fill in at least the correct name and name color for a character.
  • Characters should be prescaled as much as possible. If you have to set the scale outside of the range 0.8 to 1.2 you should consider rescaling your images beforehand.
  • Optimise your images with software like PngGauntlet (Windows), ImageOptim (macOS) or Trimage (Linux / Unix) for filesize savings. Make sure you use lossless compression in all cases to avoid artifacts!
  • If you use just a few characters from another scenario (less than 5), copy them into your scenario so that you don't depend on the other scenario.
  • If you use many characters from another scenario (more than or equal to 5), use them directly without copying them. Make sure you notify your players of the fact that they will have to install a second scenario, preferably in big-bold letters right next to your main download link and provide a link to that scenario.
  • If you want to extend an existing character, either from another scenario or from the base game, copy them into your scenario and modify them there. This ensures that modified characters of the same name don't conflict and that all scenarios and the base game display as they should.
  • Use as little custom characters as possible. The cast we provide is already rather large and we generally pay attention to file size and RAM requirements. This is especially important because a large amount of sprites might lead to Out Of Memory issues when too many scenarios are installed. So please take care to keep your scenarios as lightweight as possible.

Last update: December 27, 2021