You can only click when the dialogue was done. How?

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
jayroll123
Newbie
Posts: 22
Joined: Tue Jul 02, 2013 9:32 pm
Contact:

You can only click when the dialogue was done. How?

#1 Post by jayroll123 »

Is there a way that i can disable mouse click? and Enable it after the text/dialogue was finished? Or finish the 1st dialogue before I can go to the second one..
Example:
"Jenny" "first Dialogue first Dialogue first Dialogue first Dialogue" - the text cps = 20
"Jords" "next Dialogue" - the text cps = 20

I need to finish the 1st dialogue before I can use the mouse to proceed to the next one. To avoid turbo click ..
THANKS

User avatar
Ophelia
Regular
Posts: 96
Joined: Mon Sep 16, 2013 11:38 am
Completed: tobag
Projects: Kajima
Contact:

Re: You can only click when the dialogue was done. How?

#2 Post by Ophelia »

Why don't you let the player decide themselves how slow or fast they want to read? I'm pretty sure most of us here don't really like being forced to read at a certain pace and I really wouldn't recommend doing you so.

SundownKid
Lemma-Class Veteran
Posts: 2299
Joined: Mon Feb 06, 2012 9:50 pm
Completed: Icebound, Selenon Rising Ep. 1-2
Projects: Selenon Rising Ep. 3-4
Organization: Fastermind Games
Deviantart: sundownkid
Location: NYC
Contact:

Re: You can only click when the dialogue was done. How?

#3 Post by SundownKid »

Yeah, there's no need to lock it to a certain CPS since there's rollback if the player accidentally clicks through something. It's proper usability to let the player move as fast as they want. People sometimes want to read things at different speeds.

jayroll123
Newbie
Posts: 22
Joined: Tue Jul 02, 2013 9:32 pm
Contact:

Re: You can only click when the dialogue was done. How?

#4 Post by jayroll123 »

Im doing an evaluation tool... I need to deal with that because there's a tendency that they(pupils) will not read the question when they get board and they just click2x the mouse to forward without understanding it. ..

User avatar
trooper6
Lemma-Class Veteran
Posts: 3712
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: You can only click when the dialogue was done. How?

#5 Post by trooper6 »

Is it doable? Yes it is. Totally doable. I am doing something similar in the game I am working on, and I've the whole thing working perfectly.

Doing this, however, does require a few moving parts. And my game is more complex that what you want (I have an interrupt button that allows some text to be interrupted and some not...I also have variables that keep track of if a player interrupted the interruptible speaker or not), but I think I can lay out what you'll need for your version.

First thing you want to do, is disable the ability for your player to interact with your game at all in the configs. So in the options.rpy file, at the end in the place where you put your own code, edit this:

Code: Select all

    config.keymap["dismiss"] = None
This makes it so that your player cannot click through on the game at all by default...though I'm pretty sure they can still click on menu options by default.

Now, you do actually want you to make it possible for the player to interact. So you create an invisible screen that puts that functionality back into play while the screen is up. I do that by putting that screen code at the end of the screens.rpy file like so:

Code: Select all

screen keyscreen:
    key "mouseup_1" action Return("smth")
    key "K_RETURN" action Return("smth")
    key "K_SPACE" action Return("smth")
    key "K_KP_ENTER" action Return("smth")
    key "joy_dismiss" action Return("smth")
And then right at the beginning of your start code, you show that keyscreen to give the interactivity back to the player, which I should be like this:

Code: Select all

