Ren'Py Best way to show images

palumbra

Member
Nov 20, 2019
185
474
Also... a slight clarification of this latest suggestion...

Python:
init python:

    def showme(img):
        renpy.show(img, behind="t")
        renpy.with_statement(Dissolve(0.5))
        if store.previmg is not None:
            renpy.hide(store.previmg)
        store.previmg = img


default previmg = None

The version slightly higher in this thread wasn't working because it was using a local variable. The workaround of parsing the image name back and then passing it again does work, but is a bit cumbersome. But storing the image name as part of the function was always an option, you just needed a global variable instead.

I'm not familiar with the behind="t" but copied it because... well, why not.
ok many thanks, now renpy.hide works finaly.
How to set a global variable? i try but error error error... lol

behind="t" simply behind the text



working code:

You don't have permission to view the spoiler content. Log in or register now.
 
Last edited:

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
How to set a global variable?

Generally speaking, anything that is done within a function (the def: lines) uses local variables. They only exist within that specific function and can't be accessed elsewhere.

What I'm terming global variables are all the "normal" variables RenPy and your game uses.
So...

$ test1 = True
default test1 = True

... create (or update) global variables. In so much as they exist outside the functions at what I think of as that higher level accessible everywhere.

Or put another way... if you can imagine writing code after label start: that says if {varname} == {value}, then that variable is what I'm describing as global.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,369
15,285
I'm not familiar with the behind="t" but copied it because... well, why not.
It mean that the shown sprite will be displayed behind the sprite named "t".

But I don't see what this "t" can be. It's not the game interface, since images aren't clickable and screens aren't images. It's probably not a sprite, because as I said previously, this approach isn't designed to works with effective sprites. It can possibly be decoration for the dialog box, but it would be easier to edit the say screen, than showing a sprite for that.


behind="t" simply behind the text
Images are always behind the text. This unless the text is displayed as an image, what isn't a thing that should be just exceptionally done.
 

palumbra

Member
Nov 20, 2019
185
474
a funct for scene:

Python:
    def mscene(img,trans):
        renpy.scene()
        renpy.show(img)
        if trans == "":
            renpy.with_statement(Dissolve(0.5))
        elif trans == "cut":
            pass
        elif trans == "slow":
            renpy.with_statement(Dissolve(1.5))

instead using

scene blabla with dissolve

$ mscene("blabla","")

$ mscene("blabla","slow")

$ mscene("blabla","cut")


for behind t i suppose "t" is for text, the renpy doc its very mistic and criptic ...
so if its useless, i delete it
:ROFLMAO:
 

palumbra

Member
Nov 20, 2019
185
474
Generally speaking, anything that is done within a function (the def: lines) uses local variables. They only exist within that specific function and can't be accessed elsewhere.

What I'm terming global variables are all the "normal" variables RenPy and your game uses.
So...

$ test1 = True
default test1 = True

... create (or update) global variables. In so much as they exist outside the functions at what I think of as that higher level accessible everywhere.

Or put another way... if you can imagine writing code after label start: that says if {varname} == {value}, then that variable is what I'm describing as global.
so if i put

$ test1 = True
default test1 = True

before label start

then i can manipulate
test1
in renpy and in python blocks?

with (renpy block)
$ test1= False

or (python block)
test1 = False

correct?
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,369
15,285
a funct for scene:

Python:
    def mscene(img,trans):
        renpy.scene()
        renpy.show(img)
        if trans == "":
            renpy.with_statement(Dissolve(0.5))
        elif trans == "cut":
            pass
        elif trans == "slow":
            renpy.with_statement(Dissolve(1.5))
Ok, you're going way too far for absolutely no reason :
  1. Is it less complex ? No
    You're relying one three Python equivalents to achieve what a single statement could have done.
  2. Is it more flexible ? No
    You're hard coding the possible transition, what imply more limitation of your possibilities.
  3. Is the final syntax easier ? No
    The line now need to be prefixed by a $, and there's mandatory parenthesis and quotation marks absent from the statement syntax. And since everything now rely on the position of the value, it's also less intuitive than the statement and its properties.
  4. Is it covering all the original possibilities ? Perhaps
    The scene statement permit many things, and I'm not totally sure that all can be expressed with your code.
  5. Is it future compatible ? No
    If the scene statement evolve in the future, you'll have to change both the code and syntax of your function, what will force you to rewrite all your code using it.
  6. Is this making the devel faster ? No
    The syntax not being easier, and being less intuitive, you'll need more time to write your code.

