Collision Detection Problem (Bullet through paper)

I have a bunch of planets flying towards me and my ship shoots bullets. I’m using a LerpInterval to make the bullet travel into the far Z plane. The problem is that my bullets seem to randomly go through collision objects and I don’t know why. Any ideas on how to make the collision check every frame or slow down my projectiles so they always get checked?

Here’s some code.

def generateObstacles(self):
  self.obstacleOldPos = [None for i in range(40)]
  self.obstacle = [None for i in range(40)]
  for i in range(len(self.obstacle)):
    self.obstacle[i] = loader.loadModelCopy("models/planet_sphere")
    self.obs_tex  = loader.loadTexture("models/sun_1k_tex.jpg")
    self.obstacle[i].setTexture(self.obs_tex, 1)
    self.obstacle[i].reparentTo(render)
    self.obstacle[i].setScale(.1)
    self.obstacle[i].setPos(generateRandomFloat(),generateRandomFloat(), random.randint(-100, -20))
    #print "obstacle position "+str(self.obstacle[i].getPos())
    self.obstacleOldPos[i]=self.obstacle[i].getPos()
    
    #Create collision for the obstacles
    obstacleCS = CollisionSphere(0, 0, 0, 1.1)
    obstaclePath = self.obstacle[i].attachNewNode(CollisionNode('obstacle'))     
    obstaclePath.node().addSolid(obstacleCS)
    #obstaclePath.show()

and

  def shootObstacle(self, time):
    self.laserSound.play()
    pos = self.ship.getPos()
    bullet = loader.loadModelCopy("models/planet_sphere")  #Create the object
    self.bullet_tex = loader.loadTexture("models/mars_1k_tex.jpg")
    bullet.setTexture(self.bullet_tex, 1)
    bullet.reparentTo(render)
    bullet.setScale(.05)
    bullet.setPos(pos)
    #Set the bullet expiration time to be a certain amount past the current time
    self.setExpires(bullet, time + 1.1)
    self.bulletSeq = Sequence(
        LerpFunc(bullet.setZ,
               duration = 1,
               fromData = bullet.getZ(),
               toData = bullet.getZ()-40))
    #print "loop pos "+str(self.obstacle[i].getPos())+" for "+str(i)
    self.bulletSeq.start()
    #print str(bullet.getPos())+" bullet"
    #Finally, add the new bullet to the list
    self.bullets.append(bullet)
    bulletMask = BitMask32.bit(3)
    #create a collsion solid for this model
    bulletNode1 = CollisionNode('bulletPush')
    bulletNode1.addSolid(CollisionSphere(0,0,0,1.2))
    bulletNode1.setIntoCollideMask(BitMask32.allOff())
    bulletNode1.setFromCollideMask(BitMask32.bit(0))
    bulletC1 = bullet.attachNewNode(bulletNode1)
    #bulletC1.show()
    #create another collsion solid for this model
    bulletNode2 = CollisionNode('bulletEvent')
    bulletNode2.addSolid(CollisionSphere(0,0,0,1.3))
    bulletNode2.setIntoCollideMask(BitMask32.allOff())
    bulletNode2.setFromCollideMask(bulletMask)
    bulletC2 = bullet.attachNewNode(bulletNode2)
    #bulletC2.show()
    self.pusher.addCollider(bulletC1, bullet)
    base.cTrav.addCollider(bulletC1, self.pusher)
    base.cTrav.addCollider(bulletC2, self.cHandler)

Thanks.

You will need to turn on fluid collision detection. This also means you will need to use CollisionPolygons for your planet targets, instead of CollisionSpheres (but you should continue to use CollisionSpheres for your bullets).

It’s all described here in the manual: http://panda3d.org/manual/index.php/Rapidly-Moving_Objects

David

Ok, cool. I’m not sure how to set up a CollisionPolygon. It takes in 4 Point3() values, but how do I determine which values to pass?

Also, it states that the collision traverser checks every frame. I can definitely see the bullet hitting the planet and penetrating it. I’m not sure what would cause this. When I show the collision meshes, it looks fine. Also, if I sit in the same spot and shoot multiple bullets, eventually it’ll cause a hit.

Your object moves with a speed of the form world-units/frame.

