Ren'Py Help me make imagebutton

DanStory

Newbie
Sep 30, 2021
50
66
Hello I'm trying to make adult VN, and I'm new about renpy
So, my question is I'm so confusing about imagebutton
i already trying every way to make imagebutton but still i can't, its always error intended,block etc..
can someone here give me example or code what i have to do with that picture so that i can create imagebutton myself in the future
thank you very much for helping me
btw i'm on progress to make classic story from highschool with some psychological disorder every main character
 
Apr 18, 2021
370
788
This is the best tutorial I have found on how to do it.
Just my opinion but I think your buttons may be a bit large though you shall have to try it out for yourself.

 

Radnor

Member
Game Developer
Nov 9, 2021
365
943
Code:
screen apart_first_floor():
  add "apart_first_floor"
  imagebutton:
    focus_mask "apart_left_idle"
    idle "apart_left_idle"
    hover "apart_left_hover"
    action Jump("go_to_kitchen")
  imagebutton:
    focus_mask "apart_right_idle"
    idle "apart_right_idle"
    hover "apart_right_hover"
    action Jump("go_to_living_room")
Normally you would want to add buttons positions, but as you using fullscreen images for them it's not needed.
Plus renpy internally crop transparent area, so it's not big performance issue either, i believe.

Jump() can be replaced with Return(whatever) depending how your free roaming logic is working.

focus_mask use idle image to avoid image flicker, which could happen if you use focus_mask True and certain combination of idle/hover images.
 

DanStory

Newbie
Sep 30, 2021
50
66
Code:
screen apart_first_floor():
  add "apart_first_floor"
  imagebutton:
    focus_mask "apart_left_idle"
    idle "apart_left_idle"
    hover "apart_left_hover"
    action Jump("go_to_kitchen")
  imagebutton:
    focus_mask "apart_right_idle"
    idle "apart_right_idle"
    hover "apart_right_hover"
    action Jump("go_to_living_room")
Normally you would want to add buttons positions, but as you using fullscreen images for them it's not needed.
Plus renpy internally crop transparent area, so it's not big performance issue either, i believe.

Jump() can be replaced with Return(whatever) depending how your free roaming logic is working.

focus_mask use idle image to avoid image flicker, which could happen if you use focus_mask True and certain combination of idle/hover images.
Thank you very much bro i'll try that code
 

Radnor

Member
Game Developer
Nov 9, 2021
365
943
Keep in mind code is not tested, just to give basic idea how to do it.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,576
2,204
Here's a thread I explained imagebuttons a while ago...
https://f95zone.to/threads/help-with-imagemaps.50306

I gave examples of how to create separate images to act as hotspots...
https://f95zone.to/threads/help-with-imagemaps.50306/post-3336130

I even went so far to create test project which was a full working game using the images I showed earlier...
https://f95zone.to/threads/help-with-imagemaps.50306/post-3336719
It can be downloaded, "played" and you can see the source code.

The important bit you need to know for using irregularly shaped images as hotspots is that you'll need .

Edit:

focus_mask "apart_left_idle"

