class Controller(viz.EventClass): # Constructor def __init__(self): # base class constructor viz.EventClass.__init__(self) self.callback(viz.KEYDOWN_EVENT, self.onKeyDown) # Callback for key press self.callback(viz.TIMER_EVENT, self.onTimer) # Callback for timers self.callback(viz.KEYUP_EVENT, self.onKeyUp) #Creates memory for bullets and alien spawns self.bulletlist = [] self.aliens = [None for x in range(0, 18)] self.alienbullets = list() # Default rotation for camera self.theta = 50 #Booleans for keys pressed self.leftUp = True self.rightUp = True self.Fire = False self.start = False self.pause = False self.start = False #Checks whether the game has started self.gameover = False self.title = True self.playerSpeed = .05 #Setup default camera view self.view = viz.MainView mat = viz.Matrix() mat.postAxisAngle(1, 0, 0, self.theta) mat.postTrans(0, 0, 0) self.view.setMatrix(mat) #Spawn the player self.playerShip = Player() self.playerShip.setPosition(0, 0, -.6) self.power = 3 self.level = 1 self.speed = 1 / self.power # Start timers self.starttimer(1, .05, viz.FOREVER) self.starttimer(2, .05, viz.FOREVER) self.starttimer(3, .001, viz.FOREVER) self.starttimer(4, self.speed, viz.FOREVER) self.starttimer(5, .5, viz.FOREVER) self.starttimer(6, .3, viz.FOREVER) #Initialize these models far off screen so they can be copied, thus these models only load once self.firstRed = Alien('red', modelLabel='redAlien.dae') self.firstRed.setPosition(0, 2000, 0) self.firstBlue = Alien('blue', modelLabel='blueAlien.dae') self.firstBlue.setPosition(0, 2000, 0) self.firstPurple = Alien('purple', modelLabel='tankAlien.dae') self.firstPurple.setPosition(0, 2000, 0) self.redbullet = Bullet(modelLabel='redBullet.dae') self.redbullet.setPosition(0, 2000, 0) self.greenbullet = Bullet(modelLabel='greenBullet.dae') self.greenbullet.setPosition(0, 2000, 0) self.firstOrange = Alien('orange', modelLabel='powerupAlien.dae') self.firstOrange.setPosition(0, 2000, 0) self.firstGreen = Alien('green', modelLabel='greenAlien.dae') self.firstGreen.setPosition(0, 2000, 0) #Boss object and where the boss can move self.boss = None self.bossRight = False self.bossLeft = True #Initial dynamic text strings self.levelText = None self.levelMsg = "Level: 1" self.hpText = None self.hpMsg = "HP: 1" self.scoreText = None self.scoreMsg = "Score: 0" self.score = 0 #Spawn the title screen self.titleScreen() def spawnAliens(self): # Spawns 3x6 aliens print("LEVEL: " + str(self.level)) if self.level % 6 == 0: #Spawns a boss at every sixth level self.boss = Alien('green', model=self.firstGreen.clone(), hp=self.power * 6) self.boss.setPosition(0, 0, 1, scale=.0025 * 3) self.speed = 1 / (self.power / 2) viz.playSound('bossSpawn.wav') elif not self.pause: x = -.6 #Spawns a 3x6 wave of aliens, each alien spawn is random for i in range(0, 6): num = random.randint(0, 3) if num == 0: self.aliens[i] = Alien('blue', model=self.firstBlue.clone(), hp=3) elif num == 1: self.aliens[i] = Alien('red', model=self.firstRed.clone()) elif num == 2: self.aliens[i] = Alien('purple', model=self.firstPurple.clone(), hp=3) elif num == 3: self.aliens[i] = Alien('orange', model=self.firstOrange.clone(), hp=2) self.aliens[i].setPosition(x, 0, 1) x += .25 x = -.6 for i in range(6, 12): num = random.randint(0, 3) if num == 0: self.aliens[i] = Alien('blue', model=self.firstBlue.clone(), hp=3) elif num == 1: self.aliens[i] = Alien('red', model=self.firstRed.clone()) elif num == 2: self.aliens[i] = Alien('purple', model=self.firstPurple.clone(), hp=3) elif num == 3: self.aliens[i] = Alien('orange', model=self.firstOrange.clone(), hp=2) self.aliens[i].setPosition(x, 0, .75) x += .25 x = -.6 for i in range(12, 18): num = random.randint(0, 3) if num == 0: self.aliens[i] = Alien('blue', model=self.firstBlue.clone(), hp=3) elif num == 1: self.aliens[i] = Alien('red', model=self.firstRed.clone()) elif num == 2: self.aliens[i] = Alien('purple', model=self.firstPurple.clone(), hp=3) elif num == 3: self.aliens[i] = Alien('orange', model=self.firstOrange.clone(), hp=2) self.aliens[i].setPosition(x, 0, .5) x += .25 viz.playSound('newWave.wav') def onKeyDown(self, key): #Movement keys if key == 'a' or key == viz.KEY_LEFT: self.leftUp = False if key == 'd' or key == viz.KEY_RIGHT: self.rightUp = False if key == "p": #Pause button if self.pause and not self.gameover: self.pause = False else: self.pause = True # Default Camera if key == '1': self.theta = 50 mat = viz.Matrix() mat.postTrans(0, 0, -2) mat.postAxisAngle(1, 0, 0, self.theta) self.view.setMatrix(mat) # Top Down View if key == '2': self.theta = 90 mat = viz.Matrix() mat.postAxisAngle(1, 0, 0, self.theta) mat.postTrans(0, 2, 0) self.view.setMatrix(mat) # Side View if key == '3': self.theta = 90 mat = viz.Matrix() mat.postAxisAngle(0, 1, 0, self.theta) mat.postTrans(-1.5, 0, 0) self.view.setMatrix(mat) # Side View if key == '4': self.theta = 270 mat = viz.Matrix() mat.postAxisAngle(0, 1, 0, self.theta) mat.postTrans(1.5, 0, 0) self.view.setMatrix(mat) #Player fires if key == " " and self.Fire and not self.pause: b = Bullet(model=self.greenbullet.clone()) b.setPosition(self.playerShip.getX() - .02, self.playerShip.getY() + .02, self.playerShip.getZ()) self.bulletlist.append(b) self.Fire = False viz.playSound('laser.wav') if key == 'q': self.title = False print(self.title) if key == viz.KEY_RETURN: if not self.start: #Change out the text on screen, disable the start text and setup dynamic text for the first time self.start = True self.description.remove() self.spawnAliens() self.levelMsg = "Level: 1" self.levelText = viz.addText(self.levelMsg, viz.SCREEN, pos=[.15, .95, 0]) self.levelText.fontSize(33) self.hpText = viz.addText(self.hpMsg, viz.SCREEN, pos=[.8, .95, 0]) self.hpText.fontSize(33) self.scoreText = viz.addText(self.scoreMsg, viz.SCREEN, pos=[.45, .95, 0]) self.scoreText.fontSize(33) def onKeyUp(self, key): #Controls booleans for key presses, reactions are done by timers if key == "a" or key == viz.KEY_LEFT: self.leftUp = True if key == "d" or key == viz.KEY_RIGHT: self.rightUp = True if key == " ": self.fire = False def onTimer(self, num): if num == 1 and not self.pause: # Moves the player left/right and controls the rotation of the ship if not self.leftUp and self.playerShip.canGoLeft(-0.25): self.playerShip.setPosition( self.playerShip.getX() - self.playerSpeed, self.playerShip.getY(), self.playerShip.getZ()) if self.playerShip.theta < 45 or self.playerShip.theta >= 315: self.playerShip.rotate(9) if not self.rightUp and self.playerShip.canGoRight(0.25): self.playerShip.setPosition( self.playerShip.getX() + self.playerSpeed, self.playerShip.getY(), self.playerShip.getZ()) if self.playerShip.theta > 315 and self.playerShip.theta <= 360 or self.playerShip.theta <= 45: self.playerShip.rotate(351) if num == 2 and not self.pause: #Controls passive rotation for if the player is not actively pressing buttons if self.leftUp and self.rightUp: if self.playerShip.theta <= 45 and self.playerShip.theta >= 0: self.playerShip.rotate(351) if self.playerShip.theta >= 315: self.playerShip.rotate(9) if num == 3 and not self.pause: #Move bullet for bullet in self.bulletlist: x = bullet.getX() vx = bullet.getVX() y = bullet.getY() vy = bullet.getVY() z = bullet.getZ() vz = bullet.getVZ() bullet.setPosition(x + vx, y + vy, z + vz) #Deallocate bullets if (bullet.getZ() > 2): bullet.delete() self.bulletlist.remove(bullet) # Check bullet to alien collison deadaliens = 0 for alien in self.aliens: if alien != None: if bullet.getX() > alien.getX() - .1 and bullet.getX( ) < alien.getX() + .1 and bullet.getZ() > alien.getZ( ) - .1 and bullet.getZ() < alien.getZ() + .1: bullet.delete() self.bulletlist.remove(bullet) alien.damage() viz.playSound('alienHit.wav') if alien.getHP() <= 0: alien.delete() deadalien = self.aliens.index(alien) self.aliens[deadalien] = None deadaliens += 1 if alien.getColor( ) == 'orange': #Orange aliens death triggers a powerup self.playerShip.powerUp() self.updateHPText() viz.playSound('powerup.wav') else: viz.playSound('explosion.wav') self.score += 100 self.updateScoreText() else: deadaliens += 1 if self.boss != None: #Check if boss alien is hit if bullet.getX() > self.boss.getX() - .3 and bullet.getX( ) < self.boss.getX() + .3 and bullet.getZ( ) > self.boss.getZ() - .3 and bullet.getZ( ) < self.boss.getZ() + .3: bullet.delete() self.bulletlist.remove(bullet) self.boss.damage() viz.playSound('alienHit.wav') if self.boss.getHP() <= 0: self.boss.delete() self.boss = None viz.playSound('explosion.wav') self.score += 100 self.updateScoreText() #Check to see if current wave is complete if len(self.aliens) == deadaliens and self.boss == None: self.power += 1 self.level += 1 self.updateLevelText() self.speed = 1 / self.power viz.killtimer(4) self.starttimer(4, self.speed, viz.FOREVER) self.spawnAliens() # TRANSLATE ALIEN BULLET for bullet in self.alienbullets: x = bullet.getX() vx = bullet.getVX() y = bullet.getY() vy = bullet.getVY() z = bullet.getZ() vz = bullet.getVZ() bullet.setPosition(x - vx, y - vy, z - vz) if (bullet.getZ() < -.8): bullet.delete() self.alienbullets.remove(bullet) if bullet.getX() > self.playerShip.getX() - .1 and bullet.getX( ) < self.playerShip.getX() + .1 and bullet.getZ( ) > self.playerShip.getZ() - .1 and bullet.getZ( ) < self.playerShip.getZ() + .1: bullet.delete() self.alienbullets.remove(bullet) self.playerShip.damage(math.floor(self.power / 2)) viz.playSound('playerHit.wav') if self.playerShip.getHP() <= 0: #GAME OVER self.gameover = True self.pause = True self.playerShip.delete() viz.playSound('playerDead.wav') self.updateHPText() if num == 4 and not self.pause: # Move aliens down the Z axis for alien in self.aliens: if alien != None: alien.setPosition(alien.getX(), alien.getY(), alien.getZ() - .001, alien.getScale()) if self.playerShip.getX() + .04 > alien.getX( ) - .1 and self.playerShip.getX() - .04 < alien.getX( ) + .1 and self.playerShip.getZ() + .06 > alien.getZ( ) - .1 and self.playerShip.getZ() - .06 < alien.getZ() + .1: self.playerShip.damage(1) if self.playerShip.getHP() <= 0: #GAME OVER self.gameover = True self.pause = True self.playerShip.delete() viz.playSound('collision.wav') self.updateHPText() if alien.isOffScreen( ): #Translate aliens back if off screen alien.setPosition(alien.getX(), alien.getY(), 1, alien.getScale()) if self.boss != None: #Move the boss around, the boss moves left right on the X axis instead of foward on the Z if self.boss.getX() > -1 and self.bossLeft: self.boss.setPosition(self.boss.getX() - .001, self.boss.getY(), self.boss.getZ(), self.boss.getScale()) else: self.bossLeft = False if self.boss.getX() < 1 and not self.bossLeft: self.boss.setPosition(self.boss.getX() + .001, self.boss.getY(), self.boss.getZ(), self.boss.getScale()) else: self.bossLeft = True if self.playerShip.getX() + .04 > self.boss.getX( ) - .1 and self.playerShip.getX() - .04 < self.boss.getX( ) + .1 and self.playerShip.getZ() + .06 > self.boss.getZ( ) - .1 and self.playerShip.getZ() - .06 < self.boss.getZ() + .1: self.playerShip.damage(1) if self.playerShip.getHP() <= 0: self.playerShip.delete() viz.playSound('explosion.wav') self.updateHPText() if self.boss.isOffScreen(): self.boss.setPosition(self.boss.getX(), self.boss.getY(), 1, self.boss.getScale()) if num == 5 and not self.pause: for alien in self.aliens: if alien != None: if alien.getColor() == 'red' or alien.getColor( ) == 'purple' or alien.getColor( ) == 'green': #Only red and purple ships can fire index = self.aliens.index( alien ) #Get the index of the current ship in our list #Checks for whether a ship exists in the two spots in front, False = No Ship, True = Ship Exists checkOne = False checkTwo = False if index < 6: if self.aliens[index + 6] != None: checkOne = True if self.aliens[index + 12] != None: checkTwo = True elif index < 12: if self.aliens[index + 6] != None: checkOne = True # FIRES ALIEN BULLETS, THESE CHECKS ARE REQUIRED TO ALLOW A SHIP TO FIRE, alien cannot fire if there is another ship in front of it if not checkOne and not checkTwo and self.playerShip.getX( ) <= alien.getX() + .1 and self.playerShip.getX( ) >= alien.getX() - .1 and not self.pause: b = Bullet(model=self.redbullet.clone()) b.setTheta(180) b.setPosition(alien.getX(), alien.getY(), alien.getZ()) self.alienbullets.append(b) viz.playSound('laser.wav') if self.boss != None: #The boss fires three bullets, one straight ahead and two at an angle b = Bullet(model=self.redbullet.clone()) b.setTheta(180) b.setPosition(self.boss.getX(), self.boss.getY(), self.boss.getZ(), 0) self.alienbullets.append(b) b = Bullet(model=self.redbullet.clone()) b.setTheta(180) b.setVXVY(.02, 0, .02) b.setPosition(self.boss.getX(), self.boss.getY(), self.boss.getZ()) self.alienbullets.append(b) b = Bullet(model=self.redbullet.clone()) b.setTheta(180) b.setVXVY(-.02, 0, .02) b.setPosition(self.boss.getX(), self.boss.getY(), self.boss.getZ(), 90) self.alienbullets.append(b) viz.playSound('laser.wav') if num == 6: #Allow player to fire self.Fire = True #Setup all possible dynamically changing text boxes def updateHPText(self): self.hpMsg = "HP: " + str(int(self.playerShip.getHP())) self.hpText.remove() self.hpText = viz.addText(self.hpMsg, viz.SCREEN, pos=[.8, .95, 0]) self.hpText.fontSize(33) def updateLevelText(self): self.levelText.remove() self.levelMsg = "Level: " + str(self.level) self.levelText = viz.addText(self.levelMsg, viz.SCREEN, pos=[.15, .95, 0]) self.levelText.fontSize(33) def updateScoreText(self): self.scoreText.remove() self.scoreMsg = "Score: " + str(self.score) self.scoreText = viz.addText(self.scoreMsg, viz.SCREEN, pos=[.45, .95, 0]) self.scoreText.fontSize(33) def titleScreen(self): #Commands to setup the title screen self.description = viz.addText3D( 'Make a last stand against an endless alien attack \n\n' + 'Use the A and D keys or left and right keys to move ship\n\n' + 'Press the spacebar to fire \n\n' + 'There are 5 different types of aliens\n\n' + 'Red: Shoots back at player\n\n' + 'Blue: Tank takes 3 hits to kill \n\n' + 'Purple: Has both the Blue and Red alien abilities\n\n' + 'Orange: Gives players an extra hitpoint when hit\n\n' + 'Green: Boss alien which will be a challenge to defeat\n\n' + 'Press enter when you are ready to begin!') self.description.font('Comic Sans MS') #Best font self.description.alignment(viz.ALIGN_CENTER) mat = viz.Matrix() mat.postScale(.05, .05, .05) mat.postAxisAngle(1, 0, 0, self.theta) mat.postTrans(0, .3, -.1) self.description.setMatrix(mat)