New to Renpy development; basic questions about how to set up array of imagebuttons for puzzle minigame

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
enaielei
Regular
Posts: 114
Joined: Fri Sep 17, 2021 2:09 am
Tumblr: enaielei
Deviantart: enaielei
Github: enaielei
Skype: enaielei
Soundcloud: enaielei
itch: enaielei
Discord: enaielei#7487
Contact:

Re: New to Renpy development; basic questions about how to set up array of imagebuttons for puzzle minigame

#16 Post by enaielei » Tue Aug 09, 2022 1:57 pm

If what you mean is that the passing result can be either...

Code: Select all

([ON, ON, ON], [OFF, OFF, ON], [OFF, ON, ON])
or...

Code: Select all

([ON, ON, ON], [X, X, ON], [X, ON, ON])
or...

Code: Select all

([ON, ON, ON], [X, OFF, ON], [OFF, ON, ON])
and etc...

Then its probably much better to create helper functions to do the comparison.

Code: Select all

init python:
  def is_matrix_equal(m1, m2, comparer=None):
    """
    @param m1: A matrix.

    @param m2: Another matrix.

    @param comparer: A function that takes argument c1 containing the m1 cell
    and argument c2 containing the m2 cell. The function should return a boolean
    value. Leaving the comparer as None means the usual comparison (==).
    """

    rv = True
    if callable(comparer):
      if len(m1) != len(m2): rv = False
      else:
        for i1, r1 in enumerate(m1):
          r2 = m2[i1]
          if len(r1) != len(r2): rv = False
          else:
            for i2, c1 in enumerate(r1):
              c2 = r2[i2]
              rv = comparer(c1, c2)
              if not rv: break
          
          if not rv: break
    else: rv = m1 == m2

    return rv

  # the custom comparer that caters what you're looking for.
  def comparer(c1, c2):
    return (c1 != ON and c2 != ON) or (c1 == c2)
Then use it when comparing for equality.

Code: Select all

# The game starts here.
label start:
  call screen minigame(3, 3)
  $ res = _return # assign the result

  # call the function then pass the resulting matrix and another matrix you wish
  # to compare it with, then lastly the comparer function that you made.
  if is_matrix_equal(res, ([ON, ON, ON], [OFF, OFF, ON], [OFF, ON, ON]), comparer):
    "Do something"

  "Something"
This is just my take, but I feel like there's much easier way to do it.
I feel like using enums and flags would do the trick also but idk.

Tessa
Newbie
Posts: 16
Joined: Mon Aug 08, 2022 8:18 pm
Contact:

Re: New to Renpy development; basic questions about how to set up array of imagebuttons for puzzle minigame

#17 Post by Tessa » Tue Aug 09, 2022 3:16 pm

Working like a charm!

Styling has worked quite well too, very pleased with the result!

Another relatively minor question: Currently, the Get Results button leaves the minigame screen to check the result. If the result is incorrect, the only recourse is to jump back to the screen to try again, but the previous attempt is wiped clean and the player has to start over. Is there a way to check the answer within the minigame screen so that: (1) clicking Get Results checks the matrix, shows an "Incorrect" image if wrong but allows continued attempts without starting over; shows "Correct" image and jumps to next scene if correct, (2) the player can choose to skip the puzzle via a separate "Skip" button, which jumps to the next scene without checking the answer.

Tessa
Newbie
Posts: 16
Joined: Mon Aug 08, 2022 8:18 pm
Contact:

Re: New to Renpy development; basic questions about how to set up array of imagebuttons for puzzle minigame

#18 Post by Tessa » Tue Aug 09, 2022 6:18 pm

So I figured out how to implement a skip, but not so much figuring out how to check the answer within the screen to avoid restarting if it's wrong. What would you suggest?

User avatar
enaielei
Regular
Posts: 114
Joined: Fri Sep 17, 2021 2:09 am
Tumblr: enaielei
Deviantart: enaielei
Github: enaielei
Skype: enaielei
Soundcloud: enaielei
itch: enaielei
Discord: enaielei#7487
Contact:

