Ren'Py renpy.image("x", Image("path/x.png") ) returns None

Saki_Sliz

Well-Known Member
May 3, 2018
1,403
1,004
I'm running into the titled issue, where renpy.image() seems to return None, and I can't figure out why

my only guess is maybe I'm doing something wrong with the image file path, but I don't know what, as you can see in the code below I try to hard code the path as well but still I get None

Code:
1674080846288.png
source problem (causes my other scripts to fail)
1674079919281.png

here's the file structure
1674080402393.png

because I can only run load images in an init: I can't test by hand what it takes to make the code work
1674080976265.png

I have seen somewhere, something about using %s at the end right before ".png" but I can find where I came across this and what it signifies

The only thing that matters is shoving all the images into the b_normal array, to be used by other scripts. So if need be, I can manually type each entry and ignore the for loop... but I feel I should be able to make the for loop work, but what concerns me is that my test code after the for looped didn't work either, so I must be missing something.

I usually try not to be annoying, trying to solve problems on my own before asking for help, but I can't think of a damn thing to search for to figure out what's wrong, everything I understand says this is ok code. Any help would be appreciated.
 

rayminator

Engaged Member
Respected User
Sep 26, 2018
3,040
3,135
I have seen somewhere, something about using %s at the end right before ".png" but I can find where I came across this and what it signifies
what version of renpy are you using so we don't give a code that for python 2 or 3

more info here for %s
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,309
15,185
I stop you there.

define (as well as default and some others) create its own "init" context. The statement SHOULD be at 0 level of indentation.

renpy.image() declare an image, but return nothing. So anyway it's normal that your b_normal list only contain None.

Image displayable expect a fully qualified image name as argument, and "[b_normal_local][x].png" isn't a fully qualified image name. Text interpolation only apply to renpy.image. Anyway there's another error here, see below.

You are going really far in the interpolation here, having one in the image name (renpy.image), one in the file name (Image) and this last one itself rely on an interpolation (b_normal_local). Even if you could use text interpolation in the Image displayable, Ren'Py wouldn't follow you this far.

What lead to: define are constants in mind, not in use. Ren'Py isn't a compiled language, when you use a constant somewhere, the value isn't immediately replaced.

What at its turn lead to: text interpolation apply in real time and in real time only.

What mean that you defined 12 times an image named "b_normal_[x]", and all of them point to a displayable expected to use an image named "[b_normal][x].png".

In its spirit, your code should have been:
b_normal.append( renpy.image( "b_normal_{}".format( x ), Image( "{}{}.png".format( "[bubble]/Normal/", x ), xalign=0.5, yalign=0.5) ) )
But as I said, it wouldn't works since there's text interpolation in the image name passed to the Image displayable, and renpy.image return nothing.


In the end, your code should be:
Python:
image b_normal_1 = "[bubble]/Normal/1.png"
[...]
image b_normal_n = "[bubble]/Normal/n.png"
[...]
# Range stop *before* the last value.
image b_normal_12 = "[bubble]/Normal/12.png"
Alternatively it's possible (can't verify right now) that you can simplify it with:
Python:
init python:
    for x in range(1, 13):
        renpy.image( "b_normal_{}".format( x ), "[bubble]/Normal/{}.png".format( x ) )
You'll not have the alignment part, but would have 12 images, all pointing to a different file. File that itself would depend, in real time, of the value gave to bubble. And, unless I misunderstood your code, it's what you wanted to have as image.

And it stop here, because images are stored on their own space, and aren't available as variable, so your b_normal list can't be built, whatever method you want to use.
Well, technically it's always possible to access the images as variables, but it would be dirty and you wouldn't be able to use them.


The only thing that matters is shoving all the images into the b_normal array, to be used by other scripts.
And it's the only thing that isn't possible. So, what do you want to do with the b_normal list ?
I'm sure that it can be done without it.

