Fortunately, we'll be able to do a good bit of copying and pasting code we've already written to make the main cannon. Let's get started.
ExplosionClasses_01.py
. The first thing we'll do is to make a new kind of explosion for the main cannon.from pandac.PandaModules import *
Pop
class and paste it into the bottom of the file. Change the class name to Boom
, and use the find and replace feature of Notepad++ to change self.pop
into self.boom
everywhere it appears in the Boom
class. __init__
method for the Boom
class to look like this:def __init__(self, pos, scale, damage):
__init__
method of the Boom
class, immediately after self.boom.setPos(pos):
self.boom.setScale(scale)
Boom
class's __init__
method, add the following block of code:self.boomCN = CollisionNode("BoomCN") self.boomCS = CollisionSphere(0,0,0,scale) self.boomCN.addSolid(self.boomCS) self.boomCN.setIntoCollideMask(BitMask32.allOff()) self.boomCN.setFromCollideMask(BitMask32.bit(4)) self.boomCNP = render.attachNewNode(self.boomCN) self.boomCNP.setPos(pos) self.boomCTrav = CollisionTraverser() self.boomCHan = CollisionHandlerQueue() self.boomCTrav.addCollider(self.boomCNP, self.boomCHan) self.checkCollision(damage)
checkCollision()
method we just put in a call to. Put this method right above the destroy()
method in the Boom
class:def checkCollision(self, damage): cyclesDamaged = [] self.boomCTrav.traverse(render) if(self.boomCHan.getNumEntries() > 0): for E in range(self.boomCHan.getNumEntries()): entry = self.boomCHan.getEntry(E) cycleHit = entry.getIntoNodePath().getPythonTag("owner") if(cycleHit not in cyclesDamaged): cycleHit.hit(damage) cyclesDamaged.append(cycleHit)
destroy()
method to clean up the collision sphere we made. Add this line, right after self.boom.removeNode():
self.boomCNP.removeNode()
ExplosionClasses_02.py
and we're done with it. Next, open GunClasses_02.py
. MachineGun
class and paste it into the bottom of the file. Change the name of this new class to Cannon
. __init__
method where we load the Actor
and model for the gun to look similar to the following code:self.actor = Actor("../Models/CannonActor.egg") self.model = loader.loadModel("../Models/Cannon.bam")
Cannon
class' __init__
method:self.projModel.setScale(.25, 1, .25)
reloadTime
to equal 1.5
, and change self.damage
to equal 75
. __init__
method, right underneath our declaration of self.damage:
self.blastR = 10
self.flashLerp
to make the flash bigger:self.flashLerp = LerpScaleInterval(self.flashModel, reloadTime * .1, Point3(2,2,2), Point3(.2,.2,.2))
self.fireSeq
to add a longer wait, like this:self.fireSeq = Sequence(self.firePar, Func(self.clearEffects), Wait(reloadTime * .9))
self.firePar
so that it looks like the following code:self.firePar = Parallel( Func(self.checkForHit), Func(self.setEffects), self.flashLerp)
checkForHit()
method, delete all the lines that contain the thingHit
variable anywhere in them. Then, edit the method to use Boom
instead of Pop
. The method should look similar to the following code when we're finished: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) boom = Boom(colPoint, self.blastR, self.damage) else: self.refNP.setPos(self.cycle.trgtrCNP, 0, 300, 0) boom = Boom(self.refNP.getPos(render), self.blastR, self.damage)
GunClasses_03.py
and open CycleClass_03.py
. We need to add the cannons to the cycle, and tie the cannon's fire control to the right mouse button. setupVarsNPs()
method and add the following two lines to it, right underneath where we create our machine guns:self.CannonMount = self.turretActor.exposeJoint(None, "modelRoot", "CannonMount") self.cannon = Cannon(self, self.CannonMount)
CycleControl()
method and add these lines right above the line where we declare aimPoint
.if(self.inputManager.keyMap["mouse3"] == True): self.cannon.fire()
destroy()
method, right beneath the lines that remove the machine guns:self.cannon.destroy() self.cannon = None
CycleClass_04.py
. RaceClass_02.py
to use CycleClass_04.py
, and then resave it as RaceClass_03.py
. WorldClass_02.py
to use RaceClass_03.py
, and then resave it as WorldClass_03.py
. WorldClass_03.py
from the command prompt and try out the cannon!This time we really didn't do anything new at all. By now, we should have noticed that the game tends to skip a little when the guns are first fired. That's because when we use a new explosion, Panda3D needs to load the 16 image files that make up the explosion. Once we've used the explosion already, the images are loaded and the skipping stops. We'll be taking care of this problem in Chapter 12, Finishing Touches: Getting the Game Ready for the Customer when we create a pre-loader.