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
Tessa
Newbie
Posts: 16
Joined: Mon Aug 08, 2022 8:18 pm
Contact:

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

#1 Post by Tessa » Mon Aug 08, 2022 8:33 pm

Hi all!

I've been racking my brain all day trying to figure out how to do this, but I'm new to Renpy and python in general, and I really don't have a good sense of how to even search for answers and I could use some guidance.

Here's my goal:

During the VN, a minigame is triggered. This is a logic puzzle, with an array of imagebuttons that can be toggled into three states: OFF, ON, and X, each with their own idle and hover images (e.g. on is highlighted, off is dark, X is...an X). When the VN calls the minigame screen, I need the game screen to generate, say, a 6x6 matrix of square buttons that are initially in the OFF state. Then, the player can click each button to cycle it through from OFF to ON, and again from ON to X, and again from X to OFF, as much as they'd like. When the correct combination is selected (the logic puzzle itself is unimportant here), the game is won and the VN proceeds.

Here's my problem:

I have no idea what I'm doing. I tried following this tutorial initially: https://youtu.be/nvMP9g1drjM, to get the overall structure into a test game so I could divert into my own minigame structure, but as soon as I get to the point where I'm trying to generate interactive elements (buttons), it all falls apart and I can't get it to work.

So I started over in a blank project and simply tried creating a single image button that I could toggle between these three states, and I can't figure this basic problem out either. I don't really understand the syntax or structure I need to achieve it.

Code: Select all

screen GameWindow1:

    if tilecurrent_1 == 0:
        $idle_1 = "images/tile_off_idle.png"
        $hover_1 = "images/tile_off_hover.png"
    elif tilecurrent_1 == 2:
        $idle_1 = "images/tile_on_idle.png"
        $hover_1 = "images/tile_on_hover.png"
    elif tilecurrent_1 == 3:
        $idle_1 = "images/tile_mark_idle.png"
        $hover_1 = "images/tile_mark_hover.png"

    imagebutton:
        idle idle_1
        hover hover_1
        if tilecurrent_1 == 0:
            action Jump("Cell1_0")
        elif tilecurrent_1 == 1:
            action Jump("Cell1_1")
        elif tilecurrent_1 ==2:
            action Jump("Cell1_2")

    label Cell1_0:
        $tilecurrent_1 = 1
    label Cell1_1:
        $tilecurrent_1 = 2
    label Cell1_2:
        $tilecurrent_1 = 0


label start:

    $tilecurrent_1 = 0

    scene background1
    "Click to call game window."
    call screen GameWindow1

    return
What guidance I'm looking for:

Where do I begin here? Are there any good tutorials you can link me to? I've been googling all day but can't seem to wrap my head around it just yet.

Thank you.

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

#2 Post by enaielei » Mon Aug 08, 2022 9:06 pm

Here's my goal:

During the VN, a minigame is triggered. This is a logic puzzle, with an array of imagebuttons that can be toggled into three states: OFF, ON, and X, each with their own idle and hover images (e.g. on is highlighted, off is dark, X is...an X). When the VN calls the minigame screen, I need the game screen to generate, say, a 6x6 matrix of square buttons that are initially in the OFF state. Then, the player can click each button to cycle it through from OFF to ON, and again from ON to X, and again from X to OFF, as much as they'd like. When the correct combination is selected (the logic puzzle itself is unimportant here), the game is won and the VN proceeds.
Something like this?

Code: Select all

# define the constants
define OFF = 0
define ON = 1
define X = 2

screen minigame(xcount, ycount):
  # range constants
  default XRANGE = range(xcount)
  default YRANGE = range(ycount)

  default matrix = tuple([OFF for y in YRANGE] for x in XRANGE)

  vbox:
    grid ycount xcount:
      for x in XRANGE:
        for y in YRANGE:
          python:
            cell = matrix[x][y]
            # in this example, the status of each cell is shown using text, you can use the same conditional statement to determine your image.
            if cell == OFF:
              txt = "off"
            elif cell == ON:
              txt = "on"
            else:
              txt = "x"

          textbutton txt:
            # just a nested If action to determine what value to set on each click.
            action If(cell == OFF,
              SetDict(matrix[x], y, ON),
              If(cell == ON,
                SetDict(matrix[x], y, X),
                SetDict(matrix[x], y, OFF),
              )
            )

    # this is an example how to get the results, just use a Return action and pass the matrix variable
    # be noted that a Return action ends the called screen.
    textbutton "Get Results" action Return(matrix)

