[Solved] Renpy variable in scene command, is possible?

Porcus Dev

Engaged Member
Game Developer
Oct 12, 2017
2,582
4,693
Hi,

I hope you can help me with a question about variables.

I have an identical sequence but with three possible dresses (with fullscreen images), and at the moment I have put this code to show one of the three dresses according to a variable:

Code:
default katia_sport_dress = 1

label katia_forgottenpark_md:
    if katia_sport_dress == 1:
        scene katia train_ves1_5
    if katia_sport_dress == 2:
        scene katia train_ves2_5
    if katia_sport_dress == 3:
        scene katia train_ves3_5
    k "bla, bla, bla..."
This way works and show the correct image but that means repeating this conditional about 30 times and more in the future... of course this is the simple way but I think that perhaps not the easier.
I've tried to use variables in name but any of my tries doesn't works.

I've tried something like:
Code:
scene katia train_ves[katia_sport_dress]_5
or
Code:
scene katia train_ves + [katia_sport_dress] + _5
I don't know if this is possible with "scene" command.

I need the help of this forum Gurus ;):coldsweat:

Thanks in advance.
 

khumak

Engaged Member
Oct 2, 2017
3,674
3,707
You can use a condition switch where you're doing your image definitions like this:

image Day10_HotTub46 = ConditionSwitch(
"StringBikini == 1", "backgrounds/Day10_HotTub46a.jpg",
"StringBikini == 0", "backgrounds/Day10_HotTub46b.jpg",)

Then when you call the scene later you can do something like this and it will using the right clothing option:

scene Day10_HotTub46 with dissolve

The example above is from Babysitter.
 

Porcus Dev

Engaged Member
Game Developer
Oct 12, 2017
2,582
4,693
Hi khumak,

First, thanks for your help!

I already take a look at "CoditionSwitch" command in renpy documentation, but this way I need to declare all images, it's more or less similar to write all conditionals with "if" command; I try to find a way to use variable in a more direct way.

Maybe what I'm looking for can't be done and I'll have to opt for one of these other methods.
 

khumak

Engaged Member
Oct 2, 2017
3,674
3,707
Yeah the condition switch would be an indirect method but you only have to declare it once. Then you can change the variable however many times you want and the scene command will automatically use the right clothing based on the variable change since the condition switch is just redefining it any time the variable changes. There may be other ways to do it. I don't have my own game, I just started modding recently.
 
  • Like
Reactions: Porcus Dev

Epadder

Programmer
Game Developer
Oct 25, 2016
568
1,062
By using the python statement equivalents to scene/show you can do string manipulation and do this:
Code:
    default katia_sport_dress = 1

    $ renpy.scene()
    $ renpy.show("katia train_ves%d_5" % (katia_sport_dress))
Now if you want the outfit to be a string instead of %d you use %s.
 

Porcus Dev

Engaged Member
Game Developer
Oct 12, 2017
2,582
4,693
By using the python statement equivalents to scene/show you can do string manipulation and do this:
Code:
    default katia_sport_dress = 1

    $ renpy.scene()
    $ renpy.show("katia train_ves%d_5" % (katia_sport_dress))
Now if you want the outfit to be a string instead of %d you use %s.
Yes!

That's exactly what I'm looking for.

Thanks a lot! ;)
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,561
15,518
By using the python statement equivalents [...]
Why using Python equivalent when you can use the natural behavior of the statement itself ?


Code:
image myScene = "whatever/needed/path/katia train_ves[katia_sport_dress]_5.png"

label something:
    scene myScene
Will do exactly what he want.
 

Porcus Dev

Engaged Member
Game Developer
Oct 12, 2017
2,582
4,693
Why using Python equivalent when you can use the natural behavior of the statement itself ?


Code:
image myScene = "whatever/needed/path/katia train_ves[katia_sport_dress]_5.png"

label something:
    scene myScene
Will do exactly what he want.
But this way I need to declare images :oops:
With the other way isn't needed :biggrin:

BTW: I think I've already tried your way (declare image with variable) and didn't worked to me, surelly I wrote something wrong x'D
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,561
15,518
But this way I need to declare images :oops:
What's wrong with declaring image ? Anyway they'll be declared. If it's not explicitly by you, it will be implicitly by Ren'py when it will start.
I can understand that you don't want to declare all the image, it's really a pain in the ass. But they also are a powerful tool to help you by simplifying the code you have to write. Like in this particular case, where a single line not only replace all the condition you gave as example, but also already cover all the possible future changes (you can add or remove variation of the picture without need to edit anything) and this will letting you continue to write the code in the regular way.


BTW: I think I've already tried your way (declare image with variable) and didn't worked to me, surelly I wrote something wrong x'D
Well, it's not impossible that there were a bug at one time, but it works like this since at least the version 6.99.12.4 (never tryied with a previous version).
 
  • Like
Reactions: Porcus Dev

Epadder

Programmer
Game Developer
Oct 25, 2016
568
1,062
For me the reason I took that approach is since I have a ton of images to crawl through (Since my mod/recreation is like Haramase Sim turned up to 11) and I know Ren'py will declare the images automatically so I already have names that accurately represent my images. It seemed like a better idea to just use variables to manipulate the names that follow a common structure instead of declaring specific images with another naming scheme on top of the already existing scheme.

An Example of my after battle scene code.:
Code:
label hscenelabel_LamiaGirlVictoryScene:
    stop music
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    $ randomized_GirlInVictoryScene = renpy.random.randint(1,24)
    scene scene_bg with dissolve
    nar "..."
    if randomized_GirlInVictoryScene < 10:
        $ renpy.show("lamia_0%d 1" % (randomized_GirlInVictoryScene), at_list=[transform_CenterInScreen, transformfunction_PulseSlow()])
    else:
        $ renpy.show("lamia_%d 1" % (randomized_GirlInVictoryScene), at_list=[transform_CenterInScreen, transformfunction_PulseSlow()])
    $ renpy.with_statement(dissolve)
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    nar "..."
    nar "..."
    if randomized_GirlInVictoryScene < 10:
        $ renpy.show("lamia_0%d 2" % (randomized_GirlInVictoryScene), at_list=[transform_CenterInScreen, transformfunction_PulseSlow()])
    else:
        $ renpy.show("lamia_%d 2" % (randomized_GirlInVictoryScene), at_list=[transform_CenterInScreen, transformfunction_PulseSlow()])
    $ renpy.with_statement(dissolve)
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    nar "..."
    nar "..."
    if randomized_GirlInVictoryScene < 10:
        $ renpy.show("lamia_0%d 3" % (randomized_GirlInVictoryScene), at_list=[transform_CenterInScreen, transformfunction_PulseSlow()])
    else:
        $ renpy.show("lamia_%d 3" % (randomized_GirlInVictoryScene), at_list=[transform_CenterInScreen, transformfunction_PulseSlow()])
    $ renpy.with_statement(dissolve)
    ## PLAY SOME SOUNDS
    nar "..."
    if randomized_GirlInVictoryScene < 10:
        $ renpy.show("lamia_0%d 2" % (randomized_GirlInVictoryScene), at_list=[transform_CenterInScreen, transformfunction_PulseSlow()])
    else:
        $ renpy.show("lamia_%d 2" % (randomized_GirlInVictoryScene), at_list=[transform_CenterInScreen, transformfunction_PulseSlow()])
    $ renpy.with_statement(dissolve)
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    nar "..."
    if randomized_GirlInVictoryScene < 10:
        $ renpy.show("lamia_0%d 4" % (randomized_GirlInVictoryScene), at_list=[transform_CenterInScreen, transformfunction_PulseSlow()])
    else:
        $ renpy.show("lamia_%d 4" % (randomized_GirlInVictoryScene), at_list=[transform_CenterInScreen, transformfunction_PulseSlow()])
    $ renpy.with_statement(dissolve)
    show whiteflash zorder 50
    ## PLAY SOME SOUNDS
    nar "..."
    if randomized_GirlInVictoryScene < 10:
        $ renpy.show("lamia_0%d 5" % (randomized_GirlInVictoryScene), at_list=[transform_CenterInScreen, transformfunction_PulseSlow()])
    else:
        $ renpy.show("lamia_%d 5" % (randomized_GirlInVictoryScene), at_list=[transform_CenterInScreen, transformfunction_PulseSlow()])
    $ renpy.with_statement(dissolve)
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    ## RUN A FUNCTION
    stop mid1 fadeout 0.5
    stop mid3 fadeout 0.5
    nar "..."
    scene scene_bg with dissolve
    ## PLAY SOME SOUNDS
    nar "..."
    jump functionlabel_AfterHSceneHub
 
  • Like
