Ren'Py How to make a image button insensitive until the character finish their sentence?

iSleepZZZ

New Member
Aug 10, 2022
14
4
126
Hi guys. Just like the title, how can I make the image button on the screen only clickable after the character has finished speaking?
Here's a simple demonstration of my code:

Python:
label start:
  show screen change_conversation
  mc "A veeeeeeeeeerrrrrrrrry long dialogue."
  return

screen change_conversation:
  imagebutton:
    
    # if character is speaking:
    #    sensitive False
    # else:
    #    sensitive True
    
    auto "image/button_%s.png"
    action ToggleScreen("Some_other_screen")
I want the image button only able to be toggled when the mc has finished speaking. But the screen need to stay up there when the mc speaks. Is there a way to do that? Thanks.
 

Winterfire

Conversation Conqueror
Respected User
Game Developer
Sep 27, 2018
6,384
9,155
800
Switched to my alt account real quick :KappaPride: to let you know that it should be quite easy to do what you want, you simply need to set a bool as a temp variable. Or it can be a global one if you often need to turn on/off the button.
You can simply have a bool variable at the start being false (so sensitive false), then once the dialogue is done, you can set it to true, making the button interactable.


-edit-
To expand on that, I wrote some quick code (not sure if it works, but it should show what I meant better) while reminiscing the happy days with
Count Morado and how we used to share meals (I ate most of them because I am fat):

Python:
default dialogueComplete = False

label start:
    $dialogueComplete = False #in case it was changed by something else.
    show screen change_conversation
    mc "Count Morado"
    mc "COUNT MORADO"
    $dialogueComplete = True
    
    return

screen change_conversation:
    imagebutton:
        auto "image/button_%s.png"
        action If(dialogueComplete, ToggleScreen("Some_other_screen"))
        sensitive dialogueComplete
 
Last edited:
  • Like
Reactions: iSleepZZZ

iSleepZZZ

New Member
Aug 10, 2022
14
4
126
Thanks for the reply, here's how I do it with your suggestion:
Python:
label start:
    default dialog_end = True
   
    show screen change_conversation
    $ dialog_end = False
    mc "A veeeeeeeeeerrrrrrrrry long dialogue.{nw}"
    $ dialog_end = True
    extend "" # I do this to let the dialogue stay on the screen.
    return

screen change_conversation:
  imagebutton:

    sensitive dialog_end

    auto "image/button_%s.png"
    action ToggleScreen("Some_other_screen")
It works... although I'm think if there's any less repeating way to do it since I have many more dialogue that need the same function.

Thank you for you help.
 

Winterfire

Conversation Conqueror
Respected User
Game Developer
Sep 27, 2018
6,384
9,155
800
Thanks for the reply, here's how I do it with your suggestion:
Python:
label start:
    default dialog_end = True
  
    show screen change_conversation
    $ dialog_end = False
    mc "A veeeeeeeeeerrrrrrrrry long dialogue.{nw}"
    $ dialog_end = True
    extend "" # I do this to let the dialogue stay on the screen.
    return

screen change_conversation:
  imagebutton:

    sensitive dialog_end

    auto "image/button_%s.png"
    action ToggleScreen("Some_other_screen")
It works... although I'm think if there's any less repeating way to do it since I have many more dialogue that need the same function.

Thank you for you help.
I don't agree with keeping the "default dialog_end" within the label start, if you're reusing it for other stuff.

Also, you could simply use Pause: instead of extend, I feel it's a better usage for what you intend to do.

Also, if you want to shorten it or make it more simple, the answer is always the same: Functions.

If you wrote a function, you could simply call it at the end of a dialogue to set that boolean to true. As an extra, you could have the function pause AND set the boolean to true.
You could also call the same function (or a different one) by the screen to set it back to false, since action can be an array (togglescreen + call function), this way it's pretty much set and forget.

They're highly useful to avoid repetition and do other cool functions you might need, so if you haven't already, learn them!
 

iSleepZZZ

New Member
Aug 10, 2022
14
4
126
Sorry I'm not good with coding so I only know the basic way to use the Call function.

Here's how I imagine it works with the call function:

Python:
default dialog_enable = True

label start:
    show screen change_conversation
    
    call dialog_start
    mc "A veeeeeeeeeerrrrrrrrry long dialogue.{nw}"
    call dialog_end
    pause

    return

label dialog_start:
    $ dialog_enable = False
label dialog_end:
    $ dialog_enable = True
    
screen change_conversation:
  imagebutton:
    sensitive dialog_enable
    auto "image/button_%s.png"
    action ToggleScreen("Some_other_screen")
So... If there are more dialogues, it will become...

