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() ) )