[SOLVED] How can I act upon a player's Text Input without needing an 'Enter' press?

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
User avatar
Breadlump
Newbie
Posts: 6
Joined: Sun Apr 03, 2022 10:52 am
Completed: Demon Sighting
Projects: Missile Input
itch: flakstadarts
Contact:

[SOLVED] How can I act upon a player's Text Input without needing an 'Enter' press?

#1 Post by Breadlump » Sun Apr 03, 2022 11:57 am

Hi, I need help trying to change the default way text input behaves.

I am creating a typing game where words appear on the screen and the player needs to type them out as fast as they can (similar to games like 'The Typing of the Dead'). I have all the groundwork set up. In fact, the project is very playable at this stage. A word appears together with a bar timer, and using renpy.input the player can type freely. My issue is that an Enter press is required for the text input to be processed. For this game, that is an extra unnecessary input I would like to get rid of.

I would like the text input to be processed immediately once it matches the word presented to the player, without the need for an Enter press or Confirm button.

Here is a simplified version of how I currently have things set up:

Code: Select all

label generate_word:
    $ lvl1_word = renpy.random.choice(lvl1) 		# active_word is what the player needs to type at any given time. These are selected randomly from a list
    $ active_word = lvl1_word
    jump typing

label typing:
	$ playertype = renpy.input("[active_word]") 
	if case_sensitive == False: 			# a 'hardcore mode' can be enabled which enables case_sensitivity and accurate punctuation (latter not included for simplicity)
		$ active_word = active_word.lower()
		$ playertype = playertype.lower()
	jump resolve

label resolve:
	if playertype == active_word:			# sometimes there will be multiple words on screen at once, other times the player can type 'powerup' words using different variables than 'active_word' (not included for simplicity).
		$ points += 20				# basically, whatever the solution is to my problem, it also needs to accommodate multiple different 'correct' words.
		$ combo += 1
		$ enemy_hp -= 10
		if enemy_hp <= 0:
			jump enemy_dead
		else:
			jump generate_word
			
In addition to this, a screen with a timer is shown for each word, where some variables are affected if it runs out. The timer is refreshed each time a correct input is entered. Probably not super relevant to my issue but I thought I'd mention it anyway.

People have recommended that I subclass InputValue, and use VariableInputValue in some way. Unfortunately, while I have worked with Ren'Py for a few years, there are some aspects of coding and syntax I know almost nothing about. I'm not sure how to create a useful subclass, or exactly how to use it in conjunction with the rest of the script. Similarly, I don't know how exactly I can use VariableInputValue to accomplish my goal. Bottom line is; I may need a thorough explanation of what needs to be done so I can understand the what, how and why.

I've asked around in the Discord, and while I super appreciate the help, I find myself needing a proper thread to figure out all the little details that are involved in this issue and don't want to spam :P
Last edited by Breadlump on Tue Apr 05, 2022 10:27 am, edited 1 time in total.

User avatar
plastiekk
Regular
Posts: 40
Joined: Wed Sep 29, 2021 4:08 am
Discord: plastiekk#3072
Contact:

Re: How can I act upon a player's Text Input without needing an 'Enter' press?

#2 Post by plastiekk » Tue Apr 05, 2022 6:57 am

Counter question: How should an input work without the Enter key? After all, you would then have to monitor the keyboard and when the predefined word size is reached, it has to be compared with the word to be searched for. Following this logic, a player could type randomly on the keyboard and, with luck, find the right word.

What you could do is to check a given key input.
Does the letter in the searched word match?
Yes - next try
No - try -1
I hope this makes sense.
Why on earth did I put the bread in the fridge?

User avatar
Ocelot
Eileen-Class Veteran
Posts: 1883
Joined: Tue Aug 23, 2016 10:35 am
Github: MiiNiPaa
Discord: MiiNiPaa#4384
Contact:

Re: How can I act upon a player's Text Input without needing an 'Enter' press?

#3 Post by Ocelot » Tue Apr 05, 2022 9:18 am

An example of what you might find useful:

Code: Select all

init python:
    class ListeningInputValue(InputValue):
        def __init__(self, default = '', actions={}):
            self.default = True
            self.value = default
            self.actions = actions

        def get_text(self):
            return self.value

        def set_text(self, str):
            self.value = str
            if self.is_key(str):
                self.value = ''
                self.process(str)

        def enter(self):
            raise renpy.IgnoreEvent()

        def is_key(self, str):
            return str in self.actions

        def process(self, key):
            data = self.actions.get(key)
            if data[1]:
                del self.actions[key]
            renpy.run(data[0])

default v1 = 1
# LIV takes map 'expected string' to tuple (Action, one-time)
# expceted string is a string you want to match
# Action is a screen action / list of actions
# one-time is boolean value, True indicates that mapping should be removed after executing
default console_input = ListeningInputValue('text', {
    '111': (Jump('l1'), True),
    '222': (Jump('l2'), True),
    '333': (Jump('l3'), True),
    '123': (ToggleVariable("v1", 1, 0), False),
})


screen inp():
    vbox:
        input value console_input
        text "[v1]"

label start:
    show screen inp
    $ renpy.pause(hard=True)
    return

label l1:
    '1'
    $ renpy.pause(hard=True)
    return

label l2:
    '2'
    $ renpy.pause(hard=True)
    return

label l3:
    '3'
    $ renpy.pause(hard=True)
    return
< < insert Rick Cook quote here > >

User avatar
Breadlump
Newbie
Posts: 6
Joined: Sun Apr 03, 2022 10:52 am
Completed: Demon Sighting
Projects: Missile Input
itch: flakstadarts
Contact:

Re: How can I act upon a player's Text Input without needing an 'Enter' press?

#4 Post by Breadlump » Tue Apr 05, 2022 10:27 am

Thank your for your input guys. I have since found a solution that so far works well. By searching around I found a bit of code where someone else wanted to monitor keypresses in a similar way. This helped me get a better understanding of what I needed to to.

Code: Select all

init -1509 python:

    @renpy.pure
    class TypingVariableInputValue(VariableInputValue):
            
        def set_text(self, playertype):
            
            if playertype == active_word:
                renpy.jump("type_active_word")
                    
            globals()[self.variable] = playertype
            renpy.restart_interaction()
            
            
screen typing:    # show this screen instead of using $ renpy.input()
    input:
        value TypingVariableInputValue("playertype")

Post Reply

Who is online

Users browsing this forum: Google [Bot]