CollisionEvent issues

“again” events are not generated in my program.
Code:

from direct.showbase.ShowBase import ShowBase
from direct.actor.Actor import Actor
from direct.task import Task
from direct.gui.OnscreenText import OnscreenText
from panda3d.core import *
from classes import *
loadPrcFile("config/config.prc")

class Game(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        
        self.disableMouse()
        
        self.cTrav = CollisionTraverser()
        self.pusher = CollisionHandlerPusher()
        self.pusher.addInPattern("%fn-into-%in")
        self.pusher.addAgainPattern("%fn-again-%in")
        self.pusher.addOutPattern("%fn-outof-%in")
        self.pusher.setHorizontal(True)
        
        self.room = self.loader.loadModel("models/room.egg")
        self.room.setH(270)
        self.room.reparentTo(self.render)
        
        self.player = Player(Point3(0, -20, 2))
        
        self.keyMap = {"w" : False, "a" : False, "s" : False, "d" : False, "arrow_left" : False, "arrow_right" : False}
        
        for key in self.keyMap:
            self.accept(key, self.updateKeyMap, [key, True])
            self.accept(key + "-up", self.updateKeyMap, [key, False])
        
        self.taskMgr.add(self.update, "update")
        
        wallNode = CollisionNode("wall")
        wallSolid = CollisionCapsule(-4, -6, 1, -1, -6, 1, 0.5)
        wallNode.addSolid(wallSolid)
        wallC = render.attachNewNode(wallNode)
        
        wallNode = CollisionNode("wall")
        wallSolid = CollisionPlane(Plane(Vec3(1, 0, 0), Point3(-5, 0, 2)))
        wallNode.addSolid(wallSolid)
        wallC = render.attachNewNode(wallNode)
        
        wallNode = CollisionNode("wall")
        wallSolid = CollisionPlane(Plane(Vec3(0, 1, 0), Point3(6, -15, 2)))
        wallNode.addSolid(wallSolid)
        wallC = render.attachNewNode(wallNode)
        
        wallNode = CollisionNode("wall")
        wallSolid = CollisionPlane(Plane(Vec3(-1, 0, 0), Point3(5, -5, 2)))
        wallNode.addSolid(wallSolid)
        wallC = render.attachNewNode(wallNode)
        
        wallNode = CollisionNode("wall")
        wallSolid = CollisionPlane(Plane(Vec3(0, -1, 0), Point3(-3, 5, 2)))
        wallNode.addSolid(wallSolid)
        wallC = render.attachNewNode(wallNode)
        
        self.monster = Actor("models/monster1.egg", {"attack" : "models/monster1-pincer-attack-both.egg", "explode" : "models/monster1-explode.egg"})
        self.monster.setScale(0.25, 0.25, 0.25)
        self.monster.reparentTo(self.render)
        
        monsterCenter = self.monster.getBounds().getCenter()
        monsterRad = 2
        monsterNode = CollisionNode("monster")
        monsterNode.addSolid(CollisionSphere(monsterCenter, monsterRad))
        monsterC = self.monster.attachNewNode(monsterNode)
           
        self.cTrav.addCollider(monsterC, self.pusher)
        self.pusher.addCollider(monsterC, self.monster)
        
        self.healthText = OnscreenText("Health: " + str(self.player.health), pos=(-1.1, 0.9), scale=0.07, mayChange=True)
        
        self.accept("monster-into-player", self.handleHealth, [True])
        self.accept("monster-into-player", self.handleHealth, [True])
        self.accept("monster-into-player", self.handleHealth, [False])
        
        self.taskMgr.add(self.checkGameOver, "Check Game Over")
        
        #self.accept("p", self.printPos)
        
    """def printPos(self):
        print(self.camera.getPos())"""
    
    def handleHealth(self, collisionEntry, param): # I don't know what to call the parameter
        if param:
            self.player.health -= 1
            self.healthText.setText("Health: " + str(self.player.health))
    
    def checkGameOver(self, task):
        if self.player.health <= 0:
            gameOverText = OnscreenText("GAME OVER", pos=(0, 0), scale=0.25)
             
        return Task.cont
            
    def updateKeyMap(self, key, value):
        self.keyMap[key] = value
        
    def update(self, task):
        dt = globalClock.getDt()
        
        self.player.update(self.keyMap, dt)
            
        self.monster.lookAt(self.player.player)
        self.monster.setY(self.monster, dt * 5)
        
        return Task.cont
        
game = Game()
game.run()

It is only decreasing health on the “into” event, not “again”.

EDIT: The again event is only recorded when the camera is colliding with the wall.

It looks like the problem lies in your accepting of the events: you’re accepting the “into”-event three times, and never accepting the “again” or “outof” events.

Sorry. It was a copy-paste mistake.

1 Like

Not a problem! It works now, I take it?

Yes it works. But I think again is overpowering for the monster (unless I increase the player’s health). So I removed it.

That’s fair! Experimentation is often part of the process, I think. :slight_smile:

Now I have an issue in which when I use “into”, it is acting like “again”. When “into” is present, it continues decreasing the health.

May I see your revised code, please?

I fixed the problem by removing the “outof” event. But, there is only one problem. When I am colliding with the wall, and also the monster, the health is reducing rapidly.

1 Like

I think that the problem is that, once again, you’re not applying the delta-time for the frame, and thus are dealing more damage the higher the frame-rate.

Although I’m not sure of why you’re getting events from the wall, since I don’t see a corresponding “accept” call.

I’m guessing that you’re seeing multiple events because your objects are rapidly moving into and out of each other. This may be a result of using a “CollisionHandlerPusher”, which could be preventing the objects from intersecting (which is its purpose), resulting in their repeatedly “bumping into” each other.