# The game starts here.
label start:
    call screen minigame(6, 6)
    $ res = _return # assign the result then do whatever you want with it in the next lines. below is an example.
    if res[0][0] == OFF: # checks if the first cell in the first row of the matrix is OFF.
      "Do something"

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

#3 Post by Tessa » Mon Aug 08, 2022 9:16 pm

Precisely! So how would I go about replacing the text with square images (can I set hover states using this code too)?

And how would I have the code check for the correct combination? Say for a 3x3 matrix, the "correct" combination is:
ON ON ON
OFF OFF ON
OFF ON ON

Edit: I just saw the last line, that would of course work, assuming I set up a large conditional check for all N cells. So I guess my main question now is how to use images instead of text.

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

#4 Post by Tessa » Mon Aug 08, 2022 9:33 pm

Appending my previous response, after messing with your code a bit:

More so than just the images in the cells, I'd basically need to tile over the core code here with a fancy UI/UX:

- Images with hover states for the cells - each cell is 60px by 60 px, and each of the three states has its own pair of idle/hover images
- An overlay image of the actual puzzle on top of the matrix
- The puzzle is in a frame in the center of screen

Can you point me in the right direction for this?

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

#5 Post by enaielei » Mon Aug 08, 2022 9:39 pm

For the image, since you're using imagebuttons, you may refer to this documentation
Not really a fan of imagebuttons since I use buttons for most of the time. Using buttons you can approach it like this.

Code: Select all

python:
  if cell == OFF:
    idle = "off_idle.png"
    hover = "off_hover.png"
  elif cell == ON:
    idle = "on_idle.png"
    hover = "on_hover.png"
  else:
    idle = "x_idle.png"
    hover = "x_hover.png"

  textbutton txt:
    background idle
    hover_background hover
And how would I have the code check for the correct combination? Say for a 3x3 matrix, the "correct" combination is:
ON ON ON
OFF OFF ON
OFF ON ON
If you would just compare them as a whole you can do this instead of checking each element.

Code: Select all

if res == ([ON, ON, ON], [OFF, OFF, ON], [OFF, ON, ON]):
  "Do something"
This checking corresponds to a called screen with 1x3 parameters.
When it comes to styling them, I think you can figure this out on your own by studying screens and style properties.

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

#6 Post by Tessa » Mon Aug 08, 2022 9:56 pm

When I try to substitute in your snippet of image-related code into the original code, it errors out. What am I missing? Sorry for asking what might seem like obvious questions to you :|
NameError: name 'txt' is not defined

Code: Select all

# define the constants
define OFF = 0
define ON = 1
define X = 2

screen minigame(xcount, ycount):
    # range constants
    default XRANGE = range(xcount)
    default YRANGE = range(ycount)

    default matrix = tuple([OFF for y in YRANGE] for x in XRANGE)

    vbox:
        grid ycount xcount:
          for x in XRANGE:
            for y in YRANGE:
              python:
                cell = matrix[x][y]
                # in this example, the status of each cell is shown using text, you can use the same conditional statement to determine your image.
                if cell == OFF:
                    idle = "images/tile_off_idle.png"
                    hover = "images/tile_off_hover.png"
                elif cell == ON:
                    idle = "images/tile_on_idle.png"
                    hover = "images/tile_on_hover.png"
                else:
                    idle = "images/tile_mark_idle.png"
                    hover = "images/tile_mark_hover.png"

              textbutton txt:
                # just a nested If actions to determine what value to set on each click.
                background idle
                hover_background hover
                action If(cell == OFF,
                  SetDict(matrix[x], y, ON),
                  If(cell == ON,
                    SetDict(matrix[x], y, X),
                    SetDict(matrix[x], y, OFF),
                  )
                )

        # this is an example how to get the results, just use a Return action and pass the matrix variable
        # be noted that a Return action ends the called screen.
        textbutton "Get Results" action Return(matrix)

