Another animation playing problem

In the “update” method of the execution file, the “*” position is set to traverse all enemies with a life value of 0, and then let them play the death animation. However, no matter how it is set, the animation stays in the first frame. Who can help me see what’s going on?

Here the file is the execution file,

-------------------------------------------game---------------------------------------------------
from Game_Configure7_9 import *
from direct.showbase.ShowBase import ShowBase
from direct.task import Task
story = '''Story
When codemao went out to find a gift 
for a small partner who liked it, a group 
of exotic animals would be able to take it 
away. Codemao finds where they hide, but 
it's hard to save a little, and use your 
ingenuity to help codemao!
'''
control = ''' Control 
w   ----   up
s   ----   down 
a   ----   left
d   ----   right
mouse_left ---- shoot

'''


class Game_Run(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        #self.disableMouse()
        self.player = 100
        self.configure = myConfigure(1400, 1000, 'map')
        self.configure.Window()
        self.text_1 = self.configure.Screen_Text(text_text=story,
                                                 pos_pos=(0, 0.75),
                                                 bg_bg=(0.7, 0.4, 0.8, 1),
                                                 scale_scale=0.1,)
        self.text_2 = self.configure.Screen_Text(text_text=control,
                                                 pos_pos=(0, 0),
                                                 bg_bg=(0.3, 0.6, 0.9, 1),
                                                 scale_scale=0.1)
        self.dialog_1 = self.configure.Dialog(frameSize_frameSize=(-0.5, 0.5, 0.1, -0.1),
                                              fadeScreen_fadeScreen=1,
                                              pos_pos=(0, 0, -0.8),
                                              color_color=(0.1, 0.9, 0.9, 1))
        self.button_1 = self.configure.Button(text_text='Start Game',
                                              parent_parent=self.dialog_1,
                                              command_command=self.Start,
                                              scale_scale=0.15,
                                              pos_pos=(0, 0, -0.05))
        self.dialog_1['frameTexture'] = 'brass.png'
        self.text_1['frame'] = (0.8, 0.6, 0.7, 1)
        self.text_2['frame'] = (0.8, 0.9, 0.7, 1)
        self.configure.Fence((-580, 0, 0, 580, 0, 0, 5), (0, 350, 0))
        self.configure.Fence((-580, 0, 0, 580, 0, 0, 5), (0, -350, 0))
        self.configure.Fence((0, -350, 0, 0, 350, 0, 5), (580, 0, 0))
        self.configure.Fence((0, -40, 0, 0, 350, 0, 5), (-580, 0, 0))
        self.configure.Fence((0, -150, 0, 0, -350, 0, 5), (-580, 0, 0))
        self.configure.Fence((-8, 0, 0, 8, 0, 0, 5), (33, 270, 0))
        self.configure.Fence((0, -8, 0, 0, 8, 0, 5), (20, 260, 0))
        self.configure.Fence((-8, 0, 0, 8, 0, 0, 5), (33, 250, 0))
        self.configure.Fence((0, -8, 0, 0, 8, 0, 5), (45, 260, 0))
        
        self.configure.Fence((-8, 0, 0, 8, 0, 0, 5), (-45, 310, 0))
        self.configure.Fence((0, -8, 0, 0, 8, 0, 5), (-58, 300, 0))
        self.configure.Fence((-8, 0, 0, 8, 0, 0, 5), (-45, 290, 0))
        self.configure.Fence((0, -8, 0, 0, 8, 0, 5), (-33, 300, 0))
        self.pusher = CollisionHandlerPusher()
        self.cTrav = CollisionTraverser()
        self.pusher.setHorizontal(True)
        self.state = {
            "up": False,
            "down": False,
            "left": False,
            "right": False,
            "shoot": False
        }
        self.accept('w', self.UpdateState, ['up', True])
        self.accept('w-up', self.UpdateState, ['up', False])
        self.accept('s', self.UpdateState, ['down', True])
        self.accept('s-up', self.UpdateState, ['down', False])
        self.accept('a',self.UpdateState, ['left', True])
        self.accept('a-up', self.UpdateState, ['left', False])
        self.accept('d', self.UpdateState, ['right', True])
        self.accept('d-up', self.UpdateState, ['right', False])
        self.accept('mouse1', self.UpdateState, ['shoot', True])
        self.accept('mouse1-up', self.UpdateState, ['shoot', False])

        # hLight = AmbientLight("ambient light")
        # hLight.setColor((0.1, 0.1, 0.1, 1))
        # self.hlnp = render.attachNewNode(hLight)
        # render.setLight(self.hlnp)
        self.pusher.add_in_pattern("%fn-into-%in")
        self.accept('player-into-needle', self.Attach)
        self.enemies = []
        self.maxEnemies = 4
        self.deadEnemies = []
        self.initialSpawnInterval = 1.0
        self.minimumSpawnInterval = 0.2
        self.spawnInterval = self.initialSpawnInterval
        self.spawnTimer = self.spawnInterval
        self.spawnPoints = [Vec3(0, 250, 0), Vec3(-250, 250, 0),Vec3(-250, -250, 0) ,
                            Vec3(250, -250, 0), Vec3(0, -250, 0),Vec3(250, 250, 0)]
        self.botime = 0.3
    def Attach(self,entry):
        self.playrt_health -= 1
        print("hello")

    def spawnEneny(self):
        if len(self.enemies) < self.maxEnemies:
            spawnPoint = random.choice(self.spawnPoints)
            print(spawnPoint)
            self.woodmen = Enemy_woodmen(spawnPoint)
            self.enemies.append(self.woodmen)


    def Start(self):
        self.text_1.destroy()
        self.text_2.destroy()
        self.dialog_1.hide()
        self.map_1 = self.configure.Map()
        self.player = Player()
        taskMgr.add(self.update, "update")
        # playerLight = PointLight("move light")
        # playerLight.setColor((1, 1, 1, 1))
        # playerLight.setAttenuation((0.6, 0.01, 0))
        # self.playerlnp = self.player.actor.attachNewNode(playerLight)
        # self.playerlnp.setPos(0,0,100)
        # render.setLight(self.playerlnp)
        base.camLens.setFov(60)
        self.needle = Enemy_needle()

    def UpdateState(self, controlName, controlState):
        self.state[controlName] = controlState
    def update(self, task):
        dt = globalClock.getDt()
        if self.player is not None:
            self.playrt_health = self.player.Health()
            self.needle.update(self.player,dt)
            self.spawnTimer -= dt
            if self.spawnTimer <= 0:
                self.spawnTimer = self.spawnInterval
                self.spawnEneny()
            [enemy.update(self.player, dt) for enemy in self.enemies]
            [self.player.update(self.state, enemy, dt) for enemy in self.enemies]
            newlyDeadEnemies = [enemy for enemy in self.enemies if enemy.health <= 0]
            #[self.enemies.remove(enemy)  for enemy in self.enemies if enemy.health <= 0]
            **for enemy in newlyDeadEnemies:**
**                enemy.actor.disableBlend()**
**                enemy.walking = False**
**                self.botime -= dt**
**                if self.botime <= 0:**
**                    enemy.actor.play("die")**
**                    print(enemy.actor.getAnimControl("die").isPlaying())**
**                    print('you die')**
**                self.player.score += 1**
**            self.deadEnemies += newlyDeadEnemies**
        
        return Task.cont

    def cleanup(self):
        for enemy in self.enemies:
            enemy.cleanup()
        self.enemies = []

        for enemy in self.deadEnemies:
            enemy.cleanup()
        self.deadEnemies = []
    
game = Game_Run()
game.run()

Here the file is the import file

----------------------------------------------game_configure--------------------------------------------------------
from panda3d.core import *
from panda3d.core import TextNode
from direct.gui.DirectGui import *
from direct.actor.Actor import Actor
import random

class myConfigure():
    def __init__(self, Width, Height, Model):
        self.width = Width
        self.height = Height
        self.model = Model
    def Window(self):
        self.window = WindowProperties()
        self.window.setSize(self.width, self.height)
        base.win.requestProperties(self.window)
    def Map(self):
        self.map = loader.loadModel(self.model)
        self.map.reparentTo(render)
        return self.map
    def Screen_Text(self, text_text='Welcome', pos_pos=(-0.8, 0.3), bg_bg=(0.6, 0.4, 0.3, 1), scale_scale=0.1,):
        self.text = OnscreenText(text=text_text,
                                 pos=pos_pos,
                                 bg=bg_bg,
                                 scale=scale_scale,
                                 wordwrap=25)
        return self.text
    def Dialog(self, frameSize_frameSize, fadeScreen_fadeScreen, pos_pos, color_color):
        self.dialog = DirectDialog(frameSize=frameSize_frameSize,
                                   fadeScreen=fadeScreen_fadeScreen,
                                   relief=DGG.FLAT)
        self.dialog.setPos(pos_pos)
        self.dialog.setColor(color_color)
        return self.dialog
    def Button(self, text_text, parent_parent, command_command, scale_scale, pos_pos):
        self.button = DirectButton(text=text_text,
                                   parent=parent_parent,
                                   command=command_command,
                                   scale=scale_scale,
                                   pos=pos_pos)
        return self.button
    def Fence(self, size, pos_pos):
        fenceSolid = CollisionTube(size[0], size[1], size[2], size[3], size[4], size[5], size[6])
        fenceNode = CollisionNode("fence")
        fenceNode.addSolid(fenceSolid)
        fence = render.attachNewNode(fenceNode)
        fence.setPos(pos_pos)


class ActorObject():
    def __init__(self, pos, modelName, modelAnims, maxHealth, maxSpeed, modelScale, colliderName):
        self.actor = Actor(modelName, modelAnims)
        self.actor.reparentTo(render)
        self.actor.setPos(pos)
        self.actor.setScale(modelScale)
        self.maxHealth = maxHealth
        self.health = maxHealth
        self.maxspeed = maxSpeed
        self.walking = False
        capsule = CollisionSphere(0, 0, 0, 10)
        colliderNode = CollisionNode(colliderName)
        colliderNode.addSolid(capsule)
        self.collider = self.actor.attachNewNode(colliderNode)
        self.PoAcc = 0
        self.NeAcc = 550.0
        self.velocity = Vec3(0, 7, 0)
    def move(self,dt):
        speed = self.velocity.length()
        if speed > self.maxspeed:
            self.velocity.normalize()
            self.velocity *= self.maxspeed
            speed = self.maxspeed
        if not self.walking:
            respeed = self.NeAcc * dt
            if respeed > speed:
                self.velocity = Vec3(0, 0, 0)
            else:
                respeeda = -self.velocity
                respeeda.normalize()
                respeeda *= respeed
                self.velocity += respeeda
        self.actor.setPos(self.actor.getPos() + self.velocity * dt)
    def alterHealth(self,dHeanth):
        self.health += dHeanth
        if self.health > self.maxHealth:
            self.health = self.maxHealth

    def cleanup(self):
        if self.collider is not None and not self.collider.isEmpty():
            base.cTrav.removeCollider(self.collider)
            base.pusher.removeCollider(self.collider)

        if self.actor is not None:
            self.actor.cleanup()
            self.actor.removeNode()
            self.actor = None

        self.collider = None
class Player(ActorObject):
    def __init__(self):
        ActorObject.__init__(self,
                             (-50, 0, 0),
                             "codemao",
                             {
                                 "walk": "codemao_walk",
                                 "stand":"codemao_stand"
                             },
                             5,
                             20,
                             0.4,
                             'player'
                             )

        base.pusher.addCollider(self.collider, self.actor)
        base.cTrav.addCollider(self.collider, base.pusher)
        #print(self.collider)

        self.ray = CollisionRay(0, 0, 0, 0, -1, 0)
        rayNode = CollisionNode("playerRay")
        rayNode.addSolid(self.ray)
        self.rayCollision  = self.actor.attachNewNode(rayNode)
        #self.rayCollision .show()
        self.rayQueue = CollisionHandlerQueue()
        base.cTrav.addCollider(self.rayCollision , self.rayQueue)


        mask = BitMask32()
        mask.setBit(1)
        self.collider.node().setIntoCollideMask(mask)
        mask = BitMask32()
        mask.setBit(1)
        mask.setBit(5)
        self.collider.node().setFromCollideMask(mask)

        mask = BitMask32()
        mask.setBit(2)
        rayNode.setFromCollideMask(mask)
        mask = BitMask32()
        rayNode.setIntoCollideMask(mask)


        self.laser_weapon = loader.loadModel("laser")
        self.laser_weapon.reparentTo(self.actor)
        self.laser_weapon.setPos(-30,0,40)
        self.laser_weapon.setLightOff()
        self.laser_weapon.hide()
        self.attackWaitTimer = 0.2
        self.Hue = -2

        #生命值
        self.score = 0
    def updateScore(self):
        return self.score

    def alterHealth(self,dHealth):
        ActorObject.alterHealth(self,dHealth)
    def Health(self):
        return self.health

    def update(self, keys,woodmen,dt):
        ActorObject.move(self,dt)
        self.acceleration = 200
        self.walking = False
        if keys["up"]:
            self.walking = True
            self.velocity.addY(self.acceleration*dt)
            base.cam.setPos(self.actor.getPos() + (0, -220, 80))
            self.actor.setH(180)
            base.cam.setH(self.actor.getH()+180)
        if keys["down"]:
            self.walking = True
            self.velocity.addY(-self.acceleration*dt)
            base.cam.setPos(self.actor.getPos() + (0, 220, 80))
            self.actor.setH(0)
            base.cam.setH(self.actor.getH() + 180)
        if keys["left"]:
            self.walking = True
            self.velocity.addX(-self.acceleration*dt)
            base.cam.setPos(self.actor.getPos() + (220, 0, 80))
            self.actor.setH(270)
            base.cam.setH(self.actor.getH()+180)
        if keys["right"]:
            self.walking = True
            self.velocity.addX(self.acceleration*dt)
            base.cam.setPos(self.actor.getPos() + (-220, 0, 80))
            self.actor.setH(90)
            base.cam.setH(self.actor.getH() + 180)
        if self.walking:
            walkControl = self.actor.getAnimControl("walk")
            if not walkControl.isPlaying():
                self.actor.loop("walk")
        else:
            self.actor.stop("walk")
            self.actor.loop("stand")
        if keys["shoot"]:
            if self.rayQueue.getNumEntries() > 0:
                self.rayQueue.sortEntries()
                rayHit = self.rayQueue.getEntry(0)
                hitPos = rayHit.getSurfacePoint(render)
                beamLength = (hitPos -self.actor.getPos() ).length()
                self.laser_weapon.setSy(beamLength)
                self.laser_weapon.show()
                if self.rayQueue.getEntry(0).getIntoNodePath() == woodmen.collider and self.attackWaitTimer > 0:
                    self.attackWaitTimer -= dt
                    if self.attackWaitTimer <= 0:
                        self.attackWaitTimer = random.uniform(0.1, 0.2)
                        if woodmen.health > 0:
                            woodmen.alterHealth(self.Hue)
        else:
            self.laser_weapon.hide()

class Enemy_woodmen(ActorObject):
    def __init__(self,pos):
        ActorObject.__init__(self,
                             pos,
                             "woodmen",
                             {
                                 "walk": "woodmen_walk",
                                 "stand": "woodmen_stand",
                                 "die":"woodmen_die",
                                 "attack":"woodmen_shoot"
                             },
                             5,
                             50,
                             0.8,
                             'wood'
                             )

        mask = BitMask32()
        mask.setBit(2)
        mask.setBit(5)
        self.collider.node().setIntoCollideMask(mask)

        mask = BitMask32()
        mask.setBit(1)
        mask.setBit(5)
        self.collider.node().setFromCollideMask(mask)
        base.pusher.addCollider(self.collider, self.actor)
        base.cTrav.addCollider(self.collider, base.pusher)

        self.detectiondistance = 100
        self.acceleration = 100
        self.standard  = Vec2(0, 1)
        self.attackWaitTimer = 0.3
        self.Hue = -2
        self.search_speed = Vec3(0, 50, 0)
        self.varyangle = Vec2(0, 1)
        self.changeWaitTimer = 0.1
        self.change = True
        self.changeQueue = CollisionHandlerQueue()
        base.cTrav.addCollider(self.collider, self.changeQueue)

    def alterHealth(self,dHeanth):
        ActorObject.alterHealth(self, dHeanth)


    def update(self,player,dt):
        ActorObject.move(self, dt)
        position_vevtor = player.actor.getPos() - self.actor.getPos()
        position_vevtor2D = position_vevtor.getXy()
        distanceToplayer = position_vevtor2D.length()
        position_vevtor2D.normalize()
        print('wood',self.health)
        self.actor.enableBlend()
        if self.changeQueue.getNumEntries() > 0 and self.change:
                self.search_speed = -self.search_speed
                self.varyangle = -self.varyangle
                self.change = False
                self.changeWaitTimer = 0.05
        else:
            self.changeWaitTimer -= dt
            if self.changeWaitTimer <= 0:
                self.changeWaitTimer = random.uniform(0.05, 0.06)
                self.change = True
        if distanceToplayer > self.detectiondistance:
            self.walking = True
            self.heading = self.standard.signedAngleDeg(self.varyangle)
            self.velocity = self.search_speed
            self.actor.setControlEffect('walk', 0.7)
            self.actor.setControlEffect('attack', 0.3)
        elif distanceToplayer < self.detectiondistance and distanceToplayer > 30:
            self.heading = self.standard.signedAngleDeg(position_vevtor2D)
            self.maxspeed = 50
            self.walking  = True
            self.actor.setPlayRate(2, 'walk')
            self.velocity = position_vevtor * 2
            self.actor.setControlEffect('walk', 0.9)
            self.actor.setControlEffect('attack', 0.1)
            print(111,distanceToplayer)
        elif self.attackWaitTimer > 0 and distanceToplayer <= 30:
            self.actor.disableBlend()
            self.heading = self.standard.signedAngleDeg(position_vevtor2D)
            self.walking = False
            self.actor.setPlayRate(0.3, 'attack')
            self.attackWaitTimer -= dt
            if self.attackWaitTimer <= 0  :
                self.attackWaitTimer = random.uniform(0.5, 0.7)
                self.actor.play('attack')
                player.alterHealth(self.Hue)
        if self.walking:
            walkingControl = self.actor.getAnimControl("walk")
            if not walkingControl.isPlaying():
                self.actor.loop("walk")
                self.actor.loop("attack")
        self.actor.setH(self.heading + 180)

    def cleanup(self):
        ActorObject.cleanup(self)
class Enemy_needle(ActorObject):
    def __init__(self):
        ActorObject.__init__(self,
                             (270, 0, -2),
                             "GroundNeedle",
                             {
                                 "motion": "GroundNeedle_motion",
                                 "stop": "GroundNeedle_stop",
                             },
                             5,
                             0,
                             0.5,
                             'needle'
                             )
        self.hueQueue = CollisionHandlerQueue()
        base.cTrav.addCollider(self.collider, self.hueQueue)
        mask = BitMask32()
        mask.setBit(5)
        self.collider.node().setIntoCollideMask(mask)
        mask = BitMask32()
        mask.setBit(1)
        self.collider.node().setFromCollideMask(mask)
        needlenode = NodePath('needlelist')
        for i in range(-220,-50,20):
            self.needle = needlenode.attachNewNode('needle')
            self.needle.setPos(40,i,0)
            self.actor.instanceTo(self.needle)
        for i in range(50,220,20):
            self.needle = needlenode.attachNewNode('needle')
            self.needle.setPos(80,i,0)
            self.actor.instanceTo(self.needle)
        needlenode.reparentTo((render))
        self.actor.loop("motion")
        self.attackWaitTimer = 0.2
        self.Hue = -0.2
        needleSolid_1 = CollisionTube(0,220,0,0,40,0,5)
        needleNode_1 = CollisionNode("needle")
        needleNode_1.addSolid(needleSolid_1)
        needle_1 = render.attachNewNode(needleNode_1)
        needle_1.setPos(350,0,0)
        needleSolid_2 = CollisionTube(0, -230, 0, 0, -50, 0, 5)
        needleNode_2 = CollisionNode("needle")
        needleNode_2.addSolid(needleSolid_2)
        needle_2 = render.attachNewNode(needleNode_2)
        needle_2.setPos(310, 0, 0)
        mask = BitMask32()
        needleNode_1.setIntoCollideMask(mask)
        mask = BitMask32()
        mask.setBit(1)
        needleNode_2.setFromCollideMask(mask)
        mask = BitMask32()
        needleNode_2.setIntoCollideMask(mask)
        mask = BitMask32()
        mask.setBit(1)
        needleNode_2.setFromCollideMask(mask)
        base.cTrav.addCollider(needle_1, self.hueQueue)
        base.cTrav.addCollider(needle_2, self.hueQueue)

    def update(self,player,dt):
        if self.hueQueue.getNumEntries() > 0:
            self.hueQueue.sortEntries()
            if self.hueQueue.getEntry(0).getIntoNodePath() == player.collider and self.attackWaitTimer >0 :
                self.attackWaitTimer -= dt
                if self.attackWaitTimer <= 0:
                    self.attackWaitTimer = random.uniform(0.1, 0.2)
                    player.alterHealth(self.Hue)

I forgot to add the reset of “self. Botime” above, but even if I reset it. The animation will not play.

I think that the problem may be that you’re not removing the “newly-dead” enemies from the main enemy-list. As a result, the code keeps detecting the same “newly-dead” enemies across multiple frames, and thus keeps restarting the death animation.

What I’d suggest is that, after finding the newly-dead enemies, you reconstruct the “self.enemies” list so that it only contains living enemies. That way you should find each dead enemy only once, and thus play its death-animation only once.

OK, I have found the answer in your example, as you said, it has been solved!

1 Like