Implementing a functional keypad [SOLVED]

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.
Message
Author
User avatar
ileikturtles
Regular
Posts: 32
Joined: Sun Nov 23, 2014 7:54 pm
Projects: Adventures of Scottie
Organization: StudioFondue
Tumblr: ileikturtles
Contact:

Implementing a functional keypad [SOLVED]

#1 Post by ileikturtles »

EDIT: This has been solved thanks to the kind assistance of xela! The code accepts 4 digits by way of imagebuttons, and then checks them against a pre set combination (or a randomized one), hooray! Functional keypads for everyone!
To have an imagemapped keypad which then checks your input and gives a 2nd try if you fail:

Code: Select all

screen key_pad:
    imagemap:
        ground "keypad.png"
        hover "keyHover.png"
        
        hotspot (765, 635, 100, 100) action Return(1)
        hotspot (940, 635, 100, 100) action Return(2)
        hotspot (1120, 635, 100, 100) action Return(3)
        hotspot (765, 465, 100, 100) action Return(4)
        hotspot (940, 465, 100, 100) action Return(5)
        hotspot (1120, 465, 100, 100) action Return(6)
        hotspot (765, 300, 100, 100) action Return(7)
        hotspot (940, 300, 100, 100) action Return(8)
        hotspot (1120, 300, 100, 100) action Return(9)
        hotspot (800, 825, 380, 83) action Return(0)
        
label start:
    
    $ keys = []
    $ counter = 0
    show screen key_pad
    jump crack_the_code
    
label crack_the_code:
    $ counter += 1
    python:
        while len(keys) < 4:
            $ result = ui.interact()
            if isinstance(result, int):
                $ keys.append(result)
    if keys == [2, 5, 1, 4]:
        hide screen key_pad
        play sound "carkeyturn.ogg"
        jump success
    else:
        $ keys = []
        if counter == 2:
            hide screen key_pad
            jump failed
        else:    
            "Try again..."
            jump crack_the_code
            
label failed:
    "You're a shitty code cracker..."
    return
    
label success:
    "Well done, you've cracked the code!"
    return
To have your game randomize the code:
xela wrote:For random, we generate a list of 4 integers in range of 0 - 9:

Code: Select all

$ our_code = renpy.random.sample(range(10), 4)
*Note that you can change the four to anything (determines the length of code), it should work with any number.

In order to display the code:

Code: Select all

$ our_code_string = ", ".join(str(i) for i in our_code)

"Our code is: [our_code_string]"
To check if the code is correct:

Code: Select all

    while len(keys) < 4:
should become:

Code: Select all

    while len(keys) < len(our_code):
and

Code: Select all

    if keys == [2, 5, 1, 4]:
should be:

Code: Select all

    if keys == our_code:

Original post
PRE-TL;DR
Basically my question is if someone out there knows a of functioning version of "hotspot (1120, 635, 100, 100) clicked [$ keyAttempt1.append("1"), $ inputNumbers1 += 1]" I can implement.
As far as I can tell the instruction you give after the brackets for the hotspot is called an 'action'(?) so basically I'm wondering if there are any actions out there which will tell the hotspot to keyAttempt1.append and then add 1 to the input digit counter.

LONG WINDED EXPLANATION FORTHCOMING:
Hi, it's my first time posting here for my first game, so I'm not used to the specific keywords and stuff that renpy uses. I've been searching all over but my deadline's in less than a week now and I need help sharpish :<

So my game is a heist sort of thing, and I'm trying to put in a functional keypad that will either give you access to what you're going to steal if you successfully input the 4-digit code, or else give you another attempt and then sound an alarm if you fail (twice).

