Ren'Py multiple character side images [solved]

Lou111

Active Member
Jun 2, 2018
538
680
Looking for something that will show an additional side image on the opposite side of the text box to show to whom the speaker is talking to.

Additionally, I'm looking for a way to show multiple side images on one side, like if someone is standing directly behind them or a small group is speaking to someone.

A good link will be most helpful here if anything (i struggle with searching with the right question).

Thanks again team.
 
Last edited:

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,364
15,281
Looking for something that will show an additional side image on the opposite side of the text box to show to whom the speaker is talking to.

Additionally, I'm looking for a way to show multiple side images on one side, like if someone is standing directly behind them or a small group is speaking to someone.

A good link will be most helpful here if anything (i struggle with searching with the right question).
I don't think that there's a link for that since it's far do be something basic. Plus, I'm not sure if it would effectively add something to the game, while it will clearly drastically increase the difficulty of the code.

Having a side image is easy, you define the right argument when creating a character. Then Ren'py will do everything else, changing the image in the same time it display a dialog line, accordingly to who's the speaker.
But what you want to do need way more works. Each time a character talk, you'll have to indicate to whom he is talking, or who stand behind him. It's possible do simplify a little your job and avoid having to define the value every single time, but it will still open the gate for many bugs.

All the way to do that rely on a rewriting of the say screen, what change is the way you want to pass the value. The easiest way is to rely on the say arguments :
[Note: code wrote on the fly, there's possibly some issues]
Python:
# You need to define the possible arguments here
screen say( who, what, interlocutor=None, behind=None ):
    style_prefix "say"

    if what == "":
        text what id "what" style "invisible"
    else:
        window:
            id "window"
            if who is not None:
               window:
                    style "namebox"
                    text who id "who"
            text what id "what"

        if not renpy.variant("small"):
            # If an image is defined for the person behind the speaker, display it a little shifted.
            if behind:
                add behind xalign 1.0 yalign 1.0 xoffset 10 yoffset -10
            add SideImage() xalign 0.0 yalign 1.0
            # If an image is defined for the interlocutor, display it at the opposite side.
            if interlocutor:
                add interlocutor xalign 1.0 yalign 1.0

label whatever:
    "blablabla"( interlocutor="images/sideimage/mc.jpg" )
    "bliblibli"( behind="images/sideimages/otherGirl.jpg" )
    "blobloblo"( interlocutor="images/sideimage/mc.jpg", behind="images/sideimages/otherGirl.jpg" )
    "blublublu"
After, you can simplify by using a dictionary to store the image, and just pass a keyword in place of the full image :
Code:
define sideImages = { "mc": "images/sideimage/mc.jpg",
                                                "otherGirl": "images/sideimages/otherGirl.jpg" }

screen say( who, what, interlocutor=None, behind=None ):
[...]
        if not renpy.variant("small"):
            if behind:
                add sideImages[behind] xalign 1.0 yalign 1.0 xoffset 10 yoffset -10
            add SideImage() xalign 0.0 yalign 1.0
            if interlocutor:
                add sideImages[interlocutor] xalign 1.0 yalign 1.0

label whatever:
    "blablabla"( interlocutor="mc" )
    "bliblibli"( behind="otherGirl" )
    "blobloblo"( interlocutor="mc", behind="otherGirl" )
    "blublublu"
Or "compose" the path to the image in real time:
Code:
screen say( who, what, interlocutor=None, behind=None ):
[...]
        if not renpy.variant("small"):
            # If an image is defined for the person behind the speaker, display it a little shifted.
            if behind:
                add ( "images/sideimages/{}.jpg".format( behind ) ) xalign 1.0 yalign 1.0 xoffset 10 yoffset -10
            add SideImage() xalign 0.0 yalign 1.0
            # If an image is defined for the interlocutor, display it at the opposite side.
            if interlocutor:
                add ("images/sideimages/{}.jpg".format( interlocutor ) ) xalign 1.0 yalign 1.0

label whatever:
    "blablabla"( interlocutor="mc" )
    "bliblibli"( behind="otherGirl" )
    "blobloblo"( interlocutor="mc", behind="otherGirl" )
    "blublublu"
But as I said, all those methods imply that you'll have to add the parameters every single time you'll write a dialog line.
You can avoid this by using external variables to store the information:
Python:
default interlocutor = None
default behind = None

screen say( who, what ):
[...]
        if not renpy.variant("small"):
            # If an image is defined for the person behind the speaker, display it a little shifted.
            if behind:
                add ( "images/sideimages/{}.jpg".format( behind ) ) xalign 1.0 yalign 1.0 xoffset 10 yoffset -10
            add SideImage() xalign 0.0 yalign 1.0
            # If an image is defined for the interlocutor, display it at the opposite side.
            if interlocutor:
                add ("images/sideimages/{}.jpg".format( interlocutor ) ) xalign 1.0 yalign 1.0

label whatever:
    $ interlocutor = "mc"
    # MC is seen at the right
    "blablabla"
     $ behind = "otherGirl"
    # MC is still seen at the right, and otherGirl behind
    "bliblibli"
    $ interlocutor = None
    # MC not anymore seen at the right, but otherGirl is still behind
    "blobloblo"
     $ behind =  None
     # otherGirl is not anymore seen behind
    "blublublu"
While it simplify a little your work, since the same configuration can be used for more than one dialog line, it don't really limit the number of possible bugs.
The "oops, I forgot to change the value" and "oops, I forgot to reset the value", will just replace the lack of "oops, I forgot to define the value".

There's other way to do it, way more advanced, but in the end none of them would effectively simplify the process. You have to explicitly tell what image have to be displayed, and this for almost every single line of dialog.
The only thing that change is the way to tell it, that can possibly be made easier. But as easier as it can be made, it will absolutely not remove the number of possible bugs.
There's already coders that confuse the sayer, making a dialog line being said by the wrong character. Imagine if in top of that you've also to take care of the "interlocutor" and "behind" values...


Therefore, the question is: Is all this really worth it ?

As I said, from my point of view this add nothing to the game. What character is "behind", is already know by looking at the screen. As for "to whom the character is talking", if it's not relatively obvious, then it mean that the dialog line isn't correct.
And in the same time, it complicate the writing of the code, and open the door to an incredibly high number of bugs.
 
  • Love
Reactions: Lou111

Lou111

Active Member
Jun 2, 2018
538
680
Therefore, the question is: Is all this really worth it ?
The part about if it's not relatively obvious without the help of additional side images really struck home for me.
I wanted to cut some corners by removing some of the narrator text during scenes with 10+ characters present but after your response I will be re-thinking my position here.

That said, these code examples are excellent. All of my research returned examples of side images presistently present on either side.

Thank you for taking the time to explain this to me.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,364
15,281
The part about if it's not relatively obvious without the help of additional side images really struck home for me.
I wanted to cut some corners by removing some of the narrator text during scenes with 10+ characters present but after your response I will be re-thinking my position here.
It totally depend of how you'll do your game, but there's also the possibility to use visual tricks to make it more obvious.

By example, with classical 2D sprite characters, you can zoom a little both the speaker and the interlocutor. It will make them be a little bigger than the other and so stand out enough to help the player understand who talk to who.
With a 3D game it's a little more difficult, since the character aren't independent of the whole screen. Here, the player will tend to assign the "interlocutor" role to the character near to the center of the screen. So between the camera angles, and possibly the help of Ren'py zoom and a change in the image position, you can achieve something that can possibly do the trick.

After, for the text itself, there's the obvious use of the first name or the nickname. In real life, we don't really do this, but in a game it don't feel too weird that sometime an "Alexandra" take the place that an "you" would have occupied ; or the place of a "she", what would exclude "Alexandra" of the possible interlocutor. Because you don't necessarily need to point the interlocutor obvious, you can also exclude the "none interlocutors".
There's also, more difficult since it's pure text, what make it less obvious, there's the tone. You don't talk to your mother with the same tone than to your sister, which isn't the same tone than you use for when you talk to a stranger. So, if by example the dialog line use a formal tone, it will exclude the friends as possible interlocutor. A sweet tone will exclude the character of the same sex than the speaker (unless it's a gay/lesbian character), and so on.

