First of all, thank you for posting only the relevant code! It’s much appreciated–and I think that it helped me to quickly find the problem!
As to that problem, you didn’t specify quite what was happening–does the looping of the “attack” animation work? Is it, as I’m currently guessing, just the “explode” animation that doesn’t work?
If so, what I think is happening is this:
In “checkMonsterDead”, you’re playing the “explode” animation–and then immediately destroying the Actor-object and removing its node. As a result, the animation never has a chance to play.
What I’d suggest is that you keep your Actors around until the “explode” animation has finished playing, and only then run the cleanup-and-remove code.
(You can check whether a given animation is playing by getting the “animation control” associated with that animation–by calling “getAnimControl(<name-of-animation-here>)”–and then calling “isPlaying” on that control.)
What I’d suggest is simply storing the Actor somewhere, and checking on its animation in a task.
A “while” likely won’t work here: unless you get into asynchronous programming, a while-loop will presumably execute all of its iterations within a single frame; you want the animation to play out over multiple frames.
(I’m presuming that you would call self.monster.actor.play("explode") just before.)
The program would reach the “while”-statement. It would check the associated condition, which is whether the control is playing, and see that it is.
Since the condition is “True”, it would thus enter the “while”-section, encounter the “pass” statement, and move on.
However, this is a “while”-loop. Since the condition was “True”, it would return to the start of the “while”-loop. Once again, it would check the condition.
Now, all of this is happening in a single frame–since the program hasn’t yet moved on, the engine hasn’t yet had a chance to finish the frame and start the next one. As a result, the animation hasn’t yet updated at all–nothing has changed.
Thus the animation is still playing, and the condition is still “True”, and the program enters the “while”-loop.
And it’ll keep doing that until either the program is stopped, or the computer shuts down, I imagine.
I mean, it’s saying that because you literally posted the same text twice.
Honestly, how long have you spent trying to figure it out thus far? It’s been less than an hour, at least some of which was spent with one or the other of us typing responses.
Think about it some more, try and figure it out. I honestly think that you’ll learn more that way, and it’s good practice, and once again I feel like you’re asking me to do your work for you. Not to mention that I have my own work to attend to.
By the way, my “Beginner’s Tutorial” covers a bunch of the things that you’ve been asking about of late–off the top of my head: “pusher”-based collision; ray-collision with a queue; and the handling of enemy animations (as in this thread). Furthermore, it includes both description and code. I really do think that it might be useful to you.
If you’re interested, I’d suggest going through it from the start–even the bits that you’re already familiar with, so that you don’t inadvertently miss some item that you’re not familiar with.
I tried what came to my mind. But I have 2 issues. If I don’t use the “explode” animation, it removes the node nicely. Issues:
When I use the "explode" animation it still doesn't play
Even though it doesn't play, the node is removed, but not properly. There is still collision detection for the monster
def checkMonsterDead(self, task):
if self.monster.health <= 0:
if not self.monster.actor.getAnimControl("explode").isPlaying():
Okay, I think that what’s happening when you play the “explode” animation is a little non-obvious: I think that it is playing… but because you’re calling “play” on every frame after the monster “dies”, the animation is being reset to the beginning on every frame, and so appears to never play.
What I’d suggest is that you store a new value in your monster-class, something like “isAlive”, which is set to “True” when the monster is created, and which is set to “False” when the monster dies (i.e. just after checking that its health is less-than-or-equal-to zero).
You can then use this value to differentiate between a monster that has just died (because its value is still “True”) and one that died previously (because its value is already “False”). This way you can play the animation only for a monster that has just died, meaning that it shouldn’t be reset.
As to collision-detection, hmm, that’s odd! However, I do think that it’s probably good practice to remove collision-items from the traverser and pusher when they’re no longer being used anyway, and doing so might fix the problem.
And just in case you missed it, please see my previous post, above, about the tutorial.
If I may add, this can also be handled using an Interval:
You could make a Sequence containing an Actorinterval and then a Func that will call actor destroy afterwards. So from that function you can just set up the Sequence and start() it and it’ll run on its own.