• @trey, one idea would be to place a transparent view on top (as a subview of scene.view) to handle the touches.

    Then you would need to check if the touch is near the top-right corner to simulate clicking on the ”x” with superview.close(). And remember to flip the y coordinate before passing the coordinate and touch type to your scene code. And maybe go via screen coordinates if you do a lot of zooming and panning in your scene.

  • @mikael Thanks for the pull to refresh example. I really appreciate the help. I had a couple issues. The biggest issue was only being able to refresh once after the view is loaded. The second Issue was when pulled too far down, the refresh function was called multiple times. I think I solved these issues. I attached the solution I came up with below.

    import ui, sound class scrollViewDelegate: maxPull = -100 def __init__(self): self.refresh = False def scrollview_did_scroll(self, scrollview): x, y = scrollview.content_offset if y <= 0: delta = max(y, self.maxPull) / self.maxPull if (y <= self.maxPull and not scrollview.tracking and scrollview.decelerating and not self.refresh): scrollview['refresh_bg'][ 'refresh_label'].text_color = 0.50, 0.50, 0.50, delta self.contentRefresh() elif (y <= self.maxPull - 10 and scrollview.tracking and not scrollview.decelerating and not self.refresh): scrollview['refresh_bg']['refresh_label'].text = 'Release to refresh' scrollview['refresh_bg'][ 'refresh_label'].text_color = 0.50, 0.50, 0.50, delta elif (y >= self.maxPull - 10 and scrollview.tracking and not scrollview.decelerating and not self.refresh): scrollview['refresh_bg']['refresh_label'].text = 'Pull to refresh' scrollview['refresh_bg'][ 'refresh_label'].text_color = 0.60, 0.60, 0.60, delta def contentRefresh(self): self.refresh = True sound.play_effect('ui:click3') #print('refreshing') ui.delay(self.contentDidRefresh, 0) def contentDidRefresh(self): self.__init__() w, h = ui.get_screen_size() sv = ui.ScrollView() sv.name = 'Scrollview' sv.always_bounce_horizontal = False sv.always_bounce_vertical = True sv.directional_lock_enabled = True sv.scroll_indicator_insets = (10, 0, 10, 0) sv.bounces = True sv.paging_enabled = False sv.indicator_style = 'black' sv.scroll_enabled = True sv.background_color = 1.0, 1.0, 1.0 sv.content_inset = (0, 0, 0, 0) sv.content_size = (w - 10, h*2) sv.delegate = scrollViewDelegate() rb = ui.View() rb.name = 'refresh_bg' rb.alpha = 1.0 rb.background_color = 0.90, 0.90, 0.90 rl = ui.Label() rl.name = 'refresh_label' rl.alpha = 1.0 rl.alignment = ui.ALIGN_CENTER #rl.background_color = 'white' rl.text = 'Pull to Refresh' rl.text_color = None rl.font = ('<system>', 14) rb.add_subview(rl) sv.frame = (0, 0, w, 0.5) rb.frame = (0, -600, sv.width, 600) rl.frame = (0, rb.height - 32, sv.width, 32) sv.add_subview(rb) sv.present('fullscreen')
  • @JonB Not bad at all for an admin πŸ˜‚
    Sorry, I could not stop myselfπŸ˜‡

  • Thanks, it’s working now!

  • Hi @ETPH. Couple of generic advices:

    Do not use magic constants in your code (like position_options) in multiple places, it's a nightmare when you want to change them. Move them outside of create_tile, touch_began and reuse them there. Like MARGIN_OF_ERROR. Keep your functions / methods short. It's good when they can fit one screen (well, depends how the screen is big :), but you know what I mean. Not a hard rule, but it's about readability and crunching all these bugs quickly. It's easier when it's short. touch_moved is very long and overly complicated. You shouldn't hardcode positions based on your device in case you want to run it on iPhone SE for example. Split your task into several smaller ones. Replace one huge function with many small ones doing just one thing. Again, readability & easier way how to spot a bug.

    I didn't dive into your touch_moved method, sorry. But I did quickly hack an example of generic board & moving tiles. You can find it here.

  • as I understand your code, it is not that data is getting duplicated, but you are using the same touch instance, since the touch Id is the same -- i.e you are updating the touch object, but not creating a new one. really, I think you sort of want to compute the rotation, etc parameters for each state, when the state object gets created, rather than manipulating the touch object in Data. Dunno.

    btw, the python built in debugger is called pdb, and does let you single step code, look at variables in real time, etc. But it is not really useful within scene, since it is console based. I am not sure if scene is compatible with the long press to set breakpoints in the python ista debugger.

  • Hardcore maths!
    I was looking to get a moveable line. Did you squeeze a rect and rotate it?

  • Using min() and max() simplifies keeping sprites in bounds...

    import scene class ButtonNode(scene.SpriteNode): def __init__(self, title, *args, **kwargs): scene.SpriteNode.__init__(self, 'pzl:Button1', *args, **kwargs) self.title = title scene.LabelNode(title, color='blue', font=('Avenir Next', 20), parent=self, position=(0, 0)) def touch_began(self, touch): sprite = self.parent.sprite x, y = sprite.position if self.title == '←': sprite.position = max(x - 20, 0), y elif self.title == 'β†’': sprite.position = min(x + 20, self.parent.size.w), y elif self.title == '↓': sprite.position = x, max(y - 20, 0) elif self.title == '↑': sprite.position = x, min(y + 20, self.parent.size.h) class MyScene(scene.Scene): def setup(self): center = self.size/2 self.sprite = scene.SpriteNode('Dog_Face', parent=self, position=center) ButtonNode('←', parent=self, position=center - (300, 300)) ButtonNode('β†’', parent=self, position=center - (100, 300)) ButtonNode('↓', parent=self, position=center + (100, -300)) ButtonNode('↑', parent=self, position=center + (300, -300)) def touch_began(self, touch): for node in self.children: if touch.location in node.frame and hasattr(node, 'touch_began'): node.touch_began(touch) scene.run(MyScene())
Internal error.

Oops! Looks like something went wrong!