Python:
label start:
    show screen change_conversation
    
    call dialog_start
    mc "Dialogue 1.{nw}"
    call dialog_end
    pause
    
    call dialog_start
    mc "Dialogue 2.{nw}"
    call dialog_end
    pause
    
    call dialog_start
    mc "Dialogue 3.{nw}"
    call dialog_end
    pause
    
    call dialog_start
    mc "Dialogue 4.{nw}"
    call dialog_end
    pause

    ...

Umm... Sorry if I understand it wrong.
 

Winterfire

Conversation Conqueror
Respected User
Game Developer
Sep 27, 2018
6,384
9,155
800
Sorry I'm not good with coding so I only know the basic way to use the Call function.

Here's how I imagine it works with the call function:

Python:
default dialog_enable = True

label start:
    show screen change_conversation
   
    call dialog_start
    mc "A veeeeeeeeeerrrrrrrrry long dialogue.{nw}"
    call dialog_end
    pause

    return

label dialog_start:
    $ dialog_enable = False
label dialog_end:
    $ dialog_enable = True
   
screen change_conversation:
  imagebutton:
    sensitive dialog_enable
    auto "image/button_%s.png"
    action ToggleScreen("Some_other_screen")
So... If there are more dialogues, it will become...

Python:
label start:
    show screen change_conversation
   
    call dialog_start
    mc "Dialogue 1.{nw}"
    call dialog_end
    pause
   
    call dialog_start
    mc "Dialogue 2.{nw}"
    call dialog_end
    pause
   
    call dialog_start
    mc "Dialogue 3.{nw}"
    call dialog_end
    pause
   
    call dialog_start
    mc "Dialogue 4.{nw}"
    call dialog_end
    pause

    ...

Umm... Sorry if I understand it wrong.
What I meant is python functions, but even in your example, you could put "pause" in the dialog_end so you don't need to repeat it.
Also, you could avoid calling "dialog_start" if you turn the boolean back to False as an action once you're done in the screen.
 

iSleepZZZ

New Member
Aug 10, 2022
14
4
126
Thank you very much! I think got it sorted out.
Python:
default button_enable = False

label start:
    show screen change_conversation

    mc "Dialog1.{nw}"
    call next_line

    mc "Dialog2.{nw}"
    call next_line
    
    mc "Dialog3.{nw}"
    call next_line
    
    mc "Dialog4.{nw}"
    call next_line

    return

label next_line:
    $ button_enable = True
    pause
    $ button_enable = False

screen change_conversation:
  imagebutton:
    sensitive button_enable
    auto "image/button_%s.png"
    action ToggleScreen("Some_other_screen")
It solved my image button problem and the code looks more tidy now. Thanks again for your help @Winterfire
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
12,726
20,889
1,026
Thank you very much! I think got it sorted out.
Hmm...

I'm not really sure what you want to achieve, but let me tell you that average players will hate your game, because they'll have to click twice for every single dialog line to advance, this due to the pause. This will advanced players will hate your game because of its unusable button, that never turn sensitive because they bypass the said pause.


But a change of perspective offer you a better approach. Instead of wanting the button to only be sensitive when a character finished to speak, make its action only happen when the character finished to speak:

Python:
screen change_conversation:
    imagebutton:
        auto "image/button_%s.png"
        action SetVariable( "changeAsked", True )

default changeAsked = False

label whatever:
    show screen change_conversation

    mc "blablabla"
    call changeAsked

    mc "blablabla"
    call changeAsked
    [...]

label changeAsked:
    if changeAsked:
        hide screen change_conversation
        show screen Some_other_screen
        $ changeAsked = False
    return
This approach also offer you way more flexibility, by letting you reuse both the "change_conversation" screen and the "changeAsked" label for all the future changes you could need:
Python:
screen change_conversation:
    imagebutton:
        auto "image/button_%s.png"
        action SetVariable( "changeAsked", True )

default changeAsked = False

label whatever:
    show screen change_conversation

    mc "blablabla"
    call changeAsked( "Some_other_screen" )

    mc "blablabla"
    call changeAsked( "Some_other_screen" )
    [...]


label changeAsked( newScreen ):
    if changeAsked:
        hide screen change_conversation
        show screen expression newScreen
        $ changeAsked = False
    return
 

iSleepZZZ

New Member
Aug 10, 2022
14
4
126
I'm not really sure what you want to achieve...
Thanks for answering my question. The reason I want the button to be disabled until a character finished to speak is I'm using a Callback function which makes beeping sound when the character speaks. If the other screen is activated when the character is still speaking, the beeping sound won't stop, and the line they're saying is paused too.

...they'll have to click twice for every single dialog line to advance, this due to the pause...
Also about the pausing problem, I add a {nw} at the end of each line before the Call function, so they will end up clicking once only for each line.

The last approach you provided sure seems better. I will try it out. Thanks again.