Erm, that's not how focus_mask works. It's usually focus_mask True or focus_mask None (though more often it's just omitted rather than specifying None. I know you said it's untested, but that's one hell of a typo.
 
Last edited:

DanStory

Newbie
Sep 30, 2021
50
66
Here's a thread I explained imagebuttons a while ago...
https://f95zone.to/threads/help-with-imagemaps.50306

I gave examples of how to create separate images to act as hotspots...
https://f95zone.to/threads/help-with-imagemaps.50306/post-3336130

I even went so far to create test project which was a full working game using the images I showed earlier...
https://f95zone.to/threads/help-with-imagemaps.50306/post-3336719
It can be downloaded, "played" and you can see the source code.

The important bit you need to know for using irregularly shaped images as hotspots is that you'll need .

Edit:




Erm, that's not how focus_mask works. It's usually focus_mask True or focus_mask None (though more often it's just omitted rather than specifying None. I know you said it's untested, but that's one hell of a typo.
Thank you very much bro this is important thank you
 

Radnor

Member
Game Developer
Nov 9, 2021
365
943
Erm, that's not how focus_mask works. It's usually focus_mask True or focus_mask None (though more often it's just omitted rather than specifying None. I know you said it's untested, but that's one hell of a typo.


If you use True then currently visible image will be used, and if your hover image has transparent pixels where idle image has opaque then you will get flicker when player hover mouse over these pixels. To avoid this you use focus_make <displayable>, making it stable, in my code i used idle image.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,576
2,204


If you use True then currently visible image will be used, and if your hover image has transparent pixels where idle image has opaque then you will get flicker when player hover mouse over these pixels. To avoid this you use focus_make <displayable>, making it stable, in my code i used idle image.

Ah, I can see your point - though that's why I tend to make the hover image either identical in size (at a per pixel level) as the idle image... or make the hover image ever so slightly bigger by applying a glow or outline effect in addition to any color, hue, contrast or brightness changes I might make to highlight it to the player who move the pointer over it.

I stand corrected... it can be done that way.
 
  • Like
Reactions: Radnor

Sitho

"..more than a game!"
Game Developer
Sep 29, 2020
138
495
HeyGuys,

maybe one of you have an idea about this:

want to achieve:
- idle image is shown (if never interacted before)
- player interacts with "object" for the first time
- idle images changes into "not shown state" (but object is still interactable)

works perfectly fine after the "second interact"
and it doesn't show the "== 0 idle" anymore

..so, why does it preview the "idle == 0" after the first interact,
although it already changes it to "==1" after the first interact?

did I miss something?

best
~Sitho


Python:
label start:
define larissas_nachtschrank_angesehen = 0
jump larissas_wohnzimmer


label larissas_wohnzimmer:
    scene larissas_wohnzimmer with dissolve
    #(just to preview the current var state)
    if larissas_nachtschrank_angesehen == 1:
        "var = 1"
    else:
        "var = 0"
    call screen larissas_wohnzimmer_mouse_hover
    


screen larissas_wohnzimmer_mouse_hover():
       imagebutton:
            if larissas_nachtschrank_angesehen == 0:
                idle "larissas_nachtschrank_idle"
            else:
                idle "idle_alpha"
            hover "larissas_nachtschrank_hover"
            focus_mask True
            action Jump ("larissas_wohnzimmer_nachtschrank")
            
            
label larissas_wohnzimmer_nachtschrank:
    $ larissas_nachtschrank_angesehen = 1
    nar "XYZ"
    jump larissas_wohnzimmer
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,302
15,172
..so, why does it preview the "idle == 0" after the first interact,
although it already changes it to "==1" after the first interact?

did I miss something?
First thing first, strictly speaking you missed nothing.

Fixing your problem is simple, replace if larissas_nachtschrank_angesehen == 0: by if store.larissas_nachtschrank_angesehen == 0:, and it will works as you expect it.


As for the why, well... Be reassured, it's absolutely not your fault and you had no way to know it, but how to say this without being too sarcastically grumpy, and without complaining again because a project as big as Ren'Py have near to no test policy (well, I guess I already failed for this one) ?

Somewhere in the 7.x branch, PyTom introduced the notion of screen variables and local variables, because initially variables declared in a screen through default where only available in this screen, and unavailable in used screens. Since then, variables have a strange behavior in screens, and thanks to the obviousness of your problem, it's now clear that while doing this it, he broke the relation that screens have with global variables ; or at least changed this relation and, unless I missed it (what is still possible), didn't notified about this change.

I haven't looked at the code, and have no desire to do it, but I guess that screens get a copy of the global scope and that, for optimization reason, this copy isn't systematically updated. What mean that, unless you address the variable by explicitly specifying its store, a screen can perfectly works with outdated variables.

TL;DR:
Starting the 7.x branch, and by security, in a screen global variables SHOULD always be prefixed by store., or the corresponding store when it apply.
 
  • Like
Reactions: Sitho

Sitho

"..more than a game!"
Game Developer
Sep 29, 2020
138
495
Fixing your problem is simple, replace if larissas_nachtschrank_angesehen == 0: by if store.larissas_nachtschrank_angesehen == 0:, and it will works as you expect it.
works perfectly fine, thank you!

and thanks for the enlightenment about it!
(in my case it's 8.0.1 and it is still the same behaviour with it)

best
~Sitho
 
Last edited:

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,576
2,204
Python:
label start:
define larissas_nachtschrank_angesehen = 0
jump larissas_wohnzimmer

Two tiny things...

Since the value of larissas_nachtschrank_angesehen is a variable that will be changed directly while the program is running, it should probably be created using default rather than define.

Technically RenPy doesn't care where in the code default and define statements are found. RenPy (effectively) scans the whole code before the program starts to run and processes all those type of statements before anything else happens. It also ignores them if it encounters one while the script is running. But it's generally a good idea to put all your default and define statements before the label start: line. Usually all together at (or near) the top of the script file.

So I'd expect to see...

Python:
default larissas_nachtschrank_angesehen = 0

label start:

    jump larissas_wohnzimmer
 
Last edited:
  • Like
Reactions: Sitho

Sitho

"..more than a game!"
Game Developer
Sep 29, 2020
138
495
Two tiny things...

Since the value of larissas_nachtschrank_angesehen is a variable that will be changed directly while the program is running, it would probably be created using default rather than define.
[/CODE]

ahh.. yes I spelled & set it up "wrong" due to testing .. actually I have all variables in an seperate .rpy and there it's of course via "default" too! I still get confused with "define" and "default" here and there, I am still kind of new to all of this^^
All of the "jumps" and "calls" are seperated too, within their own .rpy's
But, thank you, for this additional note! :)
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,576
2,204
[...] I still get confused with "define" and "default" here and there [...]

It really is this simple:

If you have any code that says $ a = ... then it should be default a = ... otherwise define is fine.

The reasoning why is a little more complicated, but if you stick to the simple rule that "variables that will be changed/updated should be default" - that really is enough.

In short though... variables created with define are NOT normally saved into a savegame file. That changes when the value is changed/updated, whereupon it gets flagged as needing to be included in the save. Since the value will "sometimes" be in the save file and sometime not, things stop being easily predictable. Worst case scenario... you end up with some players out in the world loading save files which include values that cause the script to do unexpected things because the developer did something wrong in a previous release. default variables are ALWAYS included in save files.

The really common example used to be developers who didn't understand that a character and a character's name are two separate things.

So you'd end up with code like:

Python:
define e = Character("Eileen")

label start:

    $ e = renpy.input("What is the player's name?", exclude='[]{})

Now suddenly, e is part of the save file so even when the developer fixes the problem. So any player that loads those save files effectively breaks the game again, despite the fix. It is a complete PITA to fix without resorting to "Sorry, saves from 0.2 will no longer work. Please start a new game with version 0.3".

This is actually two coding problems, but highlights the one I'm trying to explain.

btw.. the correct code (for this very simplified example) should be:

Python:
default e_name = "Unknown"

define e = Character("[e_name]")

label start:

    $ e_name = renpy.input("What is the player's name?", exclude='[]{}')
# -or-
    $ e_name = renpy.input(_"What is the player's name?", exclude='[]{}')    # if you want your game to support translations.
 
Last edited:
  • Like
Reactions: Sitho

DanStory

Newbie
Sep 30, 2021
50
66
First thing first, strictly speaking you missed nothing.

Fixing your problem is simple, replace if larissas_nachtschrank_angesehen == 0: by if store.larissas_nachtschrank_angesehen == 0:, and it will works as you expect it.


As for the why, well... Be reassured, it's absolutely not your fault and you had no way to know it, but how to say this without being too sarcastically grumpy, and without complaining again because a project as big as Ren'Py have near to no test policy (well, I guess I already failed for this one) ?

Somewhere in the 7.x branch, PyTom introduced the notion of screen variables and local variables, because initially variables declared in a screen through default where only available in this screen, and unavailable in used screens. Since then, variables have a strange behavior in screens, and thanks to the obviousness of your problem, it's now clear that while doing this it, he broke the relation that screens have with global variables ; or at least changed this relation and, unless I missed it (what is still possible), didn't notified about this change.

I haven't looked at the code, and have no desire to do it, but I guess that screens get a copy of the global scope and that, for optimization reason, this copy isn't systematically updated. What mean that, unless you address the variable by explicitly specifying its store, a screen can perfectly works with outdated variables.

TL;DR:
Starting the 7.x branch, and by security, in a screen global variables SHOULD always be prefixed by store., or the corresponding store when it apply.
Wow I can try this..
Big thanks dude