A weapon that can't hit anything isn't much good to us. In order to hit things, we need to use collision detection. Let's go ahead and add collision detection to our MachineGun class so we can shoot some things in the scene.

  1. Before we start going hog wild with this, let's create a small explosion effect to use when the laser strikes something. Open a new file and save it as ExplosionClasses_01.py.
  2. Place these imports at the top of the file:
    from direct.interval.IntervalGlobal import *
    import random
    
  3. Add the class definition and the __init__ method as follows:
    class Pop:
    def __init__(self, pos):
    rand = random.randint(1,3)
    self.pop = loader.loadModel(
    "../Models/Explosions/Laserburst" + str(rand) + ".bam")
    self.pop.reparentTo(render)
    self.pop.setPos(pos)
    self.pop.find('**/+SequenceNode').node().play(0, 15)
    self.self = self
    self.seq = Sequence(
    Wait(.5),
    Func(self.destroy))
    
  4. Now, we just need a destroy() method to clean up after the explosion is finished:
    def destroy(self):
    self.pop.removeNode()
    self.self = None
    return
    
  5. Resave the file; we're done there. Next, open GunClasses_01.py.
  6. Add this line to our section of imports:
    from ExplosionClasses_01 import *
    
  7. Add this new variable to the __init__ method, right underneath our declaration of reloadTime:
    self.damage = 10
    
  8. Next, change the declaration of self.firePar so that it looks like the following code:
    self.firePar = Parallel(
    Func(self.checkForHit),
    Func(self.setEffects),
    self.flashLerp)
    
  9. Scroll down to the fire() method. Remove the line that repositions self.refNP; we won't need it anymore.
  10. Add this new method below the clearEffects() method. It will employ a CollisionRay we're going to add to the Cycle class to check if the laser hit anything.
    def checkForHit(self):
    self.cycle.trgtrCTrav.traverse(render)
    if(self.cycle.trgtrCHan.getNumEntries() > 0):
    self.cycle.trgtrCHan.sortEntries()
    entry = self.cycle.trgtrCHan.getEntry(0)
    colPoint = entry.getSurfacePoint(render)
    self.refNP.setPos(render, colPoint)
    pop = Pop(colPoint)
    thingHit = entry.getIntoNodePath()
    if(thingHit.hasPythonTag("owner")):
    thingHit.getPythonTag("owner").hit(self.damage)
    else:
    self.refNP.setPos(self.cycle.trgtrCNP, 0, 300, 0)
    pop = Pop(self.cycle.refNP.getPos(render))
    
  11. That's it for this file. Resave it as GunClasses_02.py.
  12. Open CycleClass_02.py and update the imports to use the new file for our gun class.
  13. Add the following code to the bottom of the setupCollisions() method:
    self.trgtrCN = CollisionNode(self.name + "_TargeterCN")
    self.trgtrRay = CollisionRay(0,0,0,0,1,0)
    self.trgtrCN.addSolid(self.trgtrRay)
    self.trgtrCN.setFromCollideMask(BitMask32.bit(3))
    self.trgtrCN.setIntoCollideMask(BitMask32.allOff())
    self.trgtrCNP = self.trgtrMount.attachNewNode(self.trgtrCN)
    self.trgtrCTrav = CollisionTraverser()
    self.trgtrCHan = CollisionHandlerQueue()
    self.trgtrCTrav.addCollider(self.trgtrCNP, self.trgtrCHan)
    
  14. We'll also add a method that the cycle will perform when it gets hit by something that deals damage. Add this method right below the bump() method since it's a similar sort of method to bump:
    def hit(self, damage):
    print(self.name + " has taken " + str(damage) + " damage!")
    return
    
  15. Lastly, scroll down to the destroy() method and add the following line right under the line that removes gRayCNP to clean up the new CollisionRay we've created:
    self.trgtrCNP.removeNode()
    
  16. That's everything in this file. Resave it as CycleClass_03.py.
  17. Update RaceClass_01.py to use CycleClass_03.py, and then resave it as RaceClass_02.py.
  18. Update WorldClass_01.py to use RaceClass_02.py, and then resave it as WorldClass_02.py.
  19. Run WorldClass_02.py from the command prompt. Try and shoot the AI cycles as they drive past, and try shooting the ground as well.
Time for action - adding collision detection to the MachineGun