How to build a randomized dialogue menu with images

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
CutlassBoardgame
Regular
Posts: 27
Joined: Sun Jan 03, 2021 6:23 am
Projects: Winning Love by Daylight
Organization: Cutlass Boardgames
itch: cutlassboardgame
Contact:

How to build a randomized dialogue menu with images

#1 Post by CutlassBoardgame » Sun Jan 31, 2021 5:25 am

I'm looking to build a game where a player's menu responses instead of popping up with the text box, pop up with images, and images would be clickable buttons that progress the story. Here's the kicker, I want the images that are chosen to be randomly chosen from a list that the player can manage and collect.

Like If I reach a point in the story where I'm now the owner of a big orange cat, and I meet someone that says, hey show me your favourite cat, the big orange cat would be one of the options I can choose from (as an image) but if I had other cats they might randomly show up in the short list instead.
Image

User avatar
_ticlock_
Veteran
Posts: 391
Joined: Mon Oct 26, 2020 5:41 pm
Contact:

Re: How to build a randomized dialogue menu with images

#2 Post by _ticlock_ » Sun Jan 31, 2021 7:15 am

You can create a custom screen. Maybe also make a class to keep things organized and add more functionality later. For example:

Code: Select all

init python:
    class ChoiceOption():
        def __init__(self, name, idle_img, img_hover):
            self.name = name
            self.idle_img = idle_img
            self.img_hover = img_hover
        def random(self):
            # For example 50% chance to show this option if it is in the list
            if renpy.random() > 0.5:
                return True

default available_choice_items = []
screen img_menu():
    style_prefix "choice"
    vbox:
        for i in available_choice_items:
            if i.random():
                imagebutton:
                    idle i.img_idle
                    hover i.img_hover
                    action Return(i)
                    
label start:
    python:
        available_choice_items.append(ChoiceOption(_("orange cat"), "orange_cat_idle.png", "orange_cat_hover.png"))
        available_choice_items.append(ChoiceOption(_("white cat"), "white_cat_idle.png", "white_cat_hover.png"))
    call screen img_menu
    $ chosen = _return
    "You have chosen [chosen.name!t]
You also need to add some functionality to manage the list available_choice_items.
PS: Tag !t to enable translation for the name.

User avatar
CutlassBoardgame
Regular
Posts: 27
Joined: Sun Jan 03, 2021 6:23 am
Projects: Winning Love by Daylight
Organization: Cutlass Boardgames
itch: cutlassboardgame
Contact:

Re: How to build a randomized dialogue menu with images

#3 Post by CutlassBoardgame » Sun Jan 31, 2021 2:54 pm

Can you walk me through how each of these parts work? I'm understanding maybe 60% aha

Also, would I be able to have a screen where players can add or remove cats from a list? Think like a jukebox, where you can add stuff to a playlist or remove, and when its played it gets put on the bottom or something.
Image

User avatar
_ticlock_
Veteran
Posts: 391
Joined: Mon Oct 26, 2020 5:41 pm
Contact:

Re: How to build a randomized dialogue menu with images

#4 Post by _ticlock_ » Sun Jan 31, 2021 11:41 pm

CutlassBoardgame wrote:
Sun Jan 31, 2021 2:54 pm
Can you walk me through how each of these parts work? I'm understanding maybe 60% aha
class ChoiceOption can be used to create "objects" like Orange cat. Here, def __init__(self, name, idle_img, img_hover) is function that is responsible for "object" property assignment. For example, to create Orange cat that has name "orange cat" and uses "orange_cat_idle.png" and "orange_cat_hover.png" images for the buttons you write:

Code: Select all

ChoiceOption(_("orange cat"), "orange_cat_idle.png", "orange_cat_hover.png")
Screen img_menu is an example of the choice screen with imagebuttons like you mentioned. In this screen, we look through all objects that are stored in the list available_choice_items. Each object has 50% chance to be shown as an option (that is dictated by function random in the class ChoiceOption). You might consider rewriting this function to fit your requirement for random selection.
When the player clicks the button it returns to the label and the temporal variable _return stores the chosen object.
CutlassBoardgame wrote:
Sun Jan 31, 2021 2:54 pm
Also, would I be able to have a screen where players can add or remove cats from a list? Think like a jukebox, where you can add stuff to a playlist or remove, and when its played it gets put on the bottom or something.
No, I did not put that.
Well, lets say you created 2 objects Orange cat and White cat. Let's put these object to the list jukebox:

Code: Select all

default jukebox = []
default available_choice_items = []
label start:
    python:
        jukebox.append(ChoiceOption(_("orange cat"), "orange_cat_idle.png", "orange_cat_hover.png"))
        jukebox.append(ChoiceOption(_("white cat"), "white_cat_idle.png", "white_cat_hover.png"))
Please notice, that list available_choice_items is empty.
Let's make the screen for the player to select objects from jukebox:

Code: Select all

init python:
    def pop_append(list_to_pop, indx, list_to_append):
        list_to_append.append(list_to_pop.pop(indx))
screen manage_options():
    hbox:
        vbox:
            label _("Enabled")
            for i, item  in enumerate(available_choice_items):
                imagebutton:
                    idle item.img_idle
                    hover item.img_hover
                    action Function(pop_append, available_choice_items, i, jukebox)
        vbox:
            label _("Disabled")
            for i, item  in enumerate(jukebox):
                imagebutton:
                    idle item.img_idle
                    hover item.img_hover
                    action Function(pop_append, jukebox, i, available_choice_items)
    textbutton _("Accept") action Return()
function pop_append transfer object between lists jukebox and available_choice_items.

