Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Text input in a <Scene> based Game
-
I have attempted to search this forum via Google, to answer the question.
No joy apart from some old posts stating that it is not possible.Has anyone come up with a method for resolving this?
I can call a menu but have not figured out how to get text input.....
Ideas anyone?
-
-
@adrius42 just to show it, little modification of Examples/Animation/Magic Text.py
Tap on top of screen, it will show a popover ui.TextView where you can change the text.
If you tap lower and move your finger, you get the standard process of the script.# coding: utf-8 ''' Draw lines on the screen to reveal the 'Zen of Python' -- or replace it with your own text (by changing the MESSAGE string). ''' from scene import * import random import math import ui from colorsys import hsv_to_rgb A = Action FONT_NAME = 'Ubuntu Mono' if min(ui.get_screen_size()) > 750: FONT_SIZE = 60 else: FONT_SIZE = 30 SPACING = FONT_SIZE * 0.45 MESSAGE = '''The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those! ''' class MyScene (Scene): def setup(self): self.hue = 0.0 self.prev_touch = None self.letter_index = 0 self.background_color = '#262b30' self.instructions = LabelNode('Tap at top to change text or \nDraw with one finger.', ('HelveticaNeue-Light', 24), position=self.size/2, parent=self) def did_change_size(self): if self.instructions: self.instructions.position = self.size/2 def textview_did_end_editing(self, textview): global MESSAGE MESSAGE = textview.text textview.end_editing() textview.close() return True def touch_began(self, touch): if touch.location[1] > (ui.get_screen_size()[1]-50): tv = ui.TextView() tv.font = ('Menlo',15) tv.frame = (0,0,400,500) tv.delegate = self tv.text = MESSAGE tv.begin_editing() tv.present('popover', popover_location=(touch.location[0], ui.get_screen_size()[1]-touch.location[1]), hide_title_bar=True) return if self.instructions: self.instructions.run_action(Action.fade_to(0, 1)) self.instructions = None self.prev_touch = touch.location def touch_moved(self, touch): d = touch.location - self.prev_touch if abs(d) < SPACING: return letter_pos = self.prev_touch + 0.5 * d self.prev_touch = touch.location letter = MESSAGE[self.letter_index] self.letter_index += 1 self.letter_index %= len(MESSAGE) if not letter.strip(): return a = -math.atan2(*d) + math.pi/2 font = (FONT_NAME, FONT_SIZE) color = hsv_to_rgb(self.hue, 0.65, 1) label = LabelNode(letter, font=font, position=touch.location, color=color) label.rotation = a self.hue += 0.03 label.run_action(A.sequence( A.move_to(letter_pos.x, letter_pos.y, 1.2, TIMING_ELASTIC_OUT), A.wait(3), A.scale_to(0, 0.25), A.remove())) self.add_child(label) for i in range(5): p = SpriteNode('shp:Spark', position=letter_pos, color=color) p.blend_mode = BLEND_ADD r = max(FONT_SIZE, 50) dx, dy = random.uniform(-r, r), random.uniform(-r, r) p.run_action(A.sequence( A.group( A.scale_to(0), A.move_by(dx, dy, 0.5, TIMING_EASE_OUT_2)), A.remove())) self.add_child(p) if __name__ == '__main__': run(MyScene(), multi_touch=False)
-
@adrius42, if you want your text input to be a part of the scene and not a ’popover’, there is this in the docs:
”You can also use this approach to add traditional UI elements (e.g. text fields) to your game. For this purpose, you don’t have to create a SceneView – you can simply use the view that was created automatically, using your Scene‘s view attribute (this will only work if a scene is already being presented of course).”
-
@cvp, I see many of your excellent answers utilize the ’popover’ present option. Please note that this only works on the iPad.
-
@mikael You are right, as I have an iPad. Here, it is only a quick sample but in my other last scripts about ObjectveC ViewControllers, you can use them as popover and sheet.
-
-
You could also use dialogs.
def touch_began(self, touch): if touch.location[1] > (ui.get_screen_size()[1]-50): global MESSAGE MESSAGE = dialogs.text_dialog('enter text', text='') self.letter_index = 0 return if self.instructions: self.instructions.run_action(Action.fade_to(0, 1)) self.instructions = None self.prev_touch = touch.location
-
I might be late to this conversation but I am using Scene to build a visual Zork, and I find that ui.textfield works perfect for input.
def player_input(self): def command_given(sender): self.command = com_input.text self.player_command() com_input = ui.TextField() com_input.name = 'What next?' com_input.autocapitalization_type = False com_input.background_color = 'lightblue' com_input.frame = (0, 0, 500, 50) com_input.present('popover', popover_location = (5, 685)) com_input.clear_button_mode = 'always' com_input.action = command_given def player_command(self): if self.command in ['north', 'south', 'east', 'west']: self.current_room = self.current_room.move(self.command) self.player_roominfo() ```
-
Here is a sample of using ui.textfield for input in scene