Commits

Anonymous committed ee7ca13

Now the output of a scrolling dialog also looks good and we can specify not to end with a linebreak and a starting position in the line, so we can (in future) print different parts in the same line using different styles (for example with different speed).

  • Participants
  • Parent commits a54e004

Comments (0)

Files changed (3)

rpg_lib/anyrpg.py

 Ideas: 
     - Lazy loading modules, to be able to print stuff at once without having to print before the imports. 
     - Add getting experience for groups and show the chars together (only one experience header instead of one per char). 
+    - Being able to press "pause" when using autoscrolling output. 
 
 
 Basic design principles for the scripting language: 
     """Basic user interaction: Showing and asking things."""
     def __init__(self, *args, **kwds): 
         super(UserInteraction, self).__init__(*args, **kwds)
+	self.line_wait = 0.4
+	self.char_wait = 0.05
         
     def ask(self, question=None, *args, **kwds): 
         """Ask a question.
 	    sleep(0.01)
             return raw_input(_(question) + " ")
     
-    def diag(self, data, localize=True, autoscroll=False, line_wait = 0.4, char_wait = 0.05, *args, **kwds):
+    def diag(self, data, localize=True, autoscroll=False, line_wait = None, char_wait = None, relative_speed = 1, end_with_linebreak = True, position_in_line = 0, *args, **kwds):
 	""" Print a dialog line. 
 	
 	@param line_wait: The time to wait at linebreaks before continuing with the text. 
 	@param char_wait: The time to wait per char before printing the next char. 
+	@param relative_speed: The relative speed of this dialog compared to others. - Limitation: Speed can only be adjusted for whole lines! 
 	@param autoscroll: If diag should output char by char (True) or wait for user input for each lines (False). 
+	@param end_with_linebreak: If there should be a linebreak at the end (True), or if the next dialog should write on the same line (False). 
+	@param position_in_line: Where in the text line the cursor should be positioned when writing. 
 	"""
+	# If the method doesn't get line_wait and/or char_wait, it uses the default values for the UI. 
+	# With this we can customize the speed of the output. 
+	if line_wait is None: 
+	    line_wait = self.line_wait
+	if char_wait is None: 
+	    char_wait = self.char_wait
+
+	# Now adjust the speed by the relative speed: 
+	if relative_speed != 1: 
+	    char_wait *= relative_speed
+	    line_wait *= relative_speed
+
+	# Localize the text
         if localize: 
             text = _(data)
         else: text = data 
     
+	# And output it. 
+	# If we have no autoscrolling, we just output the text. 
         if not autoscroll: 
             raw_input(text)
+	
+	# If we have autoscrolling, we print it char by char. 
+	# Limitation: This looks really dumb, if the text is longer than one line. 
         else: 
 	    if text: 
-		print text[0]
+		print '\033[' + str(position_in_line) + 'G' + text[0]
 	    else: 
+		self.diag("...press enter to read on...") # press enter to read on at each empty line, so readers can rest. 
+		print "\033[1A", 
+		for i in range(len(_("...press enter to read on..."))): 
+		    print " ",
 		print text
 		sleep(line_wait)
             # First sleep 1/10th second. This ensures that the text gets shown before sleeping.
             sleep(char_wait)
 	    # If we have text, wait one 10th of a second per char. 
 	    for i in range(len(text)): 
-		print '\033[1A' + text[:i+1] # !!! this depends on the shell scape seqneuces to work !!!
+		# load the current cursor position
+		print '\033[1A\033[' + str(position_in_line) + 'G' + text[:i+1] # !!! this depends on the shell scape sequences to work !!!
 		sleep(char_wait)
+	
+	# If we don't want a linebreak at the end, jump back up to the last line. 
+	if not end_with_linebreak: 
+	    # Move back after the last char on the last line. 
+	    print '\033[1A\033[' + str(len(text)) + 'G',
 
 class Dialogs(object): 
     """Basic dialogs. 
 
 ### Functions ###
 
-def _(text):
-    '''String function to allow localizing later on. '''
-    return str(text)
+de_DE = {
+"""...press enter to read on...""": """...zum weiterlesen Enter drücken...""",
+}
+
+def _(text, locale="en_EN", locales={"de_DE": de_DE}):
+    '''String function to allow localizing later on. 
+    
+    @return: A localized string. '''
+    # TODO: Localize cleanly - this is but a test. 
+    if text in locales["de_DE"]: 
+	return locales["de_DE"][text]
+    else: 
+	return str(text)
+
+
 
 ## Functions needed to be implemented in EVERY simple rpg scripting module (changing their effect for all places where they get used can only be done in the Story class) ###
 def ask(question, *args, **kwds): 

rpg_lib/textrpg.py

 # __date__      = '7th March 2007' 
 
 
-print "...Loading rpg library..."
+#print "...Loading rpg library..."
 
 
-try: 
+try: # Get the modules by relative path
     # AnyRPG classes
     from anyrpg import Char
     from anyrpg import Story as any_story
     # AnyRPG function for localizing. 
     from anyrpg import _