PS: You probably should have one default object in the screen img_menu, so you don't get to the situation when there 0 options to select from and that results in frozen screen.

User avatar
CutlassBoardgame
Regular
Posts: 27
Joined: Sun Jan 03, 2021 6:23 am
Projects: Winning Love by Daylight
Organization: Cutlass Boardgames
itch: cutlassboardgame
Contact:

Re: How to build a randomized dialogue menu with images

#5 Post by CutlassBoardgame » Mon Feb 01, 2021 1:13 am

I gave that a go and I got this error:

Code: Select all

While running game code:
  File "game/script.rpy", line 47, in script
    call screen img_menu
  File "renpy/common/000statements.rpy", line 531, in execute_call_screen
    store._return = renpy.call_screen(name, *args, **kwargs)
  File "game/script.rpy", line 22, in execute
    screen img_menu():
  File "game/script.rpy", line 22, in execute
    screen img_menu():
  File "game/script.rpy", line 24, in execute
    vbox:
  File "game/script.rpy", line 25, in execute
    for i in available_choice_items:
  File "game/script.rpy", line 26, in execute
    if i.random():
  File "game/script.rpy", line 18, in random
    if renpy.random() > 0.16:
TypeError: 'DetRandom' object is not callable

my script looks like this:

Code: Select all

init python:
    class ChoiceOption():
        def __init__(self, name, idle_img, img_hover):
            self.name = name
            self.idle_img = idle_img
            self.img_hover = img_hover
        def random(self):
            # For example 50% chance to show this option if it is in the list
            if renpy.random() > 0.16:
                return True

default available_choice_items = []
screen img_menu():
    style_prefix "choice"
    vbox:
        for i in available_choice_items:
            if i.random():
                imagebutton:
                    idle i.img_idle
                    hover i.img_hover
                    action Return(i)

default jukebox = []

label start:
"Placeholder Dialogue"
python:
  available_choice_items.append(ChoiceOption(_("Two of Diamonds"), "d2.png", "d2.png"))
  available_choice_items.append(ChoiceOption(_("Three of Diamonds"), "d3.png", "d3.png"))
  available_choice_items.append(ChoiceOption(_("Four of Diamonds"), "d4.png", "d4.png"))
call screen img_menu
$ chosen = _return
"You have chosen [chosen.name!t]"

"Placeholder Dialogue"
and I made a separate .rpy for the jukebox, which I managed to successfully link from the main screen, which looks like this:

Code: Select all

init python:
    def pop_append(list_to_pop, indx, list_to_append):
        list_to_append.append(list_to_pop.pop(indx))
screen jukebox():
 tag menu
screen manage_options():
    hbox:
        vbox:
            label _("Enabled")
            for i, item  in enumerate(available_choice_items):
                imagebutton:
                    idle item.img_idle
                    hover item.img_hover
                    action Function(pop_append, available_choice_items, i, jukebox)
        vbox:
            label _("Disabled")
            for i, item  in enumerate(jukebox):
                imagebutton:
                    idle item.img_idle
                    hover item.img_hover
                    action Function(pop_append, jukebox, i, available_choice_items)
    textbutton _("Accept") action Return()
I know I've done something wrong, I feel like there's a few bridges I'm not crossing with what you've put down for me. Sorry that I'm struggling to get this, I feel like i'm getting there. I know I haven't put anything in the default available choice items yet, I'm not sure how that's supposed to be formatted.
Image

User avatar
midgethetree
Regular
Posts: 39
Joined: Wed Dec 30, 2020 3:51 pm
Completed: Appetité Amor, The Mother of Pearls, Anise Flowers, Sinless: on Middle Ground, Back When, I'm Just Here to Change the Lights, DUFE: Masquerade
Projects: When Everyone's Watching
Github: midgethetree
itch: midge-the-tree
Discord: rainafc#3353
Contact:

Re: How to build a randomized dialogue menu with images

#6 Post by midgethetree » Mon Feb 01, 2021 1:42 am

Use renpy.random.random() instead of renpy.random() - renpy.random is an object, renpy.random.random is the function defined in the object's class that you actually want to call.

Also don't use > .16 if your intention is for the check to pass 16% of the time. Use < .16. With the 50% example it didn't really matter, but with other amounts you've got the probabilities backwards. For example, renpy.random.random() > .16 is true ~84% of the time.

User avatar
_ticlock_
Veteran
Posts: 391
Joined: Mon Oct 26, 2020 5:41 pm
Contact:

Re: How to build a randomized dialogue menu with images

#7 Post by _ticlock_ » Mon Feb 01, 2021 5:15 am

CutlassBoardgame wrote:
Mon Feb 01, 2021 1:13 am
I know I haven't put anything in the default available choice items yet, I'm not sure how that's supposed to be formatted.
One way to do that:

Code: Select all

default def_choice_option = ChoiceOption(_("Joker"), "j.png", "j.png"))
screen img_menu():
    style_prefix "choice"
    vbox:
        for i in available_choice_items:
            if i.random():
                imagebutton:
                    idle i.img_idle
                    hover i.img_hover
                    action Return(i)
        imagebutton:
            idle def_choice_option.img_idle
            hover def_choice_option.img_hover
            action Return(def_choice_option)
Basically, I add another button to the vbox.
I put the default option in another variable and not in the list. Alternatively, we can put it as the first object in the available_choice_items, but in this case we need to do some tweaks to make sure that player won't be able to remove it and it is shown 100%.

PS: midgethetree, thanks for the correction.
PS: I didn't run the code, so other mistakes are possible.

Post Reply

Who is online

Users browsing this forum: Ocelot