Reactions: Porcus Dev

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,561
15,518
It seemed like a better idea to just use variables to manipulate the names that follow a common structure instead of declaring specific images with another naming scheme on top of the already existing scheme.
I understand, but look at what your code can look like :
Code:
image lamiaVictory = "needed/path/lamia_[randVictoryScene] [victoryStep].ext"

label hscenelabel_LamiaGirlVictoryScene:
    stop music
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    $ victoryStep = 1
    # Directly format the randomized value in two digits
    $ randVictoryScene = "{:02}".format( renpy.random.randint(1,24) )
    scene scene_bg with dissolve
    nar "..."
    show lamiaVictory at transform_CenterInScreen, transformfunction_PulseSlow 
    with dissolve
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    nar "..."
    nar "..."
    $ victoryStep = 2  # The scene will automatically update itself
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    nar "..."
    nar "..."
    $ victoryStep = 3  # The scene will automatically update itself
    ## PLAY SOME SOUNDS
    nar "..."
    $ victoryStep = 2  # The scene will automatically update itself
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    nar "..."
    $ victoryStep = 4  # The scene will automatically update itself
    show whiteflash zorder 50
    ## PLAY SOME SOUNDS
    nar "..."
    $ victoryStep = 5  # The scene will automatically update itself
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    ## RUN A FUNCTION
    stop mid1 fadeout 0.5
    stop mid3 fadeout 0.5
    nar "..."
    scene scene_bg with dissolve
    ## PLAY SOME SOUNDS
    nar "..."
    jump functionlabel_AfterHSceneHub
It's smaller, easier to write and like there's less code, there's also less possibilities of errors.

For me, the really power of the text substitution for image is the fact that Ren'py take really care of everything, including the update of the screen. Where you had to show the scene many times, with the substitution you only need to show it once, and update the variables when it's needed.
It's a good way to completely disconnect the visual from the code. In the particular case of your example, the effect is minor. But imagine a game where the player can choose what the girl will looks like or the clothes she'll wear. Or a game when the mood, corruption, whatever, of the girl is reflected visually. You don't need to take care of that when you write your code. The scene to display is "girl washing the dishes" by example, and all you need is to code this :
Code:
label event_dishes5:
   scene roommate wash dishes
   "Looks like [rm.name] is occupied"
   menu:
         "help her":
             pass
         "Do nothing":
             return
   mc "Can I help you ?"
   [...]
This code will works whatever her mood/corruption/clothes/whatever, while the player will see a different scene depending of the said mood/corruption/clothes/whatever.
If after x updates you discover that finally the corruption level rise too quickly, you don't have to change your whole code to update every scene. You just change the small part where the said corruption level change the variable used for the substitution. Same if you want to add more clothes, remove a particular mood, and so on.
Like I said above, the code and the visual are completely disconnected, and it's one of the many ways to limit the possibilities of errors ; especially syntax errors. And, at least from my point of view, everything that can limit the number of possible errors is a good thing.
 
  • Like
Reactions: Porcus Dev

Porcus Dev

Engaged Member
Game Developer
Oct 12, 2017
2,582
4,693
I understand, but look at what your code can look like :
Code:
image lamiaVictory = "needed/path/lamia_[randVictoryScene] [victoryStep].ext"