# The game starts here.
label start:
    call screen minigame(6, 6)
    $ res = _return # assign the result
    if res[0][0] == OFF: # checks if the first cell in the first row of the matrix is OFF.
      "Do something"

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

#7 Post by enaielei » Mon Aug 08, 2022 9:58 pm

Yeah, I removed the txt variable when I excerpted from the original code.
Just define it again.

Code: Select all

python:
  if cell == OFF:
    txt = "off"
    idle = "off_idle.png"
    hover = "off_hover.png"
  elif cell == ON:
    txt = "on"
    idle = "on_idle.png"
    hover = "on_hover.png"
  else:
    txt = "x"
    idle = "x_idle.png"
    hover = "x_hover.png"

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

#8 Post by Tessa » Mon Aug 08, 2022 10:01 pm

It works! And is there a way to manually set the size of the cells in the matrix?

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

#9 Post by enaielei » Mon Aug 08, 2022 10:04 pm

Setting the size for each cell is a matter of styling and a preference of your own. So you need to learn and implement this on your own.
I already included links on where you can learn about this.

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

#10 Post by Tessa » Mon Aug 08, 2022 10:11 pm

It just clicked for me that the textbutton is driving the cell width, not the matrix itself. It was just a matter of adding xminimum 60 and yminimum 60 to the button. Thank you SO MUCH for your help!

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

#11 Post by Tessa » Tue Aug 09, 2022 2:22 am

Sorry, back again with another question. I was testing everything before on a different PC from the one I'm developing the VN on. When I tried duplicating it in a new project on this PC, there's an error I didn't get before:
NameError: global name 'YRANGE' is not defined
Any thoughts? Why would it suddenly not work?

If it matters, I'm using Renpy 7.4.11.2266 on my main PC (where it fails) and I used the latest release 8.0.1 on the PC I was testing the puzzle code on earlier.

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

#12 Post by enaielei » Tue Aug 09, 2022 2:48 am

If you have these lines in your code then you're good.

Code: Select all

screen minigame(xcount, ycount):
  # range constants
  default XRANGE = range(xcount)
  default YRANGE = range(ycount)
I'd suggest force recompiling your scripts through the launcher.

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

#13 Post by Tessa » Tue Aug 09, 2022 11:35 am

Those lines are indeed in the code, I copy/pasted the entirety of the code from before:

Code: Select all

# define the constants
define OFF = 0
define ON = 1
define X = 2

screen minigame(xcount, ycount):
    # range constants
    default XRANGE = range(xcount)
    default YRANGE = range(ycount)

    default matrix = tuple([OFF for y in YRANGE] for x in XRANGE)

    vbox:
        grid ycount xcount:
          for x in XRANGE:
            for y in YRANGE:
              python:
                cell = matrix[x][y]
                # in this example, the status of each cell is shown using text, you can use the same conditional statement to determine your image.
                if cell == OFF:
                    txt="    "
                    idle = "images/tile_off_idle.png"
                    hover = "images/tile_off_hover.png"
                elif cell == ON:
                    txt="    "
                    idle = "images/tile_on_idle.png"
                    hover = "images/tile_on_hover.png"
                else:
                    txt="    "
                    idle = "images/tile_mark_idle.png"
                    hover = "images/tile_mark_hover.png"

              textbutton txt:
                # just a nested If actions to determine what value to set on each click.
                background idle
                hover_background hover
                yminimum 60
                xminimum 60
                action If(cell == OFF,
                  SetDict(matrix[x], y, ON),
                  If(cell == ON,
                    SetDict(matrix[x], y, X),
                    SetDict(matrix[x], y, OFF),
                  )
                )

        # this is an example how to get the results, just use a Return action and pass the matrix variable
        # be noted that a Return action ends the called screen.
        textbutton "Get Results" action Return(matrix)

# The game starts here.
label start:
    call screen minigame(6, 4)
    $ res = _return # assign the result
    if res[0][0] == OFF: # checks if the first cell in the first row of the matrix is OFF.
      "Do something"
This is the complete error message:

