I have almost zero experience with Ren'Py itself, but have been coding professionally in various languages for a while. I'm moderately skilled with Python, though hardly an expert.
I am building a custom GUI on top of NVL mode as part of a project to port a game from RAGS to Ren'Py. The idea is that there will be graphical controls that allow the player to move around and interact with the game world. At the moment, I'm working on the compass rose. My current game script basically involves putting the control screens on frame, then pausing indefinitely while waiting for input. I'm pretty sure this is wrong, and the cause of my error, but I'm not sure what the correct way to go accomplish this is.
What I'm actually trying to accomplish is, when the game has no more text to display, it stops and waits for the player to tell it to do something, rather than just running off the end and exiting the game. My current solution obviously isn't going to work, and I suspect that it is inherently flawed in execution. What is a good way to accomplish this goal? Please note that player_gui is located on the left side of the screen, while room_gui is located on the right. I haven't found a way to put them in the same screen call, though I haven't really tried. Whatever solution is used will need to allow the player to interact with both screens, simultaneously. Bonus points if neither GUI screen will respond to player clicks while it still has text to display.
For fun, the entirety of traceback.txt is attached, but the relevant part seems to be:
Code: Select all
While running game code:
File "game/script.rpy", line 27, in script
pause
File "renpy/common/000statements.rpy", line 445, in execute_pause
renpy.pause()
File "renpy/common/00action_other.rpy", line 537, in __call__
rv = self.callable(*self.args, **self.kwargs)
File "game/classes.rpy", line 47, in move
self.location = self.location.exits.get(exit)
File "game/classes.rpy", line 33, in location
renpy.say(None, location.name)
File "renpy/common/00nvl_mode.rpy", line 381, in do_display
**display_args)
Exception: Cannot start an interaction in the middle of an interaction, without creating a new context.
Code: Select all
define claire = Character("Claire", kind=nvl)
define narrator = nvl_narrator
define menu = nvl_menu
init python:
config.keymap['hide_windows'] = []
player = Player()
playerGui = PlayerGui()
label start:
scene bg room
show screen player_gui()
show screen room_gui()
$ player.location = prologueBedroom
window show None
jump roomLoop
label roomLoop:
"roomLoop before"
while True:
pause
"roomLoop after"
Code: Select all
## Player screen ###############################################################
##
## This screen is used for player-related GUI elements
screen player_gui:
frame:
xsize 324
yfill True
padding (0, 0)
background 'gui player_menu background'
vbox:
fixed:
xsize 324
ysize 405
add "[player.avatar]" fit 'contain' align (0.5, 0.5)
fixed:
xsize 324
ysize 331
null
fixed:
xsize 324
ysize 144
null height 144
frame:
xsize 324
ysize 200
padding (0, 0)
background 'gui player_menu compass base'
if player.location.exits.get('n'):
imagebutton:
idle 'gui player_menu compass point'
pos (162, 40)
anchor (0.5, 0.5)
action Function(player.move, 'n')
<snip for brevity, just the rest of the compass rose here>
Code: Select all
init -1 python:
class Player(object):
def __init__(self, avatar='avatar prologue claire dressed', location=None):
self._avatar = avatar
self._location = location
@property
def avatar(self):
return self._avatar
@avatar.setter
def avatar(self, avatar):
self._avatar = avatar
@property
def location(self):
return self._location
@location.setter
def location(self, location):
if not isinstance(location, Room):
raise ValueError("Expected a room, got {}".format(type(location)))
# Exit triggers for current location
if location.exit:
location.exit()
if location.nextExit:
location.nextExit()
# Move to next location and announce it
self._location = location
renpy.say(None, location.name)
# Enter triggers for new location
if location.enter:
location.enter()
if location.nextEnter:
location.nextEnter()
if location.examine:
location.examine()
def move(self, exit):
if self.location.exits.get(exit):
self.location = self.location.exits.get(exit)
class PlayerGui(object):
def __init__(self, compass='gui hive compass', logo='gui hive logo'):
self.compass = compass
self.logo = logo
@property
def compass(self):
return self._compass
@compass.setter
def compass(self, compass):
self._compass = compass
@property
def logo(self):
return self._logo
@logo.setter
def logo(self, logo):
self._logo = logo
class Room:
_validExits = ['n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw', 'u', 'd', 'i', 'o']
def __init__(self, name='', description='', image='', exits=dict()):
self.name = name
self.description = description
self.image = image
self.exits = exits
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
@property
def description(self):
return self._description
@description.setter
def description(self, description):
self._description = description
@property
def exits(self):
return self._exits
@exits.setter
def exits(self, exits):
if isinstance(exits, dict):
for k in exits.keys():
if k not in self._validExits:
raise ValueError("Direction '{}' not valid".format(k))
self._exits = exits
elif isinstance(tuple, exits) and len(exits) == 2:
if exits[0] not in self._validExits:
raise ValueError("Direction '{}' not valid".format(exits[0]))
self._exits[exits[0]] = exits[1]
else:
raise ValueError("Expecting dict or tuple (direction, room)")
@property
def image(self):
return self._image
@image.setter
def image(self, image):
self._image = image;
enter = None
nextEnter = None
exit = None
nextExit = None
search = None
def examine(self):
# Say the location description(s)
if isinstance(self.description, list):
for i in self.description:
renpy.say(None, i)
else:
renpy.say(None, self.description)
Code: Select all
init python:
prologueBedroom = Room(
name='Bedroom',
description='Your bedroom. It took a long time to get it just how you like it!',
image='room prologue bedroom'
)
prologueBathroom = Room(
name='Bathroom',
description=['Your bathroom. Pretty awesome really, with a great view.',
'You\'re going to replace the bath with a shower cubicle soon. You really don\'t like bathing, showers are just faster, more economical and less icky.'
],
image='room prologue bathroom'
)
prologueBedroom.exits = {'s': prologueBathroom}
prologueBathroom.exits = {'n': prologueBedroom}