Page 1 of 1
Multiple conditional statements in an imagebutton
Posted: Fri Nov 12, 2021 6:15 pm
by account183
I have three objects (imagebuttons) on screen. I want the user to click all three imagebuttons before it goes to the next screen. The order doesn't matter, but it can't move on until all three are clicked.
I'm really struggling with coding the logic on this. My initial thought was to assign each button a True/False variable, and then embed an "if" statement and an "and" statement within each imagebutton. So, for instance, if imagebuttons #1 and #2 are both clicked, then clicking #3 would go to the next screen. Whereas, if imagbuttons #2 and #3 are clicked first, then imagebutton #1 would go to the next screen. I can't get the code to work though.
As a workaround, I was thinking I could assign each button a different numerical value, but I couldn't get that to work either. Finally, I was thinking I could just link each order of clicks to different imagebutton files, but it still presents the same issue, I think.
Please help!
Re: Multiple conditional statements in an imagebutton
Posted: Sat Nov 13, 2021 1:24 am
by philat
The right way to do this, imo, is to do the logic outside of the screen. Pseudocode below.
Code: Select all
screen clickallthree:
# buttons don't do anything only return value to be used in label objects
textbutton "1" action Return("firstobj")
label before_screen:
call screen clickallthree
label objects:
# use returned value from buttons to do whatever needs to be done here
# you can access returned value with _return so like if _return=="firstobj" do whatever etc.
if [all three vars]:
jump after_screen
else:
jump before_screen (i.e., call screen clickallthree but then fall down to label objects after return -- you can change the structure here to use jumps or whatever if you'd prefer, the point is that you should be looping from a call screen to another call screen until a condition is met and you break the loop)
label after_screen:
# proceed with story
Re: Multiple conditional statements in an imagebutton
Posted: Sat Nov 13, 2021 2:31 am
by strayerror
For the sake of balance, here are two options that do keep it all within the screen:
They both presuppose that you only want to click each item once, with the buttons getting disabled once clicked. It is possible to modify them if you wish to keep all buttons clickable until all have been clicked at least once, but disabling them can help nudge the player along through clicking each of them.
Code: Select all
label start:
scene black
call screen test1()
'test1 complete'
call screen test2()
'test2 complete'
return
# This one reads strangely until you remember that the condition in the If is
# evaluated when the screen is displayed, and not after the player clicks.
screen test1():
default track = {1, 2, 3}
$ check = If(len(track) == 1, Return())
textbutton 'ONE' align (.4, .4) action RemoveFromSet(track, 1), check
textbutton 'TWO' align (.5, .6) action RemoveFromSet(track, 2), check
textbutton 'THREE' align (.6, .4) action RemoveFromSet(track, 3), check
screen test2():
default track = {1, 2, 3}
textbutton 'ONE' align (.4, .4) action RemoveFromSet(track, 1)
textbutton 'TWO' align (.5, .6) action RemoveFromSet(track, 2)
textbutton 'THREE' align (.6, .4) action RemoveFromSet(track, 3)
# This is a bit cheaty, but also allows adding some delay after the final
# click before the screen ends.
if not track:
timer .001 action Return()
Hope that helps and sheds a little light on some possible pure screenlang alternatives. :)
Re: Multiple conditional statements in an imagebutton
Posted: Sat Nov 13, 2021 2:43 am
by philat
Just wanted to add that I presumed the goal is to do something on each button click when recommending the return out and loop call screen method (e.g., because all evaluation is happening out of screen anyway, it's easy to add interactions like character makes short remark about what you picked up, perhaps says there might be a few things of interest left in the area, etc.). If the goal is only to click three things in succession, doing it in screen probably makes more sense.
Re: Multiple conditional statements in an imagebutton
Posted: Sat Nov 13, 2021 7:10 am
by Alex
account183 wrote: ↑Fri Nov 12, 2021 6:15 pm
... My initial thought was to assign each button a True/False variable, and then embed an "if" statement and an "and" statement within each imagebutton. So, for instance, if imagebuttons #1 and #2 are both clicked, then clicking #3 would go to the next screen. Whereas, if imagbuttons #2 and #3 are clicked first, then imagebutton #1 would go to the next screen. I can't get the code to work though. ...
The third option (that might suit in some cases or not in others) would be
Code: Select all
screen buttons_scr():
tag my_screen # only one screen with the same tag will be shown onscreen
default flag_1 = False # screen variable (default value on each screen show)
default flag_2 = False
default flag_3 = False
vbox:
align(0.5, 0.05)
textbutton "Click Me 1":
if flag_2 and flag_3:
action [SetScreenVariable("flag_1", True), Show("the_other_scr")]
else:
action ToggleScreenVariable("flag_1", True, False) # toggles value (True/False)
textbutton "Click Me 2":
if flag_1 and flag_3:
action [SetScreenVariable("flag_2", True), Show("the_other_scr")]
else:
action ToggleScreenVariable("flag_2", True, False)
textbutton "Click Me 3":
if flag_1 and flag_2:
action [SetScreenVariable("flag_3", True), Show("the_other_scr")]
else:
action ToggleScreenVariable("flag_3", True, False)
screen the_other_scr():
tag my_screen
modal True
# clicking will hide the screen and let player proceed through the hard pause
key 'dismiss' action [Return(), Hide("the_other_scr")]
frame:
align(0.5, 0.5)
xysize(400, 200)
text "Well done!" align(0.5, 0.5)
# The game starts here.
label start:
"..."
show screen buttons_scr
$ renpy.pause(hard=True) # will stop the game untill screen Return something
"Done"
"?!"
https://www.renpy.org/doc/html/screens.html#key
https://www.renpy.org/doc/html/screen_a ... enVariable
https://www.renpy.org/doc/html/other.html#renpy.pause
Re: Multiple conditional statements in an imagebutton
Posted: Sat Nov 13, 2021 11:33 am
by account183
Thank you all so much for the help! I got it to work! It was really great getting to see the different approaches. I'm still new to all this, so I wasn't able to fully appreciate the elegance of each option.
To provide some more color, basically I was coding an "I spy" type mini-game where the player needs to find three hidden objects in a scene. After clicking an object, it switches from "idle" to "hover" state (essentially, from camouflaged to highlighted). I was able to accomplish this by adding an additional action to each imagebutton to show a screen. However, the next issue I ran into was how to clear those screens when the player moves on. I addressed this with "renpy.hide_screen".
I'm sure there must be a better way to do this, but thank you so much again!
Here's how I coded it:
Code: Select all
label game:
scene bg
call screen test1()
scene bg2
"Congrats!"
call next
screen ObjectAScreen:
add "ObjectA_hover.png" xpos 1000 ypos 300
screen ObjectBScreen:
add "ObjectB_hover.png" xpos 700 ypos 400
screen ObjectCScreen:
add "ObjectC_hover.png" xpos 1200 ypos 600
screen test1():
default track = {1, 2, 3}
$ check = If(len(track) == 1, Return())
imagebutton auto "ObjectA_%s.png" xpos 1000 ypos 300 focus_mask True action [RemoveFromSet(track, 1), check, Show("ObjectAScreen")]
imagebutton auto "ObjectB_%s.png" xpos 700 ypos 400 focus_mask True action [RemoveFromSet(track, 2), check, Show("ObjectBScreen")]
imagebutton auto "ObjectC_%s.png" xpos 1200 ypos 600 focus_mask True action [RemoveFromSet(track, 3), check, Show("ObjectCScreen")]
label next:
python:
renpy.hide_screen("ObjectAScreen")
renpy.hide_screen("ObjectBScreen")
renpy.hide_screen("ObjectCScreen")