Code: Select all

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/script.rpy", line 53, in script
    call screen minigame(6, 4)
  File "renpy/common/000statements.rpy", line 569, in execute_call_screen
    store._return = renpy.call_screen(name, *args, **kwargs)
  File "game/script.rpy", line 6, in execute
    screen minigame(xcount, ycount):
  File "game/script.rpy", line 6, in execute
    screen minigame(xcount, ycount):
  File "game/script.rpy", line 11, in execute
    default matrix = tuple([OFF for y in YRANGE] for x in XRANGE)
  File "game/script.rpy", line 11, in <module>
    default matrix = tuple([OFF for y in YRANGE] for x in XRANGE)
  File "game/script.rpy", line 11, in <genexpr>
    default matrix = tuple([OFF for y in YRANGE] for x in XRANGE)
NameError: global name 'YRANGE' is not defined

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

Full traceback:
  File "game/script.rpy", line 53, in script
    call screen minigame(6, 4)
  File "renpy/ast.py", line 2015, in execute
    self.call("execute")
  File "renpy/ast.py", line 2003, in call
    return renpy.statements.call(method, parsed, *args, **kwargs)
  File "renpy/statements.py", line 278, in call
    return method(parsed, *args, **kwargs)
  File "renpy/common/000statements.rpy", line 569, in execute_call_screen
    store._return = renpy.call_screen(name, *args, **kwargs)
  File "renpy/exports.py", line 3136, in call_screen
    rv = renpy.ui.interact(mouse="screen", type="screen", roll_forward=roll_forward)
  File "renpy/ui.py", line 298, in interact
    rv = renpy.game.interface.interact(roll_forward=roll_forward, **kwargs)
  File "renpy/display/core.py", line 3325, in interact
    repeat, rv = self.interact_core(preloads=preloads, trans_pause=trans_pause, pause=pause, pause_start=pause_start, **kwargs)
  File "renpy/display/core.py", line 3737, in interact_core
    root_widget.visit_all(lambda i : i.per_interact())
  File "renpy/display/core.py", line 568, in visit_all
    d.visit_all(callback, seen)
  File "renpy/display/core.py", line 568, in visit_all
    d.visit_all(callback, seen)
  File "renpy/display/core.py", line 568, in visit_all
    d.visit_all(callback, seen)
  File "renpy/display/screen.py", line 436, in visit_all
    callback(self)
  File "renpy/display/core.py", line 3737, in <lambda>
    root_widget.visit_all(lambda i : i.per_interact())
  File "renpy/display/screen.py", line 447, in per_interact
    self.update()
  File "renpy/display/screen.py", line 637, in update
    self.screen.function(**self.scope)
  File "game/script.rpy", line 6, in execute
    screen minigame(xcount, ycount):
  File "game/script.rpy", line 6, in execute
    screen minigame(xcount, ycount):
  File "game/script.rpy", line 11, in execute
    default matrix = tuple([OFF for y in YRANGE] for x in XRANGE)
  File "game/script.rpy", line 11, in <module>
    default matrix = tuple([OFF for y in YRANGE] for x in XRANGE)
  File "game/script.rpy", line 11, in <genexpr>
    default matrix = tuple([OFF for y in YRANGE] for x in XRANGE)
NameError: global name 'YRANGE' is not defined

Windows-10-10.0.19041
Ren'Py 7.4.11.2266
PuzzleTesting 1 1.0
Tue Aug  9 02:15:27 2022

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

#14 Post by Tessa » Tue Aug 09, 2022 11:49 am

It indeed worked again when I updated to Renpy 8.0.1 -- not sure why that's making a difference. Hopefully there are no unintended consequences of switching to it for everything else in the VN.

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

#15 Post by Tessa » Tue Aug 09, 2022 12:20 pm

Returning to the code for how it checks the answer:

Code: Select all

if res == ([ON, ON, ON], [OFF, OFF, ON], [OFF, ON, ON]):
  "Do something"
Is there a way for the code to allow both OFF or X for the above check in the OFF segments? As in, the primary check is whether the ON segments, and ONLY the ON segments, are all correct, and that OFF and be either OFF or X (and there can be a mix of OFF or X).

Post Reply

Who is online

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