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.
Help with SpriteNode movement using buttons
-
It was difficult for me to figure out because I'm a beginner, but I seem to have gotten the sprite movement halfway working with buttons. The rotation of the walking textures works with the gravity() module,
(see: https://github.com/bbroadhead/pythonista-rpg/blob/master/knight_test.py or part 3 of the pythonista game tutorial)
but it is a little wonky with using the buttons to move. I think it’s just because I haven’t figured out how to get update(self) to update only while the sprite is in motion. In the game tutorial, it uses a simple threshold for gravity() so it only updates when the accelerometer reads above a certain value, but I’m unsure what to reference in update(self) so it only updates when you’re pressing a button. I tried to reference touch_began but no matter how I tried it didn’t like that.- What could I put in the spot that I commented out so update(self) recognizes touch_began?
My end goal is to make the sprite four directional like an RPG instead of side-scrolling. Reference this video for an example.
Which brings me to my second question:
2. How would I make the sprite move a static distance while you’re holding down the button? (For example, move a certain number of pixels across the screen) rather than movement that references a fraction of the screen size as used below (I implemented the idea from this thread, but I want the sprite to move independently of screen size).I used a resized version of this sprite (but the sprite can easily be changed back to the alien from the original example),
and this song (you can comment out the Player).Thank you in advance for your help!
import ui from scene import * import sound standing_texture = Texture('Idle.png',) walk_textures = [Texture('Walk 1.png'), Texture('Walk 2.png'), Texture('Walk 3.png'), Texture('Walk 4.png'), Texture('Walk 5.png'), Texture('Walk 6.png'), Texture('Walk 7.png'), Texture('Walk 8.png'), Texture('Walk 9.png'), Texture('Walk 10.png')] player = sound.Player('battleThemeA.mp3') player.number_of_loops = -1 class MyScene(Scene): def setup(self): self.background_color = '#7bc7ff' ground = Node(parent=self) x = 0 while x <= self.size.w + 64: tile = SpriteNode('plf:Ground_Grass', position=(x, 0)) ground.add_child(tile) x += 64 self.player = SpriteNode(standing_texture) self.player.anchor_point = (0.5, 0) self.player.position = (self.size.w/2, 20) self.add_child(self.player) self.right_button = ShapeNode(ui.Path.rounded_rect(0, 0, 100, 50, 20), position=(250, 100), fill_color='black', parent=self) self.left_button = ShapeNode(ui.Path.rounded_rect(0, 0, 100, 50, 20), position=(100, 100), fill_color='black', parent=self) self.walk_step = -1 player.play() def touch_began(self, touch): right_move = Action.move_by(self.size[0]/1, 0, 2, TIMING_SINODIAL) left_move = Action.move_by(self.size[0]/-1, 0, 2, TIMING_SINODIAL) if touch.location in self.right_button.frame: self.player.run_action(right_move, 'move_action_key') Action.repeat(right_move, 0) self.player.x_scale = 1 moving += 1 elif touch.location in self.left_button.frame: self.player.run_action(left_move, 'move_action_key') Action.repeat(left_move, 0) self.player.x_scale = -1 def touch_ended(self, touch): if touch.location in self.right_button.frame: self.player.remove_action('move_action_key') elif touch.location in self.left_button.frame: self.player.remove_action('move_action_key') def stop(self): player.stop() def update(self): #if moving: -------------------------------what to do here? x = self.player.position.x x = max(0, min(self.size.w, x)) self.player.position = (x, 20) step = int(self.player.position.x / 20) % 10 if step != self.walk_step: self.player.texture = walk_textures[step] sound.play_effect('rpg:Footstep00', 0.05, 1.0 + 0.5 * step) self.walk_step = step else: self.player.texture = standing_texture self.walk_step = -1 run(MyScene())
-
here is a very simple example using the built in exAmple:
def touch_began(self,touch): if touch.location.x>.7*self.size.w: self.x_move_dir=+1 if touch.location.x < .3*self.size.w: self.x_move_dir=-1 def touch_ended(self,touch): self.x_move_dir=0
then, you replace g.x in update_player with self.x_move_dir.
you could have a similar logic for y motion.of course, this method doesnt work for multiple fingers. for that you need to keep a dictionary of touches, that gets set in touch_began (use touch.id as the key). you update the touch in touch_moved, and delete it in touch_ended. then, in your update function, you have to cycle through the active touches to see what is currently being pressed each cycle.
-
@KnightExcalibur, if you have many buttons, it is probably clearer to add custom ui views with scene.view.add_subview. They can set e.g.
pressed
to True or False in theirtouch_began
andtouch_ended
methods. Then you can just check e.g.if up_button.pressed:
-
You gentlemen are brilliant! Thank you so much, this is exactly what I needed to move forward with this little project.