show screen keyscreen
So the game starts and the player can interact. (Now this is where I'm going to have to improvise some untested code since I do things a bit differently.)

Then what you need to do is to create a callback function that removes the keyscreen while a text is scrolling and puts it back up again when the text is finished scrolling. That callback function should look something like this:

Code: Select all

init -1 python:
    def clicks(event, **kwargs):
        if event == "show" or event == "begin":
            hide screen keyscreen
        if even = "slow_done" or event == "end":
            show screen keyscreen
Then all you need to do is give this callback function to your characters that have the slow text thing going on. That would look like so:

Code: Select all

define tg = Character('Text Giver', color="#994411", what_slow_cps=20, what_slow_abortable=False, callback=clicks)
So, this should theoretically do what you want. Again, I just want to give the caveat that my actual code is a lot more complicated and so I stripped it down a lot to get what I think should work for you, but I haven't tested it.
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

jayroll123
Newbie
Posts: 22
Joined: Tue Jul 02, 2013 9:32 pm
Contact:

Re: You can only click when the dialogue was done. How?

#6 Post by jayroll123 »

Thanks for the reply. .

Code: Select all

init -1 python:
    def clicks(event, **kwargs):
        if event == "show" or event == "begin":
            hide screen keyscreen
        if even = "slow_done" or event == "end":
            show screen keyscreen
I put this at the beginning of my script.rpy and it says invalid syntax: hide screen -> keyscreen

jayroll123
Newbie
Posts: 22
Joined: Tue Jul 02, 2013 9:32 pm
Contact:

Re: You can only click when the dialogue was done. How?

#7 Post by jayroll123 »

I already solved it.

Code: Select all

init -1 python:

    def clicks(event, **kwargs):
        if event == "show" or event == "begin":
            renpy.hide_screen('keyscreen')
            #hide screen keyscreen
            #hideScreen
            
        if event == "slow_done" or event == "end":
            renpy.show_screen('keyscreen')
but the mouse click is not working after every dialogue.. . .

User avatar
trooper6
Lemma-Class Veteran
Posts: 3712
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: You can only click when the dialogue was done. How?

#8 Post by trooper6 »

jayroll123 wrote: but the mouse click is not working after every dialogue.. . .
If the mouse click works after some dialogue but not others, which characters is it working for, which isn't it working for? Is there a pattern that might lead to an answer? For example, have you given the callback to each character and narrator?
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

Elmiwisa
Veteran
Posts: 476
Joined: Sun Jul 21, 2013 8:08 am
Contact:

Re: You can only click when the dialogue was done. How?

#9 Post by Elmiwisa »

May I propose a different solution? This solution differed from the above by:
1. The player can click mouse to make all the text appear instantly, for those who read fast, but won't be able to proceed until enough time have passed for the text to be displayed if they were to be display in usual cps. EDIT: you can disable the text from displaying instantly too, see answer to trooper6's question below.
2. Direct use of say_allow_dismiss feature.
3. Instantly applicable to all say statement.
For this solution, simply add these line to near the start of the say screen code (after all the "default" line):

Code: Select all

    if _preferences.text_cps==0:
        on "show" action dismiss_control.allow_dismiss
    else:
        on "show" action dismiss_control.block_dismiss
        timer dismiss_control.calculate_time(what,_preferences.text_cps) repeat False action dismiss_control.allow_dismiss
    on "hide" action dismiss_control.allow_dismiss
And these to the init block that come right after the say screen code:

Code: Select all

    class DismissControl:
        def __init__(self):
            self.dismissable=True
            config.say_allow_dismiss=self.dismiss_check
            return
        def allow_dismiss(self):
            self.dismissable=True
            return
        def block_dismiss(self):
            self.dismissable=False
            return
        def dismiss_check(self):
            return self.dismissable
        def calculate_time(self,what,cps):
            if cps==0:
                return 0.01
            else:
                return (float)(len(what))/(float)(cps)+0.01
    dismiss_control=DismissControl()
Last edited by Elmiwisa on Sun Oct 06, 2013 4:18 pm, edited 1 time in total.

User avatar
trooper6
Lemma-Class Veteran
Posts: 3712
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: You can only click when the dialogue was done. How?

#10 Post by trooper6 »

Elmiwisa, I have a few questions about your code.

1) How do you alter this code so that the reader can't click to make the text show up instantly and still have it work?
2) How do you alter the code so that it only applies to some characters, but not others?
3) Where can I find out more about say_allow_dismiss feature? It looks really interesting! What all can be done with it? How could I use it to deal with variables or to do other things in addition?
4) Could you explain that line of code that goes "dismiss_control=DismissControl()" it looks really interesting!
5) Could you explain this code? What is it doing there? Why is it in that location.

Code: Select all

dismiss_control.allow_dismiss
    on "hide" action dismiss_control.allow_dismiss
6) Lastly, could you put the class definition somewhere else...like in a file that is dedicated to defining classes?

Thanks!
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

Elmiwisa
Veteran
Posts: 476
Joined: Sun Jul 21, 2013 8:08 am
Contact:

Re: You can only click when the dialogue was done. How?

#11 Post by Elmiwisa »

@trooper6:
1.2.&3. The say_allow_dismiss feature is in Configuation Variables documentation. See, the code made use of a very specific feature of Ren'Py that is meant for this kind of thing - that is to uniformly handle across the board whether you want to let the player click through the say statement or not. Any deviation from that and thing start to look less nice. I assume that jayroll123 want it to apply to all character, and that jayroll123 do not care whether the text is displayed instantly or not as long as the player is forced to wait for the timeout. But here are these modification anyway:
-To disallow clicking to display all text instantly, you need to set slow_abortable to False for all character, or at least those characters you want it to apply to. You need to define one for the narrator character too, because the default is True. For example:

Code: Select all

define boring_old_man=Character("Old Man",slow_abortable=False)
It's just like your code. Except that I don't have the "what_" because for this specific property it's actually not needed. However, in your method, it's literally impossible for you to enable ability to make all text appear: even if you set slow_abortable to True it still won't happen.
-To make whether dismissible apply to each character only, you basically need to intercept the say command to remember which character is speaking, then check them against a list of exception (or the list of application, if you want the default to be allowing the player to skip text instantly) when it come down to checking whether the player can dismiss instantly.
4.&6. Yes you can put the class definition somewhere else, as long as you make sure it run before the class is used to make a variable. I prefer to put it in the same location as say screens since it's really only related to say screen. And that line is just declaring a variable using that class.
5. Probably nothing. I am just super paranoid. There is a small chance that, for example, jayroll123 want to make a different screen that behave exactly like say screen but do not include that piece of code, and activate that screen right after an actual say screen was removed not because the user clicked it, but because it was removed through a timer that was not on the say screen, but was added and activated before that say screen but remain there when the say screen is displayed. So really, one in a million chance, but I would rather close that loophole than worry about it later. It's more of a paranoid thing really. I am not good of coding and I don't know much about computer, so I am super careful so that I won't make an error or trip into a potential unusual behavior from the Ren'Py engine, because if I get one, it's very hard for me to figure out where it occur. You might notice that I have a bunch of bracket in the code for calculate_time, or a bunch of pointless return statement, most of which are probably redundant. But I would rather have it there so that I would not have to worry later whether a function return or not, or whether the calculation is made in correct order, if and when a bug occur.

User avatar
trooper6
Lemma-Class Veteran
Posts: 3712
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: You can only click when the dialogue was done. How?

#12 Post by trooper6 »

@elmiwisa

Thanks for the info! Although my code is working perfectly at the moment, I always want to try and make it better. When I get some time (hopefully soon!) I'm going to play around with what you've posted here and see if I can make another version of that function that not only does the say_allow_dismiss but also trips my various flags and enables my Interrupt button. Now...I don't know if that function will be the most efficient in the end since I have sort of complex callbacks dealing with who can be clicked through when, and who can't...but I'll look into it!
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

Post Reply

Who is online

Users browsing this forum: No registered users