Side Images

Many visual novels include a picture of the character that is speaking as part of their interface. Ren'Py calls this image a side image, and has support for automatically selecting and displaying a side image as part of the dialogue.

The side image support assumes that a Character() is declared with a linked image tag:

define e = Character("Eileen", image="eileen")

When a character with a linked image tag speaks, Ren'Py creates a pool of image attributes. The linked image tag is added to this pool, as are the current image attributes that are associated with that tag.

In addition to the tag, there must be at least one attribute in the pool. If not, no side image is shown.

To determine the side image associated with a tag, Ren'Py tries to find an image with the tag "side", and the largest number of attributes from the pool. If no image can be found, or more than one image has the same number of attributes, a Null is shown instead.

For example, say we have the following script:

define e = Character("Eileen", image="eileen")

image eileen happy = "eileen_happy.png"
image eileen concerned = "eileen_concerned.png"

image side eileen happy = "side_eileen_happy.png"
image side eileen = "side_eileen.png"

label start:

    show eileen happy

    e "Let's call this line Point A."

    e concerned "And this one is point B."

At point A, the character e is speaking, which is linked to the image tag "eileen". The "eileen happy" image is showing, so the pool of attributes is "eileen" and "happy". We look for an image with the "side" tag, and as many of those attributes as possible – and we match "side eileen happy", which is the side image Ren'Py will display.

At point B, the "eileen concerned" image is showing. The pool of attributes is now "eileen" and "concerned". The only matching image is "side eileen", so that's what Ren'Py selects. If there was a "side concerned" image, there would be ambiguity, and Ren'Py wouldn't display an image.

Invisible Characters

Another use of the side image is to show an image of the player character, when that character has dialogue. The way to do this is to link an image to the character, and then use the say with attributes construct to select the side image to show.

For example:

define p = Character("Player", image="player")

image side player happy = "side_player_happy.png"
image side player concerned = "side_player_concerned.png"

label start:

    p happy "This is shown with the 'side player happy' image."

    p "This is also shown with 'side player happy'."

    p concerned "This is shown with 'side player concerned'."

Config and Store Variables

There are a number of attributes of side images that can be controlled using config variables.

_side_image_tag = None
define config.side_image_tag = None

If _side_image_tag is not None, it takes precedence over config.side_image_tag.

If this is given, then the side image will track the given image tag, rather than the image associated with the currently speaking character. For example,

define e = Character("Eileen", image="eileen")
define config.side_image_tag = "eileen"

Will make the side image track the "eileen" image tag, which is associated with the e character.

define config.side_image_only_not_showing = False

When set to true, the side image will only show if an image with that tag is not already being shown on the screen.

_side_image_prefix_tag = None
define config.side_image_prefix_tag = 'side'

If _side_image_prefix_tag is not None, it takes preference over config.side_image_prefix_tag.

The prefix that is used when searching for a side image.

define config.side_image_null = Null()

The Null displayable to use when not displaying a side image. This can be changed, but only to other Null objects. One reason for doing so would be to set the side of the Null (eg. Null(width=200, height=150)) to prevent dissolves from being cut off.

define config.side_image_same_transform = None

If not None, a transform that is used when the new side image shares the same image tag as the previous side image.

define config.side_image_change_transform = None

If not None, a transform that is used when the new side image does not share the name image tag (or one of the new or old side images does not exist).

Transforms and Transitions

The config.side_image_same_transform and config.side_image_change_transform transforms are called with two arguments – old and new side image displayables – each time the side image is displayed. These can be used to move around side images, or use a transition to go between side images.

This causes the side image to slide in and out when the character associated with that image changes:

transform change_transform(old, new):
    contains:
        old
        yalign 1.0
        xpos 0.0 xanchor 0.0
        linear 0.2 xanchor 1.0
    contains:
        new
        yalign 1.0
        xpos 0.0 xanchor 1.0
        linear 0.2 xanchor 0.0

define config.side_image_change_transform = change_transform

This is used to dissolve between old and new side images when the character remains the same. (For example, when the character changes emotion.) For the Dissolve to work correctly, both side images must be the same size.

transform same_transform(old, new):
    old
    new with Dissolve(0.2, alpha=True)

define config.side_image_same_transform = same_transform

When the SideImage() is scaled down, it might make sense to enable mipmapping in the Dissolve():

transform same_transform(old, new):
    old
    new with Dissolve(0.2, alpha=True, mipmap=True)

define config.side_image_same_transform = same_transform

Functions

renpy.get_side_image(prefix_tag, image_tag=None, not_showing=None, layer=None)

This attempts to find an image to show as the side image.

It begins by determining a set of image attributes. If image_tag is given, it gets the image attributes from the tag. Otherwise, it gets them from the image property suplied to the currently showing character. If no attributes are available, this returns None.

It then looks up an image with the tag prefix_tag, and attributes consisting of:

  • An image tag (either from image_tag or the image property supplied to the currently showing character).

  • The attributes.

If such an image exists, it's returned.

not_showing

If not showing is True, this only returns a side image if an image with the tag that the attributes are taken from is not currently being shown. If False, it will always return an image, if possible. If None, takes the value from config.side_image_only_not_showing.

layer

If given, the layer to look for the image tag and attributes on. If None, uses the default layer for the tag.

renpy.set_tag_attributes(name, layer=None)

This sets the attributes associated with an image tag when that image tag is not showing. The main use of this would be to directly set the attributes used by a side image.

For example:

$ renpy.set_tag_attributes("lucy mad")
$ renpy.say(l, "I'm rather cross.")

and:

l mad "I'm rather cross."

are equivalent.