There's many levers that you can use. It need more times, but it's also more pleasant for the player ; the dialog flows naturaly, by itself, and the player just have to let this flow guide it through the scene.
 
  • Like
Reactions: Lou111

Lou111

Active Member
Jun 2, 2018
538
680
It totally depend of how you'll do your game, but there's also the possibility to use visual tricks to make it more obvious.

By example, with classical 2D sprite characters, you can zoom a little both the speaker and the interlocutor. It will make them be a little bigger than the other and so stand out enough to help the player understand who talk to who.
With a 3D game it's a little more difficult, since the character aren't independent of the whole screen. Here, the player will tend to assign the "interlocutor" role to the character near to the center of the screen. So between the camera angles, and possibly the help of Ren'py zoom and a change in the image position, you can achieve something that can possibly do the trick.

After, for the text itself, there's the obvious use of the first name or the nickname. In real life, we don't really do this, but in a game it don't feel too weird that sometime an "Alexandra" take the place that an "you" would have occupied ; or the place of a "she", what would exclude "Alexandra" of the possible interlocutor. Because you don't necessarily need to point the interlocutor obvious, you can also exclude the "none interlocutors".
There's also, more difficult since it's pure text, what make it less obvious, there's the tone. You don't talk to your mother with the same tone than to your sister, which isn't the same tone than you use for when you talk to a stranger. So, if by example the dialog line use a formal tone, it will exclude the friends as possible interlocutor. A sweet tone will exclude the character of the same sex than the speaker (unless it's a gay/lesbian character), and so on.

There's many levers that you can use. It need more times, but it's also more pleasant for the player ; the dialog flows naturaly, by itself, and the player just have to let this flow guide it through the scene.
Absolutely.
My game's style uses a lot of sub characters who are undefined but will have some personality presets. In an area where there are a lot of characters present I didn't want to over-invest with dialog build up but still include some chatter to validify their presence. My goal was to consider the time of the reader by cutting out the "Then Alexandra turns to sub-character and says in a happy tone..." etc.
I'm no writer that's for sure so I'll be bookmarking this page to keep my options open while keeping what you said in mind.