Okay so I got my sample keypad imagemap to work perfectly fine (I don't want to use a normal text menu in the final game, because it's set in the 50's and I wanted an old timey look!).

I also got the keycode input to work in a separate script file (temporarily using a text menu). For the code input, I have $ keyAttempt1 = [] to keep track of the player's choices, and a While statement counting till 4 digits have been input, which then triggers the jump to check if the 4 numbers are correct and in the correct order.

My problem is that when I tried to combine the imagemap code, and the code for the input, it's not working :v

Here's the entire keypad code (I just rewrote it all at 1:30 am so excuse any inconsistencies):

Code: Select all

screen keyPad:
    imagemap:
        ground "keypad.png"
        hover "keyHover.png"
        
        hotspot (1120, 635, 100, 100) clicked [$ keyAttempt1.append("1"), $ inputNumbers1 += 1]
        hotspot (940, 635, 100, 100) clicked [$ keyAttempt1.append("2"), $ inputNumbers1 += 1]
        hotspot (765, 635, 100, 100) clicked [$ keyAttempt1.append("3"), $ inputNumbers1 += 1]
        hotspot (1120, 465, 100, 100) clicked [$ keyAttempt1.append("4"), $ inputNumbers1 += 1]
        hotspot (940, 465, 100, 100) clicked [$ keyAttempt1.append("5"), $ inputNumbers1 += 1]
        hotspot (765, 465, 100, 100) clicked [$ keyAttempt1.append("6"), $ inputNumbers1 += 1]
        hotspot (1120, 300, 100, 100) clicked [$ keyAttempt1.append("7"), $ inputNumbers1 += 1]
        hotspot (940, 300, 100, 100) clicked [$ keyAttempt1.append("8"), $ inputNumbers1 += 1]
        hotspot (765, 300, 100, 100) clicked [$ keyAttempt1.append("9"), $ inputNumbers1 += 1]
        hotspot (800, 825, 380, 83) clicked [$ keyAttempt1.append("0"), $ inputNumbers1 += 1]

screen keyPad2:
    imagemap:
        ground "keypad.png"
        hover "keyHover.png"
        
        hotspot (1120, 635, 100, 100) clicked [$ keyAttempt2.append("1"), $ inputNumbers2 += 1]
        hotspot (940, 635, 100, 100) clicked [$ keyAttempt2.append("2"), $ inputNumbers2 += 1]
        hotspot (765, 635, 100, 100) clicked [$ keyAttempt2.append("3"), $ inputNumbers2 += 1]
        hotspot (1120, 465, 100, 100) clicked [$ keyAttempt2.append("4"), $ inputNumbers2 += 1]
        hotspot (940, 465, 100, 100) clicked [$ keyAttempt2.append("5"), $ inputNumbers2 += 1]
        hotspot (765, 465, 100, 100) clicked [$ keyAttempt2.append("6"), $ inputNumbers2 += 1]
        hotspot (1120, 300, 100, 100) clicked [$ keyAttempt2.append("7"), $ inputNumbers2 += 1]
        hotspot (940, 300, 100, 100) clicked [$ keyAttempt2.append("8"), $ inputNumbers2 += 1]
        hotspot (765, 300, 100, 100) clicked [$ keyAttempt2.append("9"), $ inputNumbers2 += 1]
        hotspot (800, 825, 380, 83) clicked [$ keyAttempt2.append("0"), $ inputNumbers2 += 1]  

label start:
    
    $ keyAttempt1 = []
    $ keyAttempt2 = []
    $ inputNumbers1 = 0
    $ inputNumbers2 = 0
    
label attempt1:
    
    while inputNumbers1 < 4:
        call screen keyPad
    jump checkCode1
    
label checkCode1:
    if ["2", "5", "1", "4"] in keyAttempt1:
        jump codeSuccessful
    
    else:
        "One more try"
        jump attempt2

label attempt2:
    
    while inputNumbers2 < 4:
        call screen keyPad2
    jump checkCode2

label checkCode2:
    if ["2", "5", "1", "4"] in keyAttempt2:
        jump codeSuccessful
    
    else:
        jump codeFail
Okay, I guess my problem is with the "clicked [$ keyAttempt1.append("1"), $ inputNumbers1 += 1]" bit, because it's returning the following error:

Code: Select all

I'm sorry, but an uncaught exception occurred.

After initialization, but before game start.
  File "game/script.rpy", line 17, in prepare
    screen keyPad2:
  File "game/script.rpy", line 17, in prepare
    screen keyPad2:
  File "game/script.rpy", line 18, in prepare
    imagemap:
  File "game/script.rpy", line 18, in prepare
    imagemap:
  File "game/script.rpy", line 22, in prepare
    hotspot (1120, 635, 100, 100) clicked [$ keyAttempt2.append("1"), $ inputNumbers2 += 1]
  File "game/script.rpy", line 22, in prepare
    hotspot (1120, 635, 100, 100) clicked [$ keyAttempt2.append("1"), $ inputNumbers2 += 1]
SyntaxError: invalid syntax (game/script.rpy, line 22)

-- Full Traceback ------------------------------------------------------------

Full traceback:
  File "C:\Users\User\Pictures\Photoshop\Projects\1. Game Fondue\Ren'Py\renpy\bootstrap.py", line 289, in bootstrap
    renpy.main.main()
  File "C:\Users\User\Pictures\Photoshop\Projects\1. Game Fondue\Ren'Py\renpy\main.py", line 311, in main
    renpy.display.screen.prepare_screens()
  File "C:\Users\User\Pictures\Photoshop\Projects\1. Game Fondue\Ren'Py\renpy\display\screen.py", line 676, in prepare_screens
    s.ast.prepare()
  File "game/script.rpy", line 17, in prepare
    screen keyPad2:
  File "game/script.rpy", line 17, in prepare
    screen keyPad2:
  File "game/script.rpy", line 18, in prepare
    imagemap:
  File "game/script.rpy", line 18, in prepare
    imagemap:
  File "game/script.rpy", line 22, in prepare
    hotspot (1120, 635, 100, 100) clicked [$ keyAttempt2.append("1"), $ inputNumbers2 += 1]
  File "game/script.rpy", line 22, in prepare
    hotspot (1120, 635, 100, 100) clicked [$ keyAttempt2.append("1"), $ inputNumbers2 += 1]
  File "C:\Users\User\Pictures\Photoshop\Projects\1. Game Fondue\Ren'Py\renpy\python.py", line 477, in py_compile
    raise e
SyntaxError: invalid syntax (game/script.rpy, line 22)

Windows-7-6.1.7601-SP1
Ren'Py 6.18.3.761
keypad 0.0
I'm throwing the full traceback in cos idk what any of it means so i don't know what's important xD

I found a way around this by adding jumps for each hotspot which then add the keyAttempt1.append and inputNumbers1, before jumping back to the while statement, but I ended up with 20 jumps and it's not pretty. I'd like to implement something a bit more elegant if possible :/

TL;DR
Basically my question is if someone out there knows a of functioning version of "hotspot (1120, 635, 100, 100) clicked [$ keyAttempt1.append("1"), $ inputNumbers1 += 1]" I can implement.
As far as I can tell the instruction you give after the brackets for the hotspot is called an 'action'(?) so basically I'm wondering if there are any actions out there which will tell the hotspot to keyAttempt1.append and then add 1 to the input digit counter.

THANKS SO MUCH! XXXXXX
Last edited by ileikturtles on Sat Dec 06, 2014 11:48 am, edited 3 times in total.

User avatar
akemicchi
Veteran
Posts: 465
Joined: Mon Dec 31, 2007 11:22 pm
Projects: Magicians of Delphine, Panaderia: Ensaimada, SweetTooth!, XOXO Droplets
Deviantart: littlebabyshoes
Contact:

Re: HELP! Functional keypad: To use imagemap + .append()?

#2 Post by akemicchi »

You can't do that... xD If you want to change variables, you'll have to use the screen actions like SetVariable. You can't change variables like you normally would in Ren'Py while working on screens.

There isn't an Action that you can use to append things, so you'll have to make your own class and use that.

Code: Select all

class NumberInput(store.object): # I think you can change this to Action but idk
    def __init__(self, number):
        self.number = number
    def __call__(self):
        global keyAttempt1
        global inputNumbers1
        keyAttempt1.append(self.number)
        inputNumbers1 += 1
        renpy.restart_interaction()
And then you'll just need to use it like:

Code: Select all

hotspot (1120, 635, 100, 100) clicked [NumberInput("1"), Return()]
Last edited by akemicchi on Mon Nov 24, 2014 2:09 am, edited 1 time in total.

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: HELP! Functional keypad: To use imagemap + .append()?

#3 Post by xela »

Code: Select all

clicked [$ keyAttempt2.append("1"), $ inputNumbers2 += 1]
You need to use a custom action or a Function to append and SetVariable to inputNumbers2. action statement instead of clicked would not hurt either...

Edit (In case I wasn't clear):

Code: Select all

hotspot (1120, 635, 100, 100) clicked [$ keyAttempt1.append("1"), $ inputNumbers1 += 1]
should be:

Code: Select all

hotspot (1120, 635, 100, 100) action [Function(keyAttempt1.append, "1"), SetVariable("inputNumbers1",  inputNumbers1 + 1)]
Last edited by xela on Mon Nov 24, 2014 8:44 am, edited 1 time in total.
Like what we're doing? Support us at:
Image

User avatar
ileikturtles
Regular
Posts: 32
Joined: Sun Nov 23, 2014 7:54 pm
Projects: Adventures of Scottie
Organization: StudioFondue
Tumblr: ileikturtles
Contact:

Re: HELP! Functional keypad: To use imagemap + .append()?

#4 Post by ileikturtles »

akemicchi wrote:You can't do that... xD If you want to change variables, you'll have to use the screen actions like SetVariable. You can't change variables like you normally would in Ren'Py while working on screens.
Ah, oops! I have zero experience in python, or programming at all really, so I don't really know what you can/'t do :c Thanks for talking me through it though!
akemicchi wrote:There isn't an Action that you can use to append things, so you'll have to make your own class and use that.

Code: Select all

class NumberInput(store.object): # I think you can change this to Action but idk
    def __init__(self, number):
        self.number = number
    def __call__(self):
        global keyAttempt1
        global inputNumbers1
        keyAttempt1.append(self.number)
        inputNumbers1 += 1
        renpy.restart_interaction()
Okay so I have no idea what any of this means so I tried to slap it into my script, and it's returning the following error now:

Code: Select all

I'm sorry, but errors were detected in your script. Please correct the
errors listed below, and try again.

File "game/script.rpy", line 1: expected statement.
    class NumberInput(store.object): 
                     ^
Ren'Py Version: Ren'Py 6.18.3.761

Ah I hate being so helpless but this stuff really goes over my head v__v

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: HELP! Functional keypad: To use imagemap + .append()?

#5 Post by xela »

akemicchi wrote:...
He didn't give you the best advice, that class at the very least should have inherited from Action (it could work with inheritance from object (or with None at all) but it will lack some methods required for buttons/hotspots to function in accordance to documentation).

Try this:

Edit (In case I wasn't clear):

Code: Select all

hotspot (1120, 635, 100, 100) clicked [$ keyAttempt1.append("1"), $ inputNumbers1 += 1]
should be:

Code: Select all

hotspot (1120, 635, 100, 100) action [Function(keyAttempt1.append, "1"), SetVariable("inputNumbers1",  inputNumbers1 + 1)]
Like what we're doing? Support us at:
Image

User avatar
ileikturtles
Regular
Posts: 32
Joined: Sun Nov 23, 2014 7:54 pm
Projects: Adventures of Scottie
Organization: StudioFondue
Tumblr: ileikturtles
Contact:

Re: HELP! Functional keypad: To use imagemap + .append()?

#6 Post by ileikturtles »

xela wrote:
akemicchi wrote:...
He didn't give you the best advice, that class at the very least should have inherited from Action (it could work with inheritance from object (or with None at all) but it will lack some methods required for buttons/hotspots to function in accordance to documentation).

Try this:

Edit (In case I wasn't clear):

Code: Select all

hotspot (1120, 635, 100, 100) clicked [$ keyAttempt1.append("1"), $ inputNumbers1 += 1]
should be:

Code: Select all

hotspot (1120, 635, 100, 100) action [Function(keyAttempt1.append, "1"), SetVariable("inputNumbers1",  inputNumbers1 + 1)]
Man I really wanted this to work xD It's not returning any errors, but nothing's happening either. The temporary keypad imagemap thing I set up is working fine with the highlights and everything, but I can go on clicking buttons forever and nothing happens!

I tried to add something that would show the contents of "$ keyAttempt1 = []", and I also tried to add a sound to see if the loop was working, so that's what that nonsense in the script is supposed to be doing. I'm uploading the file in case you'd be so kind as to take a look?
Attachments
keypad.rar
(4.72 MiB) Downloaded 72 times

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: HELP! Functional keypad: To use imagemap + .append()?

#7 Post by xela »

Your code is a bit off... give me 10 mins.

Try this (there are other ways but I always do it this way):

Code: Select all

screen key_pad:
    imagemap:
        ground "keypad.png"
        hover "keyHover.png"
        
        hotspot (765, 635, 100, 100) action Return(1)
        hotspot (940, 635, 100, 100) action Return(2)
        hotspot (1120, 635, 100, 100) action Return(3)
        hotspot (765, 465, 100, 100) action Return(4)
        hotspot (940, 465, 100, 100) action Return(5)
        hotspot (1120, 465, 100, 100) action Return(6)
        hotspot (765, 300, 100, 100) action Return(7)
        hotspot (940, 300, 100, 100) action Return(8)
        hotspot (1120, 300, 100, 100) action Return(9)
        hotspot (800, 825, 380, 83) action Return(0)
        
label start:
    
    $ keys = []
    $ counter = 0
    show screen key_pad
    jump crack_the_code
    
label crack_the_code:
    $ counter += 1
    python:
        while len(keys) < 4:
            result = ui.interact()
            if isinstance(result, int):
                keys.append(result)
    if keys == [2, 5, 1, 4]:
        hide screen key_pad
        play sound "carkeyturn.ogg"
        jump success
    else:
        $ keys = []
        if counter == 2:
            hide screen key_pad
            jump failed
        else:    
            "Try again..."
            jump crack_the_code
            
label failed:
    "You're a shitty code cracker..."
    return
    
label success:
    "Well done, you've cracked the code!"
    return
Like what we're doing? Support us at:
Image

User avatar
ileikturtles
Regular
Posts: 32
Joined: Sun Nov 23, 2014 7:54 pm
Projects: Adventures of Scottie
Organization: StudioFondue
Tumblr: ileikturtles
Contact:

Re: HELP! Functional keypad: To use imagemap + .append()?

#8 Post by ileikturtles »

xela wrote: Try this (there are other ways but I always do it this way):
AAAAAAAAAAAAAAAAAAAAAAAAA YOU'RE THE BEST! Thanks so much xxx

For a second I thought it was accepting 5 digits in the 2nd attempt because of the "Try again..." and click to continue, but I'll change that in the game to make it more clear. But it seems to be working perfectly fine! I can't put into words how grateful I am (づ ̄ ³ ̄)づ

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: HELP! Functional keypad: To use imagemap + .append()?

#9 Post by xela »

You're welcome :)
Like what we're doing? Support us at:
Image

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: Implementing a functional keypad [SOLVED]

#10 Post by xela »

Just a thought:

Code: Select all

    python:
        while len(keys) < 4:
            result = ui.interact()
            if isinstance(result, int):
                keys.append(result)
while this works, it may not save properly or allow proper rollback (in my game I have workarounds/no rollback).

So for a proper Ren'Py game this makes more sense:

Code: Select all

    while len(keys) < 4:
        $ result = ui.interact()
        if isinstance(result, int):
            $ keys.append(result)
Moving this bit from python to Ren'Py script should allow proper rollback and saving while the code is being entered.
Like what we're doing? Support us at:
Image

User avatar
ileikturtles
Regular
Posts: 32
Joined: Sun Nov 23, 2014 7:54 pm
Projects: Adventures of Scottie
Organization: StudioFondue
Tumblr: ileikturtles
Contact:

Re: Implementing a functional keypad [SOLVED]

#11 Post by ileikturtles »

xela wrote:Just a thought:

Code: Select all

    python:
        while len(keys) < 4:
            result = ui.interact()
            if isinstance(result, int):
                keys.append(result)
while this works, it may not save properly or allow proper rollback (in my game I have workarounds/no rollback).

So for a proper Ren'Py game this makes more sense:

Code: Select all

    while len(keys) < 4:
        $ result = ui.interact()
        if isinstance(result, int):
            $ keys.append(result)
Moving this bit from python to Ren'Py script should allow proper rollback and saving while the code is being entered.
AYE AYE CAP'N
(I have no idea what any of this means so I'm just going to go with it xD) xx

User avatar
shortycake
Regular
Posts: 119
Joined: Mon Jan 20, 2014 5:53 am
Completed: Night in the Cottage
Projects: The Mishka Effect, Nocturnal Affair, Lethe, Alice in Neverland, Behind the Doll's eyes[WIP]
Deviantart: shortpencil
itch: shortycake
Location: Philippines
Contact:

Re: Implementing a functional keypad [SOLVED]

#12 Post by shortycake »

Hello! Thank you [xela] for this useful code but I'm wondering if it's possible to have a random number instead of fixed number you put? for example there is a character who will give you a combination number (random number) then that number will work in the keypad/lock. a-and if yes, how to code it? ; u ;

User avatar
ileikturtles
Regular
Posts: 32
Joined: Sun Nov 23, 2014 7:54 pm
Projects: Adventures of Scottie
Organization: StudioFondue
Tumblr: ileikturtles
Contact:

Re: Implementing a functional keypad [SOLVED]

#13 Post by ileikturtles »

Yes, it would be good to know! I'm super busy with other non-fun non-game stuff and I didn't have time to look into it, but when I do I wanted the number to be generated randomly! Because the game's too easy reusing the same code, you know?

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: Implementing a functional keypad [SOLVED]

#14 Post by xela »

For random, we generate a list of 4 integers in range of 0 - 9:

Code: Select all

$ our_code = renpy.random.sample(range(10), 4)
*Note that you can change the four to anything (determines the length of code), it should work with any number.

In order to display the code:

Code: Select all

$ our_code_string = ", ".join(our_code)

"Our code is: [our_code_string]"
To check if the code is correct:

Code: Select all

    while len(keys) < 4:
should become:

Code: Select all

    while len(keys) < len(our_code):
and

Code: Select all

    if keys == [2, 5, 1, 4]:
should be:

Code: Select all

    if keys == our_code:
Like what we're doing? Support us at:
Image

User avatar
ileikturtles
Regular
Posts: 32
Joined: Sun Nov 23, 2014 7:54 pm
Projects: Adventures of Scottie
Organization: StudioFondue
Tumblr: ileikturtles
Contact:

Re: Implementing a functional keypad [SOLVED]

#15 Post by ileikturtles »

ARGH XELA YOU ARE THE BEST I CAN'T EVEN STAND IT <3

Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot], Ocelot