Re: New to Renpy development; basic questions about how to set up array of imagebuttons for puzzle minigame

#19 Post by enaielei » Tue Aug 09, 2022 8:09 pm

Previously, I said that Return() action intentionally ends the called screen. I also included a link before for actions beside Return.
Looking at that link as a reference, you can use SetScreenVariable() variable instead to store the current check and make conditions inside your screen to dynamically show a text or other displayables depending on the stored value in the variable.

Code: Select all

screen minigame(xcount, ycount, cmatrix): # add another parameter, which contains the correct matrix answer
  default correct = None
  ...
  vbox:
    ...
    textbutton "Get Results":
      action SetScreenVariable("correct", is_matrix_equal(matrix, cmatrix, comparer))

    if correct is None: # not checked yet.
      text "Press Get Results to check"
    else:
      if correct: # if correct then show a text then return after 2 seconds
        text "Correct!"
        timer 2.0 action Return()
      else:
        text "Wrong!"
        
label start:
  call screen minigame(3, 3, ([ON, ON, ON], [OFF, OFF, ON], [OFF, ON, ON]))

Tessa
Newbie
Posts: 16
Joined: Mon Aug 08, 2022 8:18 pm
Contact:

Re: New to Renpy development; basic questions about how to set up array of imagebuttons for puzzle minigame

#20 Post by Tessa » Tue Aug 09, 2022 8:49 pm

It works great once, but something odd happens: If you enter in the wrong answer, the button greys out and can't be interacted with until the correct answer is entered in. This means the player can't ever check the answer again manually until they have it correct. Technically this doesn't break the puzzle since it doesn't necessarily allow brute-forcing the puzzle (it's no different than the player manually pressing "Get Results" after each move), but it's not as nice from a UX perspective.

Is there a way to reset the button after every "Wrong!" result?

Edit: Actually, there seems to be an error after a correct input as well. After the 2-second wait: (had error code here)
Edit2: Nevermind, it's because the block that checked the answer previously wasn't commented out.

User avatar
enaielei
Regular
Posts: 114
Joined: Fri Sep 17, 2021 2:09 am
Tumblr: enaielei
Deviantart: enaielei
Github: enaielei
Skype: enaielei
Soundcloud: enaielei
itch: enaielei
Discord: enaielei#7487
Contact:

Re: New to Renpy development; basic questions about how to set up array of imagebuttons for puzzle minigame

#21 Post by enaielei » Tue Aug 09, 2022 8:59 pm

Just specify the selected property for the button.

Code: Select all

textbutton "Get Results":
  selected False

Tessa
Newbie
Posts: 16
Joined: Mon Aug 08, 2022 8:18 pm
Contact:

Re: New to Renpy development; basic questions about how to set up array of imagebuttons for puzzle minigame

#22 Post by Tessa » Tue Aug 09, 2022 9:40 pm

Beautiful.

For the "Wrong!" text, is there a way to add a time delay and have the text disappear? E.g. "Wrong!" appears and disappears after 3 seconds.

Tessa
Newbie
Posts: 16
Joined: Mon Aug 08, 2022 8:18 pm
Contact:

Re: New to Renpy development; basic questions about how to set up array of imagebuttons for puzzle minigame

#23 Post by Tessa » Wed Aug 10, 2022 8:40 pm

Unrelated question. I have the game elements mostly set up and just need to polish it, so I'm looking at other areas of the VN that I still need set up. The last main area I haven't implemented is a journal screen to keep track of progress. I want this to be accessible in any scene in which I include a button to access it. How do I implement a button in a scene that doesnt disable advancing the scene? E.g. I know I can put the imagebutton in a screen, and call that screen, but I need to return from the screen before I can advance the story. But I don't want this, I want to have an optional screen-call to the journal via a button thats in the scene. Renpy doesn't seem to like having imagebuttons directly in the script, so whats the method here?

Post Reply

Who is online

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