def __init__(self): ShowBase.__init__(self) #start the time self.globalTime = 0 self.nextEnemy = 1 #setup your collision event handlers, apparently needs a direct object self.do = DirectObject() self.do.accept('unit-into-unit', self.handleUnitIntoCollision) self.do.accept('unit-out-unit', self.handleUnitOutCollision) self.do.accept('unit-into-cube', self.handleCubeIntoCollision) self.do.accept('unit-into-wing', self.handleWingIntoCollision) self.do.accept('unit-into-bar', self.handleBarIntoCollision) #get window properties self.winProps = WindowProperties() #self.winProps.setFullscreen(True) self.winProps.setCursorHidden(True) base.win.requestProperties(self.winProps) self.winProps = base.win.getProperties() self.screenHeight = self.winProps.getYSize() #set up the control scheme self.controlScheme = ControlScheme(base.mouseWatcherNode, base.win, \ [LEFT, RIGHT, UP, DOWN, PAUSE, PULL, PUSH, SWITCH, QUIT]) #disable the automatic task to move the camera #(this does not actually disable the mouse) base.disableMouse() #declare null values for variables, fill them in later self.environment = None self.player = None #a node for holding all in-game units self.unitNodePath = NodePath('unit holder') self.unitNodePath.reparentTo(self.render) #object lists self.enemies = [] self.obstacles = [] self.projectiles = [] #list of enemies to be spawned self.eSpawnList = [] #not paused by default self.paused = False self.pauseWasPressed = False #variables for tracking time self.previousFrameTime = 0 #start the collision traverser traverser = CollisionTraverser() base.cTrav = traverser#run every frame self.cTrav = base.cTrav #set the check for units accidentally passing through level geometry self.cTrav.setRespectPrevTransform(True) #self.cTrav.showCollisions(self.render) #self.cTrav.showCollisions(self.unitNodePath)#show the collisions #load terrain and enemies #load the environment, it seems that an x value of zero, a y value of -50 puts the origin point relatively in the middle of the crater filename = PARAMS_PATH + "environment.txt" self.loadLevelGeom(filename) #load the enemies filename = PARAMS_PATH + "enemies.txt" self.loadLevelEnemies(filename) #lookup table for actors self.actors = {} #place the player in the environment self.player = Player(self.controlScheme, self.camera, self, 0, 0, 0) self.player.setName("player") self.player.setH(180) self.player.reparentTo(self.unitNodePath) self.player.nodePath = self.render.find("player") self.actors["player"] = self.player #add some lights topLight = DirectionalLight("top light") topLight.setColor(Vec4(0.5, 0.5, 0.5, 1)) topLight.setDirection(Vec3(0, -90, 0)) self.render.setLight(self.render.attachNewNode(topLight)) ambientLight = AmbientLight("ambient light") ambientLight.setColor(Vec4(0.5, 0.5, 0.5, 1)) self.render.setLight(self.render.attachNewNode(ambientLight)) #the distance the camera is from the player self.cameraHOffset = 45 self.cameraVOffset = 10 #add the collision sound self.collisionSound = self.loader.loadSfx(SFX_PATH + "collide.wav") #register the update task self.taskMgr.add(self.updateGame, "updateGame") #add targeting to the world self.setupTargeting() #seed the random number generator random.seed() # configure the entire GUI self.setupGUI() # configure the title screen self.setupTitleScreen()
class Game(ShowBase): def __init__(self): ShowBase.__init__(self) #start the time self.globalTime = 0 self.nextEnemy = 1 #setup your collision event handlers, apparently needs a direct object self.do = DirectObject() self.do.accept('unit-into-unit', self.handleUnitIntoCollision) self.do.accept('unit-out-unit', self.handleUnitOutCollision) self.do.accept('unit-into-cube', self.handleCubeIntoCollision) self.do.accept('unit-into-wing', self.handleWingIntoCollision) self.do.accept('unit-into-bar', self.handleBarIntoCollision) #get window properties self.winProps = WindowProperties() #self.winProps.setFullscreen(True) self.winProps.setCursorHidden(True) base.win.requestProperties(self.winProps) self.winProps = base.win.getProperties() self.screenHeight = self.winProps.getYSize() #set up the control scheme self.controlScheme = ControlScheme(base.mouseWatcherNode, base.win, \ [LEFT, RIGHT, UP, DOWN, PAUSE, PULL, PUSH, SWITCH, QUIT]) #disable the automatic task to move the camera #(this does not actually disable the mouse) base.disableMouse() #declare null values for variables, fill them in later self.environment = None self.player = None #a node for holding all in-game units self.unitNodePath = NodePath('unit holder') self.unitNodePath.reparentTo(self.render) #object lists self.enemies = [] self.obstacles = [] self.projectiles = [] #list of enemies to be spawned self.eSpawnList = [] #not paused by default self.paused = False self.pauseWasPressed = False #variables for tracking time self.previousFrameTime = 0 #start the collision traverser traverser = CollisionTraverser() base.cTrav = traverser#run every frame self.cTrav = base.cTrav #set the check for units accidentally passing through level geometry self.cTrav.setRespectPrevTransform(True) #self.cTrav.showCollisions(self.render) #self.cTrav.showCollisions(self.unitNodePath)#show the collisions #load terrain and enemies #load the environment, it seems that an x value of zero, a y value of -50 puts the origin point relatively in the middle of the crater filename = PARAMS_PATH + "environment.txt" self.loadLevelGeom(filename) #load the enemies filename = PARAMS_PATH + "enemies.txt" self.loadLevelEnemies(filename) #lookup table for actors self.actors = {} #place the player in the environment self.player = Player(self.controlScheme, self.camera, self, 0, 0, 0) self.player.setName("player") self.player.setH(180) self.player.reparentTo(self.unitNodePath) self.player.nodePath = self.render.find("player") self.actors["player"] = self.player #add some lights topLight = DirectionalLight("top light") topLight.setColor(Vec4(0.5, 0.5, 0.5, 1)) topLight.setDirection(Vec3(0, -90, 0)) self.render.setLight(self.render.attachNewNode(topLight)) ambientLight = AmbientLight("ambient light") ambientLight.setColor(Vec4(0.5, 0.5, 0.5, 1)) self.render.setLight(self.render.attachNewNode(ambientLight)) #the distance the camera is from the player self.cameraHOffset = 45 self.cameraVOffset = 10 #add the collision sound self.collisionSound = self.loader.loadSfx(SFX_PATH + "collide.wav") #register the update task self.taskMgr.add(self.updateGame, "updateGame") #add targeting to the world self.setupTargeting() #seed the random number generator random.seed() # configure the entire GUI self.setupGUI() # configure the title screen self.setupTitleScreen() def setupGUI(self): GUIFont = loader.loadFont(FONTS_PATH + 'orbitron-medium.ttf') """ self.debugText = TextNode('debug') self.debugText.setText("") self.debugText.setAlign(TextNode.ALeft) self.debugText.setFont(GUIFont) dTextNodePath = aspect2d.attachNewNode(self.debugText) dTextNodePath.setScale(0.075) dTextNodePath.setPos(-1.2, 0, -0.9) """ #INTRO self.introText = TextNode('intro') self.introText.setText("") self.introText.setAlign(TextNode.ALeft) self.introText.setFont(GUIFont) self.introText.setCardColor(0.1, 0.1, 0.1, 0.6) self.introText.setCardAsMargin(0.5, 0.5, 0.5, 0.5) self.introText.setCardDecal(True) self.introText.setWordwrap(30.0) self.iTextNodePath = aspect2d.attachNewNode(self.introText) self.iTextNodePath.setScale(0.06) self.iTextNodePath.setPos(-1.2, 0, -0.7) #image is 171 x 323 self.leftMouseImage = OnscreenImage() self.leftMouseImage.setImage(GUI_PATH + "mouse-icon-left.png") self.leftMouseImage.setTransparency(1) self.leftMousePath = aspect2d.attachNewNode(self.leftMouseImage.node()) self.rightMouseImage = OnscreenImage() self.rightMouseImage.setImage(GUI_PATH + "mouse-icon-right.png") self.rightMouseImage.setTransparency(1) self.rightMousePath = aspect2d.attachNewNode(self.rightMouseImage.node()) self.middleMouseImage = OnscreenImage() self.middleMouseImage.setImage(GUI_PATH + "mouse-icon-middle.png") self.middleMouseImage.setTransparency(1) self.middleMousePath = aspect2d.attachNewNode(self.middleMouseImage.node()) self.leftMousePath.setScale(.105882, 0, .2) self.leftMousePath.setPos(1.1, 0, -0.75) self.rightMousePath.setScale(.105882, 0, .2) self.rightMousePath.setPos(1.1, 0, -0.75) self.middleMousePath.setScale(.105882, 0, .2) self.middleMousePath.setPos(1.1, 0, -0.75) self.leftMousePath.hide() self.rightMousePath.hide() self.middleMousePath.hide() #HUD #image is 365 x 187 self.attackModeImage = OnscreenImage() self.attackModeImage.setImage(GUI_PATH + "mode-area.png") self.attackModeImage.setTransparency(1) modeNodePath = aspect2d.attachNewNode(self.attackModeImage.node()) modeNodePath.setScale(.136631, 0, .07) modeNodePath.setPos(-1.13, 0, 0.88) self.energyBarImage = OnscreenImage() self.energyBarImage.setImage(GUI_PATH + "energy-bar-full.png") self.energyBarImage.setTransparency(1) eBarNodePath = aspect2d.attachNewNode(self.energyBarImage.node()) eBarNodePath.setScale(.400, 0, .0475) eBarNodePath.setPos(-0.66, 0, 0.88) self.healthBarImage = OnscreenImage() self.healthBarImage.setImage(GUI_PATH + "health-bar-full.png") self.healthBarImage.setTransparency(1) hBarNodePath = aspect2d.attachNewNode(self.healthBarImage.node()) hBarNodePath.setScale(.400, 0, .0475) hBarNodePath.setPos(0.85, 0, 0.88) def setupTitleScreen(self): self.titleScreenIsActive = True #image is 800 x 600 self.titleImage = OnscreenImage() self.titleImage.setImage(GUI_PATH + "title.png") titleNodePath = aspect2d.attachNewNode(self.titleImage.node()) titleNodePath.setScale(1.33333, 0, 1) titleNodePath.setPos(0, 0, 0) def updateTitleScreen(self): if (self.controlScheme.keyDown(PUSH) or self.controlScheme.keyDown(PULL) or self.controlScheme.keyDown(SWITCH)) and self.titleScreenIsActive: self.titleImage.hide() self.titleScreenIsActive = False elif self.titleScreenIsActive: self.titleImage.setImage(GUI_PATH + "title.png") self.globalTime=0 else: pass def calculateBarImage(self, level): if level == 0: level = "empty" elif level == 10: level = "full" elif level == 1: level = "1" elif level == 2: level = "2" elif level == 3: level = "3" elif level == 4: level = "4" elif level == 5: level = "5" elif level == 6: level = "6" elif level == 7: level = "7" elif level == 8: level = "8" elif level == 9: level = "9" return level def updateGUI(self): """ self.debugText.setText("Energy: "+str((100*self.player.energy/self.player.maxEnergy))+"%, Health: "+str((100*self.player.health/self.player.maxHealth))) """ self.updateIntro() if self.player.currentWeapon == AREA: modeImg = "mode-area" elif self.player.currentWeapon == NARROW: modeImg = "mode-narrow" energyLevel = self.calculateBarImage((100 * (self.player.energy / self.player.maxEnergy)) // 10) self.energyBarImage.setImage(GUI_PATH + "energy-bar-" + energyLevel + ".png") self.energyBarImage.setTransparency(1) self.attackModeImage.setImage(GUI_PATH + modeImg + ".png") self.attackModeImage.setTransparency(1) healthLevel = self.calculateBarImage((100 * (self.player.health / self.player.maxHealth)) // 10) self.healthBarImage.setImage(GUI_PATH + "health-bar-" + healthLevel + ".png") self.healthBarImage.setTransparency(1) def updateIntro(self): modifiedTime = self.globalTime/5 if self.introText is None: pass elif modifiedTime>=14300 and self.introText is not None: self.iTextNodePath.removeNode() self.introText = None elif modifiedTime<300: #0-300 self.introText.setText("Hey are you receiving?") elif modifiedTime<800: #300-800 self.introText.setText("We recently uncovered the location of an old cruiser wreck from the war.") elif modifiedTime<1500: #800-1500 self.introText.setText("You're gonna go in there and get the little bits of it that are still worth salvaging.") elif modifiedTime<2900: #1500-2900 self.introText.setText("Be aware though, this job may not be quite as simple as a grab-and-run. The coordinates have been leaked to some of our old enemies.") elif modifiedTime<4200: #2900-4200 self.introText.setText("To give you an edge, we've made a few upgrades to your electromagnetic grapple.") elif modifiedTime<5300: #4200-5300 self.introText.setText("Pull enemies inwards with the right mouse button.") self.leftMousePath.hide() self.rightMousePath.show() self.middleMousePath.hide() elif modifiedTime<6400: #5300-6400 self.introText.setText("Push enemies away with the left mouse button.") self.leftMousePath.show() self.rightMousePath.hide() self.middleMousePath.hide() elif modifiedTime<8500: #6400-8500 self.introText.setText("Toggle between your range and narrow electromagnet with the middle mouse button (or spacebar).") self.leftMousePath.hide() self.rightMousePath.hide() self.middleMousePath.show() elif modifiedTime<13300: #8500-13300 self.introText.setText("You can give a solid kick to anything straight in front of you or just push everything around you away. Try and throw 'em into each other or other wreckage to finish 'em off for good.") self.leftMousePath.hide() self.rightMousePath.hide() self.middleMousePath.hide() elif modifiedTime<14300: #13300-14300 self.introText.setText("After all, the more salvage left over, the better. Out.") def loadLevelGeom(self, filename): filename = os.path.abspath(filename) if not os.path.isfile(filename): print "FILE DOES NOT EXIST:" exit(1) #get the lines from the file textFileList = open(filename, 'r').readlines() if len(textFileList) < 1: print "FATAL ERROR READING FILE" exit(1) #now split each line into lists for num, val in enumerate(textFileList): val = val.rstrip('\n')#strip the newlines val = val.strip() textFileList[num] = val.split(TEXT_DELIMITER) obstacle = None for list in textFileList: #go through the list if list[0] == TERRAIN_OUTER:#do all the things for the terrain #choose the model modelVal = list[1] modelVal = (MODELS_PATH + modelVal) self.environment = self.loader.loadModel(modelVal) self.environment.reparentTo(self.render) #get the collision geometry for the environment #and move it up a bit to allow the character to float above the crater self.craterCollision = self.environment.find("**/craterCollisionPlane") self.craterCollision.setZ(self.environment.getZ() + 0.15) self.environment.setCollideMask(BitMask32.allOff()) self.craterCollision.setCollideMask(BitMask32(TERRAIN_RAY_MASK)) #self.environment.find( #.find("craterCollisionPlane").setZ(self.environment.getZ() + 10) #set scale scaleVal = list[2].split(',')#split by commas self.environment.setScale(float(scaleVal[0]), float(scaleVal[1]), float(scaleVal[2])) #set location locVal = list[3].split(',') self.environment.setPos(float(locVal[0]), float(locVal[1]), float(locVal[2]))#then we have our terrain #set rotation hprVal = list[4].split(',') self.environment.setHpr(float(hprVal[0]), float(hprVal[1]), float(hprVal[2])) elif list[0] == TERRAIN_CUBE: #choose the model modelVal = list[1] modelVal = (MODELS_PATH + modelVal) #load the model obstacle = self.loader.loadModel(modelVal) obstacle.reparentTo(render) #set scale scaleVal = list[2].split(',') obstacle.setScale(float(scaleVal[0]), float(scaleVal[1]), float(scaleVal[2])) #set location locVal = list[3].split(',') obstacle.setPos(float(locVal[0]), float(locVal[1]), float(locVal[2]))#the we have our object hprVal = list[4].split(',') obstacle.setHpr(float(hprVal[0]), float(hprVal[1]), float(hprVal[2])) #set up collisions unitCollision = obstacle.find("**/CubeBlock") unitCollision.node().setName("cube") obstacle.setCollideMask(BitMask32.allOff()) unitCollision.setCollideMask(BitMask32(PLAYER_ENEMY_OBJECTS)) self.obstacles.append(obstacle) elif list[0] == TERRAIN_WING: modelVal = list[1] modelVal = (MODELS_PATH + modelVal) #load the model obstacle = self.loader.loadModel(modelVal) obstacle.reparentTo(render) #set scale scaleVal = list[2].split(',') obstacle.setScale(float(scaleVal[0]), float(scaleVal[1]), float(scaleVal[2])) #set location locVal = list[3].split(',') obstacle.setPos(float(locVal[0]), float(locVal[1]), float(locVal[2]))#the we have our object hprVal = list[4].split(',') obstacle.setHpr(float(hprVal[0]), float(hprVal[1]), float(hprVal[2])) #set up collisions unitCollision = obstacle.find("**/wingCollider") unitCollision.node().setName("wing") obstacle.setCollideMask(BitMask32.allOff()) unitCollision.setCollideMask(BitMask32(PLAYER_ENEMY_OBJECTS)) self.obstacles.append(obstacle) elif list[0] == TERRAIN_BAR: modelVal = list[1] modelVal = (MODELS_PATH + modelVal) #load the model obstacle = self.loader.loadModel(modelVal) obstacle.reparentTo(render) #set scale scaleVal = list[2].split(',') obstacle.setScale(float(scaleVal[0]), float(scaleVal[1]), float(scaleVal[2])) #set location locVal = list[3].split(',') obstacle.setPos(float(locVal[0]), float(locVal[1]), float(locVal[2]))#the we have our object hprVal = list[4].split(',') obstacle.setHpr(float(hprVal[0]), float(hprVal[1]), float(hprVal[2])) #set up collisions unitCollision = obstacle.find("**/metalBarCollisionCube") unitCollision.node().setName("bar") obstacle.setCollideMask(BitMask32.allOff()) unitCollision.setCollideMask(BitMask32(PLAYER_ENEMY_OBJECTS)) elif list[0] == TERRAIN_SHARDS: modelVal = list[1] modelVal = (MODELS_PATH + modelVal) #load the model obstacle = self.loader.loadModel(modelVal) obstacle.reparentTo(render) #set scale scaleVal = list[2].split(',') obstacle.setScale(float(scaleVal[0]), float(scaleVal[1]), float(scaleVal[2])) #set location locVal = list[3].split(',') obstacle.setPos(float(locVal[0]), float(locVal[1]), float(locVal[2]))#the we have our object hprVal = list[4].split(',') obstacle.setHpr(float(hprVal[0]), float(hprVal[1]), float(hprVal[2])) #set up collisions unitCollision = obstacle.find("**/metalShardCollisionCube") unitCollision.node().setName("shard") obstacle.setCollideMask(BitMask32.allOff()) unitCollision.setCollideMask(BitMask32(PLAYER_ENEMY_OBJECTS)) else: print "FATAL ERROR READING FILE" exit(1) pass def loadLevelEnemies(self, filename): filename = os.path.abspath(filename) if not os.path.isfile(filename): print "FILE DOES NOT EXIST:" exit(1) #get the lines from the file and split them textFileList = open(filename, 'r').readlines() if len(textFileList) < 1: print "FATAL ERROR READING FILE" exit(1) for num, val in enumerate(textFileList): val = val.rstrip('\n')#strip the newlines val = val.strip() textFileList[num] = val.split(TEXT_DELIMITER) currwave = dict() currwave["time"] = None currwave["enemies"] = [] currEnem = dict() for val in textFileList: if val[0] == BEGIN_WAVE: currwave = dict() currwave["time"] = float(val[1])#set your time currwave["enemies"] = [] elif val[0] == RUSH_ENEMY: currEnem = dict() pos = [] pos = val[1].split(',')#get the three values for spawning, not floats currEnem["type"] = RUSH_ENEMY currEnem["xVal"] = float(pos[0]) currEnem["yVal"] = float(pos[1]) currEnem["zVal"] = float(pos[2]) currwave["enemies"].append(dict(currEnem))#copy elif val[0] == DRONE_ENEMY: currEnem = dict() pos = [] pos = val[1].split(',')#get the three values for spawning, not floats currEnem["type"] = DRONE_ENEMY currEnem["xVal"] = float(pos[0]) currEnem["yVal"] = float(pos[1]) currEnem["zVal"] = float(pos[2]) currwave["enemies"].append(dict(currEnem))#copy elif val[0] == SHOOTING_ENEMY: currEnem = dict() pos = [] pos = val[1].split(',')#get the three values for spawning, not floats currEnem["type"] = SHOOTING_ENEMY currEnem["xVal"] = float(pos[0]) currEnem["yVal"] = float(pos[1]) currEnem["zVal"] = float(pos[2]) currwave["enemies"].append(dict(currEnem))#copy elif val[0] == END_WAVE:#then we are done with that wave self.eSpawnList.append(dict(currwave))#copy else: pass#then something was stupid #now sort your waves with lowest time first self.eSpawnList.sort(key = lambda object: object["time"]) #and you're done def updateGame(self, task): if not self.titleScreenIsActive: self.globalTime = self.globalTime + task.time elapsedTime = task.time - self.previousFrameTime #base.resetPrevTransform(render)#for our high intensity collision detection if self.controlScheme.keyDown(QUIT): exit(0) if not self.paused and not self.titleScreenIsActive: time = elapsedTime while time > 0.02: self.updateGameComponents(0.02) time -= 0.02 self.updateGameComponents(time) self.cTrav.traverse(render) self.spawnEnemies()#globalTime is available if self.controlScheme.keyDown(PAUSE): if not self.pauseWasPressed: self.paused = not self.paused self.controlScheme.resetMouse() self.pauseWasPressed = True else: self.pauseWasPressed = False self.updateGUI() self.updateTitleScreen() self.previousFrameTime = task.time return task.cont def updateGameComponents(self, time): ''' Updates the state of the world. @precondition: The game isn't paused. ''' self.updateCamera(time) for enemy in self.enemies: enemy.update(time) for projectile in self.projectiles: projectile.update(time) #check for basic terrain collisions self.player.terrainCollisionCheck() self.player.update(time) for enemy in self.enemies: enemy.terrainCollisionCheck() for projectile in self.projectiles: projectile.terrainCollisionCheck() def spawnEnemies(self):#now we spawn our enemies while((len(self.eSpawnList) > 0) and self.eSpawnList[0]["time"] < self.globalTime): for val in self.eSpawnList[0]["enemies"]: if val["type"] == RUSH_ENEMY: #add an enemy tempEnemy = RushEnemy(self, val["xVal"], val["yVal"], val["zVal"]) self.configureEnemy(tempEnemy) elif val["type"] == DRONE_ENEMY: #add an enemy tempEnemy = DroneEnemy(self, self.player, val["xVal"], val["yVal"], val["zVal"]) self.configureEnemy(tempEnemy) elif val["type"] == SHOOTING_ENEMY: #add an enemy tempEnemy = ShootingEnemy(self, val["xVal"], val["yVal"], val["zVal"]) self.configureEnemy(tempEnemy) else: pass del self.eSpawnList[0]#del def configureEnemy(self, tempEnemy):#after making an enemy configure it for the game numString = str(self.nextEnemy) tempEnemy.setName("enemy" + numString) tempEnemy.reparentTo(self.unitNodePath) tempEnemy.nodePath = self.render.find("enemy1") self.actors["enemy" + numString] = tempEnemy self.nextEnemy = self.nextEnemy + 1 self.enemies.append(tempEnemy) def rotateCamera(self): if self.controlScheme.mouseX > self.winProps.getXSize(): self.camera.setH(-(self.winProps.getXSize() - 20) * 0.5) else: self.camera.setH(-self.controlScheme.mouseX * 0.5) def updateCamera(self, elapsedTime): #update the camera's heading based on the mouse's x position if self.controlScheme.recheckMouse(): self.camera.setH(-self.controlScheme.mouseX * 0.5) else: self.rotateCamera() #update the camera's pitch and vertical position based on the mouse's y position self.cameraVOffset = min(self.screenHeight, max(0, self.controlScheme.mouseY)) / self.screenHeight * 25 + 4 self.cameraHOffset = self.cameraVOffset * 0.8 + 30 self.camera.setP(atan2(-self.cameraVOffset * 0.7, self.cameraHOffset) \ * 180 / pi) #update the camera to point at the player self.camera.setPos(self.player.getX() + self.cameraHOffset * sin(self.camera.getH() * pi / 180), self.player.getY() - self.cameraHOffset * cos(self.camera.getH() * pi / 180), self.player.getZ() + 0.3 + self.cameraVOffset) def selectTarget(self): """Finds the closest shootable object and returns it""" #traverse all objects in render self.mPickerTraverser.traverse(self.unitNodePath) if (self.mCollisionQue.getNumEntries() > 0): self.mCollisionQue.sortEntries() for i in range(0, self.mCollisionQue.getNumEntries()): entry = self.mCollisionQue.getEntry(i) pickedObj = entry.getIntoNodePath() if not pickedObj.isEmpty(): name = pickedObj.getParent().getName() if name == "render": return None #if the object is shootable, set it as the target try: if self.actors[name].shootable: return self.actors[name] except: continue return None def setupTargeting(self): """Set up the collisions necessary to target enemies and other objects""" #Since we are using collision detection to do picking, we set it up #any other collision detection system with a traverser and a handler self.mPickerTraverser = CollisionTraverser() #Make a traverser #self.mPickerTraverser.showCollisions(self.unitNodePath) self.mCollisionQue = CollisionHandlerQueue() #create a collision solid ray to detect against self.mPickRay = CollisionRay() self.mPickRay.setOrigin(self.player.getPos(self.render)) self.mPickRay.setDirection(self.render.getRelativeVector(self.player, Vec3(0, 1, 0))) self.mPickRay2 = CollisionRay() self.mPickRay2.setOrigin(self.player.getPos(self.render)) self.mPickRay2.setDirection(self.render.getRelativeVector(self.player, Vec3(0.06, 1, 0))) self.mPickRay3 = CollisionRay() self.mPickRay3.setOrigin(self.player.getPos(self.render)) self.mPickRay3.setDirection(self.render.getRelativeVector(self.player, Vec3(-0.06, 1, 0))) self.mPickRay4 = CollisionRay() self.mPickRay4.setOrigin(self.player.getPos(self.render)) self.mPickRay4.setDirection(self.render.getRelativeVector(self.player, Vec3(0, 1, 0.06))) self.mPickRay5 = CollisionRay() self.mPickRay5.setOrigin(self.player.getPos(self.render)) self.mPickRay5.setDirection(self.render.getRelativeVector(self.player, Vec3(0, 1, -0.06))) #create our collison Node to hold the ray self.mPickNode = CollisionNode('pickRay') self.mPickNode.setIntoCollideMask(BitMask32.allOff()) self.mPickNode.addSolid(self.mPickRay) self.mPickNode2 = CollisionNode('pickRay2') self.mPickNode2.setIntoCollideMask(BitMask32.allOff()) self.mPickNode2.addSolid(self.mPickRay2) self.mPickNode3 = CollisionNode('pickRay3') self.mPickNode3.setIntoCollideMask(BitMask32.allOff()) self.mPickNode3.addSolid(self.mPickRay3) self.mPickNode4 = CollisionNode('pickRay4') self.mPickNode4.setIntoCollideMask(BitMask32.allOff()) self.mPickNode4.addSolid(self.mPickRay4) self.mPickNode5 = CollisionNode('pickRay5') self.mPickNode5.setIntoCollideMask(BitMask32.allOff()) self.mPickNode5.addSolid(self.mPickRay5) #Attach that node to the player since the ray will need to be positioned #relative to it, returns a new nodepath #well use the default geometry mask #this is inefficent but its for mouse picking only self.mPickNP = self.player.attachNewNode(self.mPickNode) self.mPickNP2 = self.player.attachNewNode(self.mPickNode2) self.mPickNP3 = self.player.attachNewNode(self.mPickNode3) self.mPickNP4 = self.player.attachNewNode(self.mPickNode4) self.mPickNP5 = self.player.attachNewNode(self.mPickNode5) #well use what panda calls the "from" node. This is really a silly convention #but from nodes are nodes that are active, while into nodes are usually passive environments #this isnt a hard rule, but following it usually reduces processing #Everything to be picked will use bit 1. This way if we were doing other #collision we could seperate it, we use bitmasks to determine what we check other objects against #if they dont have a bitmask for bit 1 well skip them! #self.mPickNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) self.mPickNode.setFromCollideMask(PLAYER_ENEMY_OBJECTS) self.mPickNode2.setFromCollideMask(PLAYER_ENEMY_OBJECTS) self.mPickNode3.setFromCollideMask(PLAYER_ENEMY_OBJECTS) self.mPickNode4.setFromCollideMask(PLAYER_ENEMY_OBJECTS) self.mPickNode5.setFromCollideMask(PLAYER_ENEMY_OBJECTS) #Register the ray as something that can cause collisions self.mPickerTraverser.addCollider(self.mPickNP, self.mCollisionQue) self.mPickerTraverser.addCollider(self.mPickNP2, self.mCollisionQue) self.mPickerTraverser.addCollider(self.mPickNP3, self.mCollisionQue) self.mPickerTraverser.addCollider(self.mPickNP4, self.mCollisionQue) self.mPickerTraverser.addCollider(self.mPickNP5, self.mCollisionQue) def handleUnitIntoCollision(self, entry): try: fromName = entry.getFromNodePath().getParent().getName() intoName = entry.getIntoNodePath().getParent().getName() Unit.collideWithUnit(self.actors[intoName], self.actors[fromName]) if (fromName == "player" or intoName == "player") and self.collisionSound.status() is not self.collisionSound.PLAYING: self.collisionSound.play() except: pass def handleUnitOutCollision(self, entry): pass def handleWingIntoCollision(self, entry): fromName = entry.getFromNodePath().getParent().getName() Unit.collideWithObstacle(self.actors[fromName]) if fromName == "player" and self.collisionSound.status() is not self.collisionSound.PLAYING: self.collisionSound.play() def handleCubeIntoCollision(self, entry): try: fromName = entry.getFromNodePath().getParent().getName() Unit.collideWithObstacle(self.actors[fromName]) if fromName == "player" and self.collisionSound.status() is not self.collisionSound.PLAYING: self.collisionSound.play() except: pass def handleBarIntoCollision(self, entry): fromName = entry.getFromNodePath().getParent().getName() Unit.collideWithObstacle(self.actors[fromName]) if fromName == "player" and self.collisionSound.status() is not self.collisionSound.PLAYING: self.collisionSound.play() def gameOver(self): pass