Your :
Code:
$ mscene("blabla","")
$ mscene("blabla","slow")
$ mscene("blabla","cut")
can advantageously be replaced by native Ren'py code:
Code:
define slow = Dissolve( 1.5 )
define dissolve = Dissolve( 0.5 )

label whatever:
    scene blabla with dissolve
    scene blabla with slow
    scene blabla
Shorter, easier, more intuitive, and native so compatible with the future.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
so if i put

$ test1 = True
default test1 = True

before label start

then i can manipulate
test1
in renpy and in python blocks?

Yes. As long as you're not talking about init python: which happens during game startup.

Though technically $ is itself a python: block, since $ effectively means "do single python command".

What I would expect to see in a "normal" RenPy game (if such a thing exists) is...

Python:
default var1 = "Value"
default var2 = False
default var3 = 42

define e = Character("Eileen")

label start:

    scene black with fade
    "*** START ***"

    $ var3 += 1

    e "Welcome to my game, I'm [e]."

    python:
        for x in ...... :         # some semi complex python command that can't be done in RenPy's native code
            #                     # I dunno. My example is too simple to figure out what might go here.

    e "Thanks for playing."
    "*** THE END ***"
    return
 

Asmodeus_

Creator of Neuvau
Game Developer
Apr 5, 2020
939
3,871
The only kink is that the generated image displayables are named in lowercase. (So it's generally a good idea for files to be also named all in lowercase for your sanity).
Just to say thanks! :cool:
I've been indeed driving myself crazy with my uppercase filenames :mad:
 

PandaLulz

Assets Grabber
Uploader
Aug 18, 2017
1,250
7,305
Resurrected this thread as it's possibly the best place, for future viewers to reference to too but;

How would I be able to assign a set of images that are displayed only if a player selects an 'alternate' start. These would be overlayed ontop of already existing images/dialogue, just provide extra world context.

Before story even starts

"Show World Images" "Normal Start"

If "Show World Images" is selected - in the script then they'd only appear for that.

I hope i'm making sense!

I feel like it's an "if" conditional scenario, but pinging the code monkey that is anne O'nymous for some genius assistance. :WeSmart:
 
Last edited:

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,369
15,285
How would I be able to assign a set of images that are displayed only if a player selects an 'alternate' start. These would be overlayed ontop of already existing images/dialogue, just provide extra world context.
Hmm... it depend how frequently you'll have to do that.


The basic approach is to rely on a if:
Python:
# Assuming that the /showWorldImages/ flag tell when the play have chosen to see the extra content.

label whatever:
    # Display the base image
    scene whatever
    # If needed, display the extra content
    if showWorldImages:
        show whateverExtended
But having to write this every time can, and will, be a pain in the ass.


Another approach is to deport the processing:
Python:
# Assuming that the /showWorldImages/ flag tell when the play have chosen to see the extra content.

# Generic label used to display the images
label myScene( imgName ):
    # Firstly display the 'by default' image, accordingly to the name past as parameter.
    scene expression imgName

    # Then if the play asked to see the extra content, display the second image, which name
    # is suffixed by "_extended" ; you can use something else as suffix, but it MUST be the
    # same for all the images.
    if showWorldImages:
        show expression imgName + "_extended"

    # Finally return to the game flow.
    return

label whatever:
    # Display the image named "whatever".
    call myScene( "whatever" )
Like the base image is shown with scene, there's no need to hide the extended image, Ren'Py while do this automatically.
It's already better than the previous approach, but it still is a different way to display images than expected with Ren'Py, and this can be confusing when writing your code. Plus, even with the automation, there's still more things to type than the usual way to display an image.


Finally, the best, and easiest in term of development, approach is to create your own version of the scene statement. A version that will take care of everything for you, like the "myScene" label is doing:
00sceneEx.rpy:
Python:
python early hide:

    # Parse the script.
    def sceneExtendedParser( lex ):
        #  The name of the statement is already proceeded by Ren'Py, you just
        # need to take care of the parameters. Here there's just one, the name
        # of the image.
        img  = lex.image_name_component()

        #  Ensure that there's a none empty and valid image name.
        if img is None: lex.error( 'image name is NOT optional' )

        # Nothing more is needed.
        lex.expect_eol()

        # Provide the parameters to Ren'Py for further process.
        return ( img, )


    #  Execute the statement.
    def sceneExtendedExecute( t ):

        # Clean the screen
        renpy.scene()

        # Show the 'base image'
        renpy.show( t[0] )

        #  Show the extra content if needed.

        #  Here again, 'showWorldImages' is the default name for the flag,
        # you can change it to something different, just don't forget the 'store.'
        # prefix to be sure that it will always works fine.
        if store.showWorldImages:
            #  Here again, you can replace the suffix by something else than
            # "_extended", but you need to always have the same suffix for all
            # the extra content images.
            renpy.show( t[0] + "_extended" )

    # Create the new statement named "sceneEx".
    renpy.register_statement( 'sceneEx', parse=sceneExtendedParser, execute=sceneExtendedExecute )
This create the new statement and ABSOLUTELY need to be proceeded early, so to have a name that appear in top of the alphabetical order.

And now you just need to remember that there's two way to display the image. With the usual scene statement, and with the new sceneEx statement. Which one to use depending if there's or not extra content available:
Python:
label whatever:
    # Display a regular image named "bathroom01.jpg" without extra content available.
    scene bathroom01
    [...]
    # This display an image name "bathroom02.jpg", with an extra content image
    # named "bathroom02_extended.jpg", that will be displayed only if the player
    # decided it.
    sceneEx bathroom02
You fallback to a more natural way to write your game code, and don't really have more to type in order to have the extra content.
The only obligation is to remember that the extra content is the name of the image, plus "_extended".
 
  • Like
Reactions: gojira667
Apr 14, 2018
61
39
Now... you're probably thinking about renaming your image files to use spaces rather than underscores. That way, you don't need to manually add all those extra image statements. It's a pain in the arse. Better to stick to underscores, which is what applications like Daz3D will want to use anyway.

RenPy already has you covered.

Add this line into your options.rpy file...

define config.automatic_images = [' ','_','-','/']

This will strip any of those characters out of the filename and create an image statement using the removed characters as separators for the tagging system.
Because of the "/" in the list, that also means any subdirectory names are also processed too.

You can make use of this by picking directory names to aid the tagging system.

/images/bg/myroom01.jpg -> image bg myroom01 = "/bg/myroom01.jpg"
/images/bg/myroom02.jpg -> image bg myroom02 = "/bg/myroom01.jpg"
/images/eileen/smiling.png -> image eileen smiling = "/eileen/smiling.png"
/images/eileen/neutral.png -> image eileen neutral = "/eileen/neutral.png"
/images/eileen/sad.png -> image eileen sad = "/eileen/sad.png"
Thank you so much for this detailed explanation.

Edited:

When trying to add config.automatic_images in the options.rpy I first overlooked that the expected image name would result in

Python:
show images eileen happy
In order to just be able to write

Python:
show eileen happy
Python:
define config.automatic_images = [' ','_','-','/']
needs to be used in combination with:

Python:
 define config.automatic_images_strip = [ 'images' ]
"strip" removes the indicated prefixes or folder names from the automatic_images.

If you have other sub folders that you do not want to include in the image name they can be excluded as well.

You don't have permission to view the spoiler content. Log in or register now.

You don't have permission to view the spoiler content. Log in or register now.


An extended google search yielded a reference to it on sandbox-adventure.

Adding it this way at the very end in options.rpy below the Build configuration init python: block also worked for me:

Python:
## Custom Options ##############################################################

# activate automatic image importation
    config.automatic_images = [ ' ', '_', '-', '/' ]
# allow to gather all images in the /game/images folder without having all the name starting with "images"
    config.automatic_images_strip = [ 'images' ]
 
Last edited:
  • Like
Reactions: 79flavors