label hscenelabel_LamiaGirlVictoryScene:
    stop music
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    $ victoryStep = 1
    # Directly format the randomized value in two digits
    $ randVictoryScene = "{:02}".format( renpy.random.randint(1,24) )
    scene scene_bg with dissolve
    nar "..."
    show lamiaVictory at transform_CenterInScreen, transformfunction_PulseSlow
    with dissolve
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    nar "..."
    nar "..."
    $ victoryStep = 2  # The scene will automatically update itself
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    nar "..."
    nar "..."
    $ victoryStep = 3  # The scene will automatically update itself
    ## PLAY SOME SOUNDS
    nar "..."
    $ victoryStep = 2  # The scene will automatically update itself
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    nar "..."
    $ victoryStep = 4  # The scene will automatically update itself
    show whiteflash zorder 50
    ## PLAY SOME SOUNDS
    nar "..."
    $ victoryStep = 5  # The scene will automatically update itself
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    ## RUN A FUNCTION
    stop mid1 fadeout 0.5
    stop mid3 fadeout 0.5
    nar "..."
    scene scene_bg with dissolve
    ## PLAY SOME SOUNDS
    nar "..."
    jump functionlabel_AfterHSceneHub
It's smaller, easier to write and like there's less code, there's also less possibilities of errors.

For me, the really power of the text substitution for image is the fact that Ren'py take really care of everything, including the update of the screen. Where you had to show the scene many times, with the substitution you only need to show it once, and update the variables when it's needed.
It's a good way to completely disconnect the visual from the code. In the particular case of your example, the effect is minor. But imagine a game where the player can choose what the girl will looks like or the clothes she'll wear. Or a game when the mood, corruption, whatever, of the girl is reflected visually. You don't need to take care of that when you write your code. The scene to display is "girl washing the dishes" by example, and all you need is to code this :
Code:
label event_dishes5:
   scene roommate wash dishes
   "Looks like [rm.name] is occupied"
   menu:
         "help her":
             pass
         "Do nothing":
             return
   mc "Can I help you ?"
   [...]
This code will works whatever her mood/corruption/clothes/whatever, while the player will see a different scene depending of the said mood/corruption/clothes/whatever.
If after x updates you discover that finally the corruption level rise too quickly, you don't have to change your whole code to update every scene. You just change the small part where the said corruption level change the variable used for the substitution. Same if you want to add more clothes, remove a particular mood, and so on.
Like I said above, the code and the visual are completely disconnected, and it's one of the many ways to limit the possibilities of errors ; especially syntax errors. And, at least from my point of view, everything that can limit the number of possible errors is a good thing.
Wow... well, this is different that I understand before.
This way I don't need to declare all images, only one time with the variables, and the good thing is that changing this variables renpy update automatically the shown image (so instead of write "scene" command" I need to write variable changes)

I'm still preparing the sequence so I try to use this... it's always good to know other methods (and better) to do things.

Thanks all!
 
  • Like
Reactions: anne O'nymous

Epadder

Programmer
Game Developer
Oct 25, 2016
568
1,062
@anne O'nymous - Fair Enough, I don't have that level of scene complexity. I will nab that string format example though, I don't understand how to use on my own so I used the older simpler replacement methodology.

As a side note even though they all use the same transform currently, they won't eventually. I just wanted to have them have that slight hint of movement as a default to make you think you're not necessarily looking at a static image. So without a master transform function I still need the individual show commands.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,561
15,518
So without a master transform function I still need the individual show commands.
Yeah, it's the limit of the method.
This said, I didn't shown it to say "you must do like this", but more to give a practical example. I know that the possibilities behind this substitution aren't always obvious ; especially if you don't know that Ren'py update the screen each time the variable's content change. So, a practical example explained it better.
 
  • Like
Reactions: Epadder

badcock

Member
Jun 2, 2018
131
650
I understand, but look at what your code can look like :
Code:
image lamiaVictory = "needed/path/lamia_[randVictoryScene] [victoryStep].ext"

label hscenelabel_LamiaGirlVictoryScene:
    stop music
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    $ victoryStep = 1
    # Directly format the randomized value in two digits
    $ randVictoryScene = "{:02}".format( renpy.random.randint(1,24) )
    scene scene_bg with dissolve
    nar "..."
    show lamiaVictory at transform_CenterInScreen, transformfunction_PulseSlow
    with dissolve
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    nar "..."
    nar "..."
    $ victoryStep = 2  # The scene will automatically update itself
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    nar "..."
    nar "..."
    $ victoryStep = 3  # The scene will automatically update itself
    ## PLAY SOME SOUNDS
    nar "..."
    $ victoryStep = 2  # The scene will automatically update itself
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    nar "..."
    $ victoryStep = 4  # The scene will automatically update itself
    show whiteflash zorder 50
    ## PLAY SOME SOUNDS
    nar "..."
    $ victoryStep = 5  # The scene will automatically update itself
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    ## PLAY SOME SOUNDS
    ## RUN A FUNCTION
    stop mid1 fadeout 0.5
    stop mid3 fadeout 0.5
    nar "..."
    scene scene_bg with dissolve
    ## PLAY SOME SOUNDS
    nar "..."
    jump functionlabel_AfterHSceneHub