At worse, you can replace it by a ConditionSwitch displayable:
Python:
image myImage = ConditionSwitch(
    "var = 2", "b_normal_2",
    [...]
    "var = n", "b_normal_n",
    [...]
    "var = x", "b_normal_x",
    "True", "b_normal_1" )

default var = 1

label whatever:
    show myImage
    $ var = 2
    "blablabla"
    $ var = 5
    "blablabla"
 

gojira667

Member
Sep 9, 2019
268
245
I'm running into the titled issue, where renpy.image() seems to return None, and I can't figure out why
:unsure: Mainly it's because renpy.image() in fact returns None. UTSL, . Though it might be nice if the documentation actually stated the return value.

You will want your renpy.image() statements by itself in your loop then append the registered strings to your list. Actually, see anne's post above.

Also, post code as text...in code blocks...
 
Last edited:
  • Like
Reactions: Saki_Sliz

Saki_Sliz

Well-Known Member
May 3, 2018
1,403
1,004
Thanks guys, looks like I have to retype image b_normal_1 = "[bubble]/Normal/1.png" again, Darn. thats basiaclly how the first prototype was coded and worked. I just wanted to save on typing since I added all the other bubble type. shoving all the images into a list (after making each unique image variable such as in the above code) was just so that 1 the code could do some math for me to calculate text placement in each unique bubble (different size and shapes and tails), and then by using lists like a hash table with a bit of python, a made a screen to replace the dialog boxs and allow me to give characters speech bubbles (I got tired of the static dialog box).
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,577
2,209
I'm so out of my depth in this thread,

But my thought was "isn't there something called ?"

It may not apply here, but my very quick skimming saw "image" and "text interpolation" mentioned.
Since the image interpolation is done at runtime, wouldn't that pre-empt some of the assignments you are making ahead of time?
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,309
15,185
shoving all the images into a list (after making each unique image variable such as in the above code) was just so that 1 the code could do some math for me to calculate text placement in each unique bubble (different size and shapes and tails), and then by using lists like a hash table with a bit of python, a made a screen to replace the dialog boxs and allow me to give characters speech bubbles (I got tired of the static dialog box).
If it's to select the bubble to use, it's still possible. Either through ConditionSwitch, or through text interpolation.

I guess that it apply to the "say" screen, so either:
Python:
image sayBackground = ConditionSwitch(
    "computeSize() == 2", "b_normal_2",
    [...] )
 
init python:
    def computeSize():
        # Get the currently displayed dialog line from /store._last_say_what/
        [do the computation and return the correct value]
And you use "sayBackground" as background for the dialog box:
[screen.rpy]
Python:
style window:
    xalign 0.5
    xfill True
    yalign gui.textbox_yalign
    ysize gui.textbox_height

    background sayBackground
or:
Python:
init python:
    def computeSize( text ):
        # Getting the dialog line directly is always better
        [do the computation and return the correct value]

screen say(who, what ):

    style_prefix 'say'

    window:
        id 'window'
        has vbox
        background ( "b_normal_{}".format( computeSize( what ) ) )

        if who is not None:
            window:
                id 'namebox'
                style "namebox"
                text who id 'who'

        text what:
            id 'what'
            style_suffix 'dialogue'

        ## If there's a side image, display it above the text. Do not display on the
        ## phone variant - there's no room.
        if not renpy.variant("small"):
            add SideImage() xalign 0.0 yalign 1.0

style window:
    xalign 0.5
    xfill True
    yalign gui.textbox_yalign
    ysize gui.textbox_height

# not needed anymore
#    background Image("gui/textbox.png", xalign=0.5, yalign=1.0)
 

Saki_Sliz

Well-Known Member
May 3, 2018
1,403
1,004
I'm so out of my depth in this thread,

But my thought was "isn't there something called ?"

