class Driver(object): def __init__(self, surface): self.surface = surface self.gun = Gun(surface) self.ducks = [Duck(surface), Duck(surface)] self.round = 1 self.phase = 'start' self.score = 0 self.timer = int(time.time()) self.roundTime = 10 # Seconds in a round self.controlImgs = pygame.image.load(os.path.join('media', 'screenobjects.png')) self.hitDucks = [False for i in range(10)] self.hitDuckIndex = 0 self.nextRoundSound = os.path.join('media', 'next-round.mp3') self.flyawaySound = os.path.join('media', 'flyaway.mp3') self.notices = () def handleEvent(self, event): # If we are in the shooting phase, pass event off to the gun if event.type == pygame.MOUSEMOTION: self.gun.moveCrossHairs(event.pos) elif event.type == pygame.MOUSEBUTTONDOWN: gunFired = self.gun.shoot() for duck in self.ducks: if gunFired: if duck.isShot(event.pos): self.score += 10 self.hitDucks[self.hitDuckIndex] = True self.hitDuckIndex += 1 else: duck.flyOff = True def update(self): allDone = False # Update game based on phase if self.phase == 'start': self.startRound() elif self.phase == 'shoot': # Update all ducks for duck in self.ducks: duck.update(self.round) self.manageRound() elif self.phase == 'end': self.endRound() def render(self): # If there is a notice, display and return if len(self.notices) > 0: font = pygame.font.Font(FONT, 20) text = font.render(str(self.notices[0]), True, (255, 255, 255)); x, y = NOTICE_POSITION x = x + (NOTICE_WIDTH - text.get_width()) / 2 y = NOTICE_LINE_1_HEIGHT self.surface.blit(self.controlImgs, NOTICE_POSITION, NOTICE_RECT) self.surface.blit(text, (x, y)); if len(self.notices) > 1: text = font.render(str(self.notices[1]), True, (255, 255, 255)); x, y = NOTICE_POSITION x = x + (NOTICE_WIDTH - text.get_width()) / 2 y = NOTICE_LINE_2_HEIGHT self.surface.blit(text, (x, y)); return # Show the ducks for duck in self.ducks: duck.render() # Show round number font = pygame.font.Font(FONT, 20) text = font.render(("R= %d" % self.round), True, (154, 233, 0), (0, 0, 0)); self.surface.blit(text, ROUND_POSITION); # Show the hit counter self.surface.blit(self.controlImgs, HIT_POSITION, HIT_RECT) startingX, startingY = HIT_DUCK_POSITION for i in range(10): x = startingX + (19 * i) y = startingY if self.hitDucks[i]: self.surface.blit(self.controlImgs, (x, y), HIT_DUCK_RED_RECT) else: self.surface.blit(self.controlImgs, (x, y), HIT_DUCK_WHITE_RECT) # Show the score self.surface.blit(self.controlImgs, SCORE_POSITION, SCORE_RECT) font = pygame.font.Font(FONT, 20) text = font.render(str(self.score), True, (255, 255, 255)); x, y = FONT_STARTING_POSITION x -= text.get_width(); self.surface.blit(text, (x,y)); # Show the cross hairs self.gun.render() def manageRound(self): timer = int(time.time()) # Check round end timesUp = (timer - self.timer) > self.roundTime if not (timesUp or (self.ducks[0].isFinished and self.ducks[1].isFinished)): return # Let any remaining ducks fly off for duck in self.ducks: if not duck.isFinished: duck.flyOff = True return # Check for fly offs and increment the index for duck in self.ducks: if not duck.isDead: self.hitDuckIndex += 1 # Start new around if duck index is at the end if self.hitDuckIndex >= 9: pygame.mixer.music.load(self.nextRoundSound) pygame.mixer.music.play() self.phase = 'end' return # Populate screen with new ducks self.ducks = [Duck(self.surface), Duck(self.surface)] self.timer = int(time.time()) self.gun.reloadIt() def startRound(self): timer = int(time.time()) self.notices = ("ROUND", self.round) if (timer - self.timer) > 2: self.phase = 'shoot' self.notices = () def endRound(self): # Pause game for new round music to play while pygame.mixer.music.get_busy(): return # Count missed ducks - more than 4 and you're done missedCount = 0 for i in self.hitDucks: if i == False: missedCount += 1 if missedCount > 4: self.notices = ("GAME OVER", "") return # Prep for new round self.round += 1 self.hitDucks = [False for i in range(10)] self.hitDuckIndex = 0 self.phase = 'start' self.timer = int(time.time())
class Tower: def __init__(self, i, x, y, s, t=0): self.identity = i self.x = x self.y = y self.size = s self.t_num = t self.box = pygame.Rect((self.x, self.y), (self.size, self.size)) self.level = 1 self.__c_mod = 1.0 # gets smaller self.coolness = 0 # 0 means ready to shoot self.__r_mod = 1.0 # gets bigger self.__p_mod = 1.0 # gets bigger self.__s_mod = 1.0 # gets bigger self.gun = Gun((self.x, self.y), s, t, tower_colors[self.t_num], self.level) self.upgrade_cost = 10 self.follow_mouse = False self.show_r = False self.font = pygame.font.SysFont('Century Gothic', 12) def color(self): return tower_colors[self.t_num] def cooldown(self): return enums.tower_cooldown[self.t_num] * self.__c_mod def range(self): return (enums.tower_range[self.t_num] * self.__r_mod * self.size) + self.size / 2 def power(self): return enums.tower_power[self.t_num] * self.__p_mod def speed(self): return enums.tower_speed[self.t_num] * self.__s_mod def t_type(self): return enums.TowerType(self.t_num) def pos(self): return self.x, self.y def render(self, surf): if self.t_num == 0 or self.t_num == 7: # PATH = 7, ZEROTOWER = 0 pass else: pygame.draw.circle(surf, self.color(), self.box.center, self.size // 2, 4) self.gun.render(surf) text = self.font.render(str(self.level), False, self.color()) surf.blit(text, (self.pos()[0] + 15, self.pos()[1] + 10)) if self.show_r: pygame.draw.circle(surf, red, self.box.center, int(self.range()), 1) def update(self, enemies, on_screen_shots, register): if self.t_num != 0 and self.t_num != 7: aim_spot = (0, 0) for e in enemies: if is_in_circle(e.center(), self.box.center, self.range()): aim_spot = e.pos() if self.coolness <= 0: on_screen_shots.append( Shot(self.box.center, e.id, self.color(), self.speed(), self.power())) register(on_screen_shots[ len(on_screen_shots) - 1]) # register this bullet to be drawn if self.t_num == 1: on_screen_shots[len(on_screen_shots) - 1].poison = True if self.t_num == 2: on_screen_shots[len(on_screen_shots) - 1].ice = True self.coolness = self.cooldown() break if self.coolness > 0: self.coolness -= 1 # point at the first enemy in range self.gun.update(aim_spot) def move(self, pos): self.x = pos[0] self.y = pos[1] self.gun.x = pos[0] self.gun.y = pos[1] self.box = pygame.Rect((self.x, self.y), (self.size, self.size)) def is_in(self, pos): if self.x < pos[0] < self.x + self.size: if self.y < pos[1] < self.y + self.size: return True return False def upgrade(self): self.__c_mod -= 0.05 # gets smaller self.__r_mod += 0.07 # gets bigger self.__p_mod += 1.0 # gets bigger # self.__s_mod += 0.5 # gets bigger self.upgrade_cost += (self.upgrade_cost / 2) self.upgrade_cost = int(self.upgrade_cost * 1.5) self.level += 1 def show_range(self, mouse): if self.is_in(mouse): self.show_r = True else: self.show_r = False