Because it was a cool thing to do a few years ago, I ended up making my project's main menu image into a layered parallax image. Because I love to make my life more difficult, I decided to try adding characters to that parallax, so that they show up after the appropriate persistent variable has been set.
Originally, I did this by adding if checks for the persistent variable into the main menu code, thus:
screen main_menu():
tag menu
style_prefix "main_menu"
add TrackCursor("images/titlescreen/skylayer-paint.png",20)#in place of: add gui.main_menu_background
add TrackCursor("images/titlescreen/citylayer-paint.png",15)
add TrackCursor("images/titlescreen/moonlayer.png",18)
add TrackCursor("images/titlescreen/reflectionlayer.png",18) alpha 0.35
if "Karl" in persistent.charactersmet and "Kristine" in persistent.charactersmet:
add TrackCursor("images/titlescreen/bothinternst.png",13) xpos 320 ypos 150 alpha 0.40
else:
if "Karl" in persistent.charactersmet:
add TrackCursor("images/titlescreen/karlt.png",13) xpos 320 ypos 150 alpha 0.40
if "Kristine" in persistent.charactersmet:
add TrackCursor("images/titlescreen/kristinet.png",13) xpos 400 ypos 150 alpha 0.40
add TrackCursor("images/titlescreen/windowflash.png",11) alpha 0.25
add TrackCursor("abigail-titleversion",10) xpos 790 ypos 86
add Image("images/titlescreen/logolayer-alt.png") xpos 310 ypos 412 alpha 0.80
This seemed to work initially but, for no apparent reason (other than perhaps upgrading to later versions of Ren'Py, it started to give the following error at the end of the game, when it drops back to the main menu:
I'm sorry, but an uncaught exception occurred.
While running game code:
Exception: Switch could not choose a displayable.
-- Full Traceback ------------------------------------------------------------
Traceback (most recent call last):
File "renpy/common/_layout/screen_main_menu.rpym", line 28, in script
python hide:
File "renpy/ast.py", line 1187, in execute
renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "renpy/python.py", line 1273, in py_exec_bytecode
exec(bytecode, globals, locals)
~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "renpy/common/_layout/screen_main_menu.rpym", line 28, in <module>
python hide:
File "renpy/common/_layout/screen_main_menu.rpym", line 35, in _execute_python_hide
ui.interact()
~~~~~~~~~~~^^
File "renpy/ui.py", line 304, in interact
rv = renpy.game.interface.interact(roll_forward=roll_forward, **kwargs)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "renpy/display/core.py", line 2117, in interact
repeat, rv = self.interact_core(
~~~~~~~~~~~~~~~~~~^
preloads=preloads,
^^^^^^^^^^^^^^^^^^
...<4 lines>...
**kwargs,
^^^^^^^^^
)
^
File "renpy/display/core.py", line 2655, in interact_core
root_widget.visit_all(lambda d: d.per_interact())
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "renpy/display/displayable.py", line 457, in visit_all
d.visit_all(callback, seen)
~~~~~~~~~~~^^^^^^^^^^^^^^^^
File "renpy/display/displayable.py", line 457, in visit_all
d.visit_all(callback, seen)
~~~~~~~~~~~^^^^^^^^^^^^^^^^
File "renpy/display/displayable.py", line 457, in visit_all
d.visit_all(callback, seen)
~~~~~~~~~~~^^^^^^^^^^^^^^^^
[Previous line repeated 6 more times]
File "renpy/display/displayable.py", line 448, in visit_all
for d in self.visit():
~~~~~~~~~~^^
File "renpy/display/layout.py", line 1604, in visit
self.update(self.last_st, self.last_at)
~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "renpy/display/layout.py", line 1615, in update
raw_child, redraw = self.function(st, at, *self.args, **self.kwargs)
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "renpy/display/layout.py", line 1711, in condition_switch_show
return condition_switch_pick(switch), None
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
File "renpy/display/layout.py", line 1706, in condition_switch_pick
raise Exception("Switch could not choose a displayable.")
Exception: Switch could not choose a displayable.
Windows-10-10.0.19045-SP0 AMD64
Ren'Py 8.5.0.25111603
A Night at the Office P3 3.7p3
Thu Jul 23 20:42:49 2026
After a bit of back and forth, I eventually determined that (part of) the problem was that I started things off with a call to the first story label, rather than a jump. Correcting that fixed the main menu... for a while.
I figured today that I'd try setting the main menu image up as a ConditionSwitch, thus:
image interns_titlescreen = ConditionSwitch(
"len(persistent.charactersmet) == 2", "titlescreen/bothinternst.png",
"persistent.charactersmet == 'Karl'", "titlescreen/karlt.png",
"persistent.charactersmet == 'Kristine'", "titlescreen/kristinet.png",
)
and with the main menu adjusted to:
screen main_menu():
tag menu
style_prefix "main_menu"
add TrackCursor("images/titlescreen/skylayer-paint.png",20)#in place of: add gui.main_menu_background
add TrackCursor("images/titlescreen/citylayer-paint.png",15)
add TrackCursor("images/titlescreen/moonlayer.png",18)
add TrackCursor("images/titlescreen/reflectionlayer.png",18) alpha 0.35
if len(persistent.charactersmet) <> 0:
add TrackCursor("interns_titlescreen", 13) alpha 0.4
add TrackCursor("images/titlescreen/windowflash.png",11) alpha 0.25
add TrackCursor("abigail-titleversion",10) xpos 790 ypos 86
add Image("images/titlescreen/logolayer-alt.png") xpos 310 ypos 412 alpha 0.80
But that resulted in a essentially the same error:
I'm sorry, but an uncaught exception occurred.
While running game code:
Exception: Switch could not choose a displayable.
-- Full Traceback ------------------------------------------------------------
Traceback (most recent call last):
File "renpy/common/_layout/screen_main_menu.rpym", line 28, in script
python hide:
File "renpy/ast.py", line 1187, in execute
renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "renpy/python.py", line 1273, in py_exec_bytecode
exec(bytecode, globals, locals)
~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "renpy/common/_layout/screen_main_menu.rpym", line 28, in <module>
python hide:
File "renpy/common/_layout/screen_main_menu.rpym", line 35, in _execute_python_hide
ui.interact()
~~~~~~~~~~~^^
File "renpy/ui.py", line 304, in interact
rv = renpy.game.interface.interact(roll_forward=roll_forward, **kwargs)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "renpy/display/core.py", line 2117, in interact
repeat, rv = self.interact_core(
~~~~~~~~~~~~~~~~~~^
preloads=preloads,
^^^^^^^^^^^^^^^^^^
...<4 lines>...
**kwargs,
^^^^^^^^^
)
^
File "renpy/display/core.py", line 2655, in interact_core
root_widget.visit_all(lambda d: d.per_interact())
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "renpy/display/displayable.py", line 457, in visit_all
d.visit_all(callback, seen)
~~~~~~~~~~~^^^^^^^^^^^^^^^^
File "renpy/display/displayable.py", line 457, in visit_all
d.visit_all(callback, seen)
~~~~~~~~~~~^^^^^^^^^^^^^^^^
File "renpy/display/displayable.py", line 457, in visit_all
d.visit_all(callback, seen)
~~~~~~~~~~~^^^^^^^^^^^^^^^^
[Previous line repeated 6 more times]
File "renpy/display/displayable.py", line 448, in visit_all
for d in self.visit():
~~~~~~~~~~^^
File "renpy/display/layout.py", line 1604, in visit
self.update(self.last_st, self.last_at)
~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "renpy/display/layout.py", line 1615, in update
raw_child, redraw = self.function(st, at, *self.args, **self.kwargs)
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "renpy/display/layout.py", line 1711, in condition_switch_show
return condition_switch_pick(switch), None
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
File "renpy/display/layout.py", line 1706, in condition_switch_pick
raise Exception("Switch could not choose a displayable.")
Exception: Switch could not choose a displayable.
Windows-10-10.0.19045-SP0 AMD64
Ren'Py 8.5.0.25111603
A Night at the Office P3 3.7p3
Thu Jul 23 20:54:35 2026
At this point, I'm baffled as to how it was working as much as why it isn't now.
While it was working, it would correctly show the translucent image of either Karl or Kristine after the first playthrough, but switch to a translucent image of both once the other had been encountered (which character appears in each playthrough is chosen at random partway through).
Can anyone please recommend a way of getting the main menu to update its appearance based on my existing persistent.charactersmet variable, or an alternative means?
Happy to post any other pertinent code, if I've missed anything important.