It's smaller, easier to write and like there's less code, there's also less possibilities of errors.

For me, the really power of the text substitution for image is the fact that Ren'py take really care of everything, including the update of the screen. Where you had to show the scene many times, with the substitution you only need to show it once, and update the variables when it's needed.
It's a good way to completely disconnect the visual from the code. In the particular case of your example, the effect is minor. But imagine a game where the player can choose what the girl will looks like or the clothes she'll wear. Or a game when the mood, corruption, whatever, of the girl is reflected visually. You don't need to take care of that when you write your code. The scene to display is "girl washing the dishes" by example, and all you need is to code this :
Code:
label event_dishes5:
   scene roommate wash dishes
   "Looks like [rm.name] is occupied"
   menu:
         "help her":
             pass
         "Do nothing":
             return
   mc "Can I help you ?"
   [...]
This code will works whatever her mood/corruption/clothes/whatever, while the player will see a different scene depending of the said mood/corruption/clothes/whatever.
If after x updates you discover that finally the corruption level rise too quickly, you don't have to change your whole code to update every scene. You just change the small part where the said corruption level change the variable used for the substitution. Same if you want to add more clothes, remove a particular mood, and so on.
Like I said above, the code and the visual are completely disconnected, and it's one of the many ways to limit the possibilities of errors ; especially syntax errors. And, at least from my point of view, everything that can limit the number of possible errors is a good thing.
Anne,
Could you expand upon the line:

scene roommate wash dishes

What do the 2nd and 3rd argument do? How would "wash" and "dishes" be used?

This looks very interesting as, like you said, it's much less code. I started down the path of using renpy.show. In my case it appears I could setup three background image formats (for locations, scenes, and conversations) and set the appropriate variable. I'm guessing you could also do a series of images to simulate a movie. Something like (in psuedo python/renpy):

scene movie
for i = 1 to 15:
frame = i
pause 0.2
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,561
15,518
Anne,
Could you expand upon the line:

scene roommate wash dishes

What do the 2nd and 3rd argument do? How would "wash" and "dishes" be used?
It's just the name of the scene.
Ren'py permit to use spaces in the names of the defined scenes ; it's the recommended syntax and let you benefit from some advanced features and debug options. It come from the way Ren'py works, seeing the first word ("roommate") as base for the scene, and the other words ("wash" and "dishes") as i]attributes[/i] that define more precisely the actual scene.
So here it correspond to :
Code:
image roommate wash dishes = "roommate/[rm_clothes]/washing_dishes.jpg"
I could have wrote scene roommate_wash_dishes, it would have been the same ; and would probably have been easier to understood.
 
  • Like
Reactions: empeteror

badcock

Member
Jun 2, 2018
131
650
Ok, I was thinking the "wash" and "dishes" were somehow getting used as arguments in the string. So if I understand correctly you could do something like this:

default girl = Character(...
image girl = "girl/[emotion]-[clothing]-[action].png"

$emotion = "happy"
$clothing = "reddress"
$action = "dishes"

girl "....."

the image displayed would be "girl/happy-reddress-dishes.png"
and the following would switch the image to "girl/crying-reddress-dishes.jpg"?

$emotion = "crying"


Potentially lots of images, but also very powerful. Thanks for explaining.
 

empeteror

New Member
Jul 11, 2018
11
1
Code:
image roommate wash dishes = "roommate/[rm_clothes]/washing_dishes.jpg"

Could this be done with videos also?
I've tried to do it similarly like this, but it can't find the file:
Code:
$ girlname= "sarah"
image dance = Movie(play="characters/[girlname]/dance.webm")
show dance