It may not apply here, but my very quick skimming saw "image" and "text interpolation" mentioned.
Since the image interpolation is done at runtime, wouldn't that pre-empt some of the assignments you are making ahead of time?
Due to how dynamic images work, I figure a state based system is best used with that, such as what I am using for my characters (having poses, clothing, clothing layers, expressions, etc). Renpy, as you mentioned, can do a lot of the heavy lifting, such as with the subject + attribute system, so that I don't need to set a bunch of variables to configure the dynamic image state. However, that means every time I want to use a speech bubble (which i want to use for every line and sound effect), I need to configure the state before giving the dialog... basically bloating my scripts with state configuration between every line of dialog. This is solvable by creating a label/screen to pass parameters into, and have said label/screen do the state configuration, but then thats actually a bad habit of novice programming, setting state variables to indirectly control the thing I actually want to control, ie its basically redundant code that doesn't reduce complexity....

But the main reason I am going my technique is I want speech bubbles to act like an animated comic, multiple speech bubbles on the screen at the same time, speech bubbles mutating as a way of indicating pacing (ie adding/transforming speech bubbles before removing all speech bubbles and replacing them with a new set of speech bubbles and animations). I'm trying to fake a sort of animated quality to a game that is driven mostly by players clicking. the prototype code to get this working was cleaner/simpler/more familiar using LUT's and hash tables rather than trying to work around renpy (ie I can call for multiple bubbles without having to manually tell renpy that yes, I want multiple bubbles)

Though it might be nice if the documentation actually stated the return value.
I will say, that after trying to use renpy's documentation, I have a lot more respect for Ren'py devs, especially those who's first programming experience is renpy. I have never had such a poor documentation experience before. The only other time I've struggled using a new program was with godot 3.0 release where the entire framework was changed without documentation (every function renamed, re coded, behaved differently, hell there wasn't even Intelisensed yet to automatically detect the name of the function you were typing), and it was up to the community to brute force figure out the new framework and host community made documentation. Things that should have taking 3 minutes took over a day to get working (me trying to get full screen pixel art to work ;n; ).

If it's to select the bubble to use, it's still possible. Either through ConditionSwitch, or through text interpolation.
while I can't say I know enough about ren'py's technical characteristics to worry about how performant conditional switching is during runtime, not that performance is really an issue, I will say that all my years of programming (C# 10 programming paradigms not to mention 5+ more just for good OOP design) I've learn/decided to avoid conditional statements like the plague (my own philosophy of good/clean coding), and text interpolation is how you get a hit squad to come after you in university (avoid like the plague x 100) (in fact it really bothers me to use python/renpy because of how often it uses string for a lot of its operations).

To clarify, I'm actually avoiding / not using the say screen (the dialog box) at all other than for debugging, simply because I like the aesthetics of speech bubbles and narrative bubbles way more than a general dialog box. Part of the speech bubble is that it is meant to look and act like a speech bubble, having a tail (see image below), possibly merging with other speech bubbles, and as I mentioned, several at once or in animated sequence one after another.
1674180683575.png
Because of features like this, i need a screen that takes in a bit more data, such as, where to place the speech bubble's tail, which way to turn it or which variant to use

ass you can see with the double [][] I'm using a combinations of luts and hash tables for 'little n' paradigm.

1674181012670.png
I'm also not using whosince who is speaking is obvious due to the speech bubble's tail... which is a shame because it out-modes one of my earlier character manager classes that does some tricks with 'who' and the say screen.

I haven't gotten around to really modifying the screens and gui file yet, just learned enough to make my own screens.
 

crabsinthekitchen

Well-Known Member
Apr 28, 2020
1,549
8,749
To clarify, I'm actually avoiding / not using the say screen (the dialog box) at all other than for debugging, simply because I like the aesthetics of speech bubbles and narrative bubbles way more than a general dialog box. Part of the speech bubble is that it is meant to look and act like a speech bubble, having a tail (see image below), possibly merging with other speech bubbles, and as I mentioned, several at once or in animated sequence one after another.
maybe will be useful