Forum Archive

Execute a series of actions on touch

jellybeard

How can I execute a series of actions on a single touch? For example, if I have this example from the Pythonista documentation but I want to shoot say 3 lasers, one right after the other or with a slight pause between. I tried adding the three lines defining the laser, it’s action, and it’s sound in a loop, but instead of firing the lasers in succession it fired all three at once.

Second question, is there a “do while touch” method that would repeatedly fire lasers while the touch is held?

EDIT:
Updated script to include Action.sequence. I get an error that the action sequence does not include any actions.


from scene import *
import sound
import random
import math

class MyScene (Scene):
    def setup(self):
        self.background_color = 'midnightblue'
        self.ship = SpriteNode('spc:PlayerShip1Orange')
        self.ship.position = self.size / 2
        self.add_child(self.ship)

    def update(self):
        x, y, z = gravity()
        pos = self.ship.position
        pos += (x * 15, y * 15)
        # Don't allow the ship to move beyond the screen bounds:
        pos.x = max(0, min(self.size.w, pos.x))
        pos.y = max(0, min(self.size.h, pos.y))
        self.ship.position = pos


    def touch_began(self, touch):
        self.run_action(Action.sequence(self.fire_laser(),self.fire_laser(),self.fire_laser()))

    def fire_laser(self):
        a=random.random()*500-250
        laser = SpriteNode('spc:LaserBlue9', position=self.ship.position, z_position=-1, parent=self)
        laser.run_action(Action.sequence(Action.move_by(a, 1000), Action.remove()))
        sound.play_effect('arcade:Laser_1')

cvp

@jellybeard could you try this little script

import scene, ui

class MyScene(scene.Scene):
    def setup(self):
        self.background_color = 'midnightblue'
        self.ship = scene.SpriteNode('spc:PlayerShip1Orange',
                                    position=self.size/2,
                                    parent=self)

    def touch_began(self, touch):
        self.laser = scene.SpriteNode('spc:LaserBlue9', position=self.size/2, z_position=-1, parent=self)
        self.laser.run_action(scene.Action.repeat_forever(scene.Action.sequence(scene.Action.move_by(0, 1000), scene.Action.move_by(0, -1000,0))), 'move_action_key')

    def touch_ended(self, touch):
         self.laser.remove_action('move_action_key')       
         self.laser.remove_from_parent()
         del self.laser

scene.run(MyScene(), show_fps=True)
jellybeard

Thanks for the replies.

I tried a sequence (see updated example above) but it looks as if calling a method (fire_laser) doesn’t count as an action as I get an error. The ship still fires three at once.

I tried your example too and that’s close to what I am after! The lasers stop mid flight on touch end.

cvp

@jellybeard said

The lasers stop mid flight on touch end

Did you not forget the two lines

         self.laser.remove_from_parent()
         del self.laser
cvp

@jellybeard said

calling a method (fire_laser) doesn’t count as an action

It is sure that a method is not an action! Thus normal error

There is also
classmethod Action.repeat(action, repeat_count)
Creates an action that repeats another action a specified number of times. If repeat_count is <=0, the action repeats forever (or until it is removed explicitly).

JonB

To get fire_laser to work, you need an Action.call.

Also, be sure to use duration in your move_by otherwise they will always take 1 second.

cvp

@JonB I use the standard duration of 1 second to go up and a duration of 0 to come back at center of screen

JonB

How about this slight modification to the original -- should prevent the lasers from disappearing when touch ends. Also, keeps track of the lasers for use in hit detection

from scene import *
import sound
import random
import math

class MyScene (Scene):
    def setup(self):
        self.background_color = 'midnightblue'
        self.ship = SpriteNode('spc:PlayerShip1Orange')
        self.ship.position = self.size / 2
        self.add_child(self.ship)
        self.lasers=[]
    def update(self):
        x, y, z = gravity()
        pos = self.ship.position
        pos += (x * 15, y * 15)
        # Don't allow the ship to move beyond the screen bounds:
        pos.x = max(0, min(self.size.w, pos.x))
        pos.y = max(0, min(self.size.h, pos.y))
        self.ship.position = pos


    def touch_began(self, touch):


 laser_animation=Action.repeat_forever(Action.sequence(Action.call(self.fire_laser), Action.wait(0.1) ) )
        self.run_action(laser_animation, 'laser')

    def touch_ended(self,touch):
           self.remove_action('laser')
    def remove_laser(self,laser):
        del self.lasers[laser]
    def fire_laser(self):
        a=random.random()*500-250
        laser = SpriteNode('spc:LaserBlue9', position=self.ship.position, z_position=-1, parent=self)
        self.lasers.append(laser)
        laser.run_action(Action.sequence(Action.move_by(a, 1000), Action.remove(), Action.call(lambda:self.remove_laser(laser))))
        sound.play_effect('arcade:Laser_1')