Sorry, I gave bad advice. The correct way to stop an action is

Starting the action:
   composite = Animation(...) | Playsound(...)
   worker_action = node.do(composite)

Stopping the action:
  node.remove_action(worker_action)

The call to remove_action will call worker_action.stop, and will do other
needed housekeeping.

This was causing the traceback you mentioned.

So the minimal change needed in your script would be:
  - At the end of  HelloWorld.__init__ add a line to store a reference to
the sprite,
        self.sprite = sprite

 - Replace the on_key_press method with
    def on_key_press(self, key, modifiers):
        mykey = pyglet.window.key.symbol_string(key)
        print("A key was pressed! Key: %s" % mykey)
        if mykey == "S" and self.myaction is not None:
            self.sprite.remove_action(self.myaction)
            self.myaction = None

Notice that this code also prevents to call remove_action more than once.

Appended is the modified code, with an additional print to show that the
Animate.stop is also called.

Sorry again for the wrong info




On Mon, Oct 9, 2017 at 10:21 PM, Alan Etkin <[email protected]> wrote:

>
>
>> when you call
>>    worker_action.stop()
>> then both actions should receive a a call to .stop , no need to extra
>> magic.
>> You are seeing different behavior ?
>>
>
> I had to implement stop() and step() both for Animation and Sound classes.
> Seems like cocos2d stop mechanism does not know how to stop both animation
> and sound objects after calling worker.stop() (they are pyglet objects
> anyway, not cocos2d objects). I attached the code that worked (a modified
> hello_actions.py script).
>
> My environment:
> Ubuntu 16.04
> Python 3.5
> last cocos 0.6.5
>
> By the way, if you uncomment line 127 (use spawn for sound, animation and
> movement) it throws an exception:
>
> Traceback (most recent call last):
> ...
>   File 
> "/usr/local/lib/python3.5/dist-packages/cocos/actions/interval_actions.py",
> line 368, in update
>     self.target.position = self.start_position + self.delta * t
> AttributeError: 'NoneType' object has no attribute 'position'
>
>
> Thanks again
>
> Alan
>
> --
> You received this message because you are subscribed to the Google Groups
> "cocos2d discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at https://groups.google.com/group/cocos-discuss.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"cocos2d discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/cocos-discuss.
For more options, visit https://groups.google.com/d/optout.
#
# cocos2d
# http://python.cocos2d.org
#

from __future__ import division, print_function, unicode_literals

# This code is so you can run the samples without installing the package
# import sys
# import os
# sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
#

import cocos
from cocos.actions import *
import pyglet
# A color layer is a Layer with the a color attribute


class Animate(Action):
    """Plays a frame by frame animation at a node image

    Arguments:
        animation: path to an animated gif
        loop: if true, run in loop
        stopframe: index number or resource path to
            set a static image on stop.
    """
    def init(self, animation, loop=False, stopframe=0):
        self.animation = animation
        self.loop = loop
        self.stopframe = stopframe

    def start(self):
        # set the node animation
        self.target.image = pyglet.resource.animation(self.animation)
        if not self.loop:
            # pyglet trick to set a finite loop
            self.target.image.frames[-1].duration = None
        self.duration = self.target.image.get_duration()


    def step(self, dt):
        super(Animate, self).step(dt)
        # check for finished loop (single)
        if (not self.loop) and (self._elapsed >= self.duration):
            self._done = True

    def stop(self):
        print("Animate.stop called")
        if self.target and self.target.image:
            if isinstance(self.stopframe, int):
                self.target.image = self.target.image.frames[
                                        self.stopframe].image
            else:
                self.target.image = pyglet.resource.image(self.stopframe)
        super(Animate, self).stop()


class SetImage(InstantAction):
    """A simple image setter class.
    For set image | action, etc. """
    def init(self, image):
        self.image = image

    def start(self):
        self.target.image = self.image


class PlaySound(Action):
    """Plays a sound linked to a node image

    Arguments:
        sound: path to sound (wav/uncompressed) file
        loop: if true, play in loop

    TODO: a mechanism to stop play loop once another
    parallel action is ended
    """
    def play(self):
        self.target.sound = pyglet.media.Player()
        self.target.sound.queue(self.source)
        self.target.sound.play()

    def init(self, sound, loop=False):
        self.loop = loop
        self.source = pyglet.resource.media(sound,
                        streaming=False)
        self.duration = self.source.duration

    def start(self):
        self.play()

    def step(self, dt):
        if self.target and self.target.sound:
            if not self.target.sound.playing:
                self.target.sound.delete()
                if self.loop:
                    # if looped play again
                    self.play()
                else:
                    self._done = True
        super(PlaySound, self).step(dt)

    def stop(self):
        if self.target and self.target.sound:
            self.target.sound.delete()
        super(PlaySound, self).stop()


class HelloWorld(cocos.layer.ColorLayer):

    is_event_handler = True

    def __init__(self):
        # blueish color
        super(HelloWorld, self).__init__(64, 64, 224, 255)

        # similar to cocos.text.Label, a cocos.sprite.Sprite
        # is a subclass of pyglet.sprite.Sprite with the befits of
        # being a CocosNode.
        sprite = cocos.sprite.Sprite("hombrecaminando00001.png")
        
        # sprite in the center of the screen (default is 0,0)
        sprite.position = 320, 240

        myimage = "hombrecaminando2.gif"
        self.myaction = sprite.do(MoveTo((640, 480), 10) |
            PlaySound("offroad.wav", loop=True) |
            Animate(myimage, loop=True))

        # self.anotheraction = sprite.do()

        sprite.scale = 0.5
        # add the sprite as a child, but with z=1 (default is z=0).
        # this means that the sprite will be drawn on top of the label

        self.add(sprite, z=1)
        self.sprite = sprite

    def on_key_release(self, key, modifiers):
        mykey = pyglet.window.key.symbol_string(key)
        print("A key was pressed! Key: %s" % mykey)
        if mykey == "S" and self.myaction is not None:
            self.sprite.remove_action(self.myaction)
            self.myaction = None


if __name__ == "__main__":
    # director init takes the same arguments as pyglet.window
    cocos.director.director.init()

    # We create a new layer, an instance of HelloWorld
    hello_layer = HelloWorld()

    # tell the layer to perform a Rotate action in 10 seconds.
    # hello_layer.do(RotateBy(360, duration=10))

    # A scene that contains the layer hello_layer
    main_scene = cocos.scene.Scene(hello_layer)

    # And now, start the application, starting with main_scene
    cocos.director.director.run(main_scene)

    # or you could have written, without so many comments:
    #      director.run( cocos.scene.Scene( HelloWorld() ) )

Reply via email to