Let’s say you’ve got an object that’s just 1 world-unit thick and a bullet that moves 2 world units per frame.
Then the chances are great that your bullet will never even touch the position of your object, hence normal collision detection couldn’t detect it.
That’s what fluid collision detection is for. It takes into account where your bullet was in the frame before and triggers a collision event, if the bullet must have passed the object, even if it didn’t hit it directly.

I get how it works but I have no idea how to set it up. I can’t find any examples of fluid collision detection except for what’s in the manual and even that doesn’t explain how to fully set it up.

Here’s my updated shootObstacle code

def shootObstacle(self, time):
    #self.laserSound.play()
    pos = self.ship.getPos()
    bullet = loader.loadModelCopy("models/missile")  #Create the object
    #self.bullet_tex = loader.loadTexture("models/mars_1k_tex.jpg")
    #bullet.setTexture(self.bullet_tex, 1)
    bullet.reparentTo(render)
    bullet.setScale(.005)
    bullet.setPos(pos)
    bullet.setP(-270)
    #print str(len(self.bullets))+" bullets"
    if (self.particleEffects > 45):
	    self.particleEffects = 0
	    self.effects[self.particleEffects].setPos(bullet.getPos())
	    self.effects[self.particleEffects].setZ(self.effects[self.particleEffects].getZ()-3)
	    self.effects[self.particleEffects].reparentTo(bullet)
	    #self.effects[self.particleEffects].start()
	    self.particleEffects += 1
    else:
	    self.effects[self.particleEffects].setPos(bullet.getPos())
	    self.effects[self.particleEffects].setZ(self.effects[self.particleEffects].getZ()-3)
	    self.effects[self.particleEffects].reparentTo(bullet)
	    self.effects[self.particleEffects].start()
	    self.particleEffects += 1
    #self.effect.setPos(bullet.getPos())
    #self.effect.reparentTo(bullet)
    #self.effect.start()
    #Set the bullet expiration time to be a certain amount past the current time
    self.setExpires(bullet, time + 3.1)
    endPos = bullet.getPos()
    endPos.setZ(endPos.getZ()-30)
    self.bulletSeq = Sequence(
        LerpPosInterval(bullet,
               duration = 2.5,
	       pos = endPos,
	       fluid = 1))
               #fromData = bullet.getZ(),
               #toData = bullet.getZ()-40), fluid=1)
    #print "loop pos "+str(self.obstacle[i].getPos())+" for "+str(i)
    self.bulletSeq.start()
    #print str(bullet.getPos())+" bullet"
    #Finally, add the new bullet to the list
    self.bullets.append(bullet)
    bulletMask = BitMask32.bit(3)
    #create a collsion solid for this model
    bulletNode1 = CollisionNode('bulletPush')
    bulletNode1.addSolid(CollisionSphere(0,0,0,1.2))
    bulletNode1.setIntoCollideMask(BitMask32.allOff())
    bulletNode1.setFromCollideMask(BitMask32.bit(0))
    bulletC1 = bullet.attachNewNode(bulletNode1)
    #bulletC1.show()
    #create another collsion solid for this model
    bulletNode2 = CollisionNode('bulletEvent')
    bulletNode2.addSolid(CollisionSphere(0,0,0,1.3))
    bulletNode2.setIntoCollideMask(BitMask32.allOff())
    bulletNode2.setFromCollideMask(bulletMask)
    bulletC2 = bullet.attachNewNode(bulletNode2)
    #bulletC2.show()
    self.pusher.addCollider(bulletC1, bullet)
    base.cTrav.addCollider(bulletC1, self.pusher)
    base.cTrav.addCollider(bulletC2, self.cHandler)

Tried to set up a collisionPolygon solid but it doesn’t work. I have no idea how to properly make one and the one I did I tried to ram into the missiles and nothing happened. I’m having my obstacles (enemy ships) shoot at me. The problem is it’s very hard to get hit by them even though they pass right through.

Makes no sense.

You could try to make your bullets “larger”.
I guess, you’re using CollisionSpheres for your bullets (I think I’ve read that spheres won’t work with fluid collision detection…).
Instead of using spheres, you could try using a CollisionRaySegment as the bullet.
You can then adjust the length of your CollisionRaySegment to ensure proper collision detection.