-except: 
+except: # get the modules by absolute path
     # AnyRPG classes
     from rpg_lib.anyrpg import Char
     from rpg_lib.anyrpg import Story as any_story
     from rpg_lib.anyrpg import _
 
 
-# Changing things. I want to display "..." in front of every blank story line. 
+# Changing things. I want to tell stories in lines, broken at word borders. 
 
 class Story(any_story): 
     def __init__(self, *args, **kwds): 
+	self.line_length = 80 #: The maximum length of story lines. 
         super(Story, self).__init__(*args, **kwds)
 
-    def split_diag(self, text, line_length = 80, localize=True, autoscroll=False): 
+    def split_diag(self, text, line_length = None, localize=True, autoscroll=False): 
 	"""Print a dialog in single lines split at word borders. 
 	
 	@param text: The text to output. 
 	
 	"""
 	# Split the text by words to output at most 80 chars per line. 
+	if line_length is None: 
+	    line_length = self.line_length
 	text_to_print = ""
 	for j in text.split(): 
-	    if len(text_to_print) + len(j) > 80: 
+	    if len(text_to_print) + len(j) > line_length: 
 		self.diag(text_to_print, localize=localize, autoscroll=autoscroll) # TODO: If j > 80 -> split j. 
 		text_to_print = j
 	    else: 
         if data is not None: 
             data = _(data)
             for i in data.split("\n"): 
-		self.split_diag(i, localize=False, autoscroll=True)
+		self.split_diag(i, localize=False, autoscroll=True, *args, **kwds)
+	# Wait after each full storypart and promt the user to read on. 
+	self.diag("""...press enter to read on...""", *args, **kwds)
         
 
 # Define helper functions. 
 story_helper = Story()
 
 ### Lines needed in EVERY simple rpg scripting module (changing their effect for all places where they get used can only be done in the Story class) ###
+
 def ask(question, *args, **kwds): 
     """Ask a question. 
     @return: The answer of the user."""
 
 Dieser Leitfaden wird Ihnen Schritt für Schritt die Möglichkeiten des TextRPG nahebringen und es Ihnen so ermöglichen auf einfache Weise eigene TextRPGs zu schreiben. 
 
-Erstmal zur Definition: Ein TextRPG ist eine interaktive Geschichte, in die ihre Nutzer eintauchen und ihren Ausgang beeinflussen können. 
+Erstmal zur Definition: Ein TextRPG ist eine interaktive Geschichte, in die ihre Nutzer eintauchen und so deren Ausgang beeinflussen können. 
 
 Auch wenn es mit komplexeren Skripten wohl möglich wäre, mit dem TextRPG ein MMORPG zu implementieren, ist das nicht seine grundlegende Zielsetzung. 
 
 
 Obwohl diese erste Version rein textbasiert ist, sind die Skripte auf eine Art geschrieben, die eine spätere Übertragung in graphische Oberflächen einfach macht, so dass in den Skripten nur eingefügt werden muss, welche Oberfläche sie nutzen sollen. Das gleiche gilt für sonstige Erweiterungen. 
 
-Für Charakterinteraktionen gibt sie Ihnen ausserdem eine vollständige RPG Bibliothek, die das Ein Würfel System implementert, ein universelles und frei lizensiertes Rollenspielsystem. 
+Für Charakterinteraktionen gibt sie Ihnen ausserdem eine vollständige RPG Bibliothek, die das Ein Würfel System implementert, ein universelles und frei lizensiertes Rollenspielsystem. Weitere Informationen zum Ein Würfel System finden Sie auf http://1w6.org . 
 
 Da das TextRPG in Python geschrieben wurde, funktioniert es direkt auf den verschiedensten Plattformen, GNU/Linux, MacOSX und Windows eingeschlossen. 
 
 Wir wechseln nun in den Python Interpreter. """)
 
 call("python")
+# mit call("python -ic 'from rpg_lib.textrpg import *'") kann das TextRPG schon vorgeladen werden. 
 
 story("""= Lektion 2: Dem Nutzer Fragen stellen und Geschichten weitergeben =
 
 
 mein_spiel/
     mein_spiel.py
-    lib/
+    rpg_lib/
 
 Um die Geschichte zu starten, muss der Nutzer nun einfach mein_spiel.py (doppelt) anklicken. 
 
 Im gleich startenden Python Interpreter können Sie einfach Abschnitte Ihrer eigenen Geschichte ausprobieren, bevor Sie sie in die Textdatei schreiben. Um ihn zu verlassen, benutzen sie wie üblich exit(). 
+
+Anders als in den vorigen Übungen haben wir hier bereits die die TextRPG Funktionen importiert, so dass Sie genau so schreiben können, als würden sie in ihrer vorbereiteten Textdatei schreiben. 
+
 Damit kommen wir zum Ende von Lektion 2. Viel Spaß beim experimentieren! """)
 
-call("python")
+call("python -ic 'from rpg_lib.textrpg import *")
 
 story("""Lektion 3: Charaktere erzeugen und sprechen lassen.