def calibrate(self): self.clear() recognizer = TowerRecognizer(self.difficulty) res = recognizer.calibrate_pygame(self.screen, self.player) if res == 0: return recognizer else: return None
def run(self): #Display settings pygame.mouse.set_visible(True) # mouse visible clock = pygame.time.Clock() # opens clock for fps music.stop(music.channel_menu) music.play(music.channel_game, music.game_music, True) # play music ##### reseting ##### #clear the groups for h in huds: h.kill() ##### create starting objects ##### if self.recognizer is None: self.recognizer = TowerRecognizer(self.difficulty) wave = Wave() wave.start_new_map(self.player.map) game_map = tiledtmxloader.World_map( os.path.join('Resources', 'Map Data', 'map' + str(self.player.map) + '.tmx')) self.player.game_map = game_map next_wave_timer = 300 started_next_wave_timer = True Background() time_to_next_wave_hud = Time_to_next_Wave(next_wave_timer) info_popup = Info_PopUp() info_bar_background = Info_Bar_Background() direction_arrow = Direction_Arrow() sound_toggle_button = Sound_Toggle() speed_toggle_button = Speed_Toggle() pause_button = Pause() main_menu_button = Main_Menu() next_wave_button = Next_Wave() Wave_Info(wave) Life(self.player) detection_info = Detection_Info() manual_shot_button = Manual_Shot_Button() shapes_display = Shapes_Display(self.recognizer.shape_collection) build_tower_bar = Build_Tower_Bar() direction_arrow.start_new_map(self.player) ##### general loop values ##### first_wave_started = False placing_tower = False upgrading_tower = False turret_selected = None running = True self.player.game_over = False self.player.game_won = False self.player.quiting = False game_paused = False active_indices = set() manual_shot = None ################################################################################ while running: clock.tick(FPS) # setting frame rate game_map.map_collision(pause_button.rect) res_img, found_shape_indices, succ_status = self.recognizer.run() detection_info.update(succ_status) # active buttons to build the detected tower/update if found_shape_indices is not None: for index in found_shape_indices: active_indices.add(index) build_tower_bar.buttons[index].is_active = True ##### Events Mouse / Keyboard ##### for event in pygame.event.get(): ##### Quiting ##### if event.type == pygame.QUIT: # click the 'x' to quit return "quit to menu" elif event.type == pygame.KEYDOWN: ##### escape / space buttons ##### if event.key in [pygame.K_ESCAPE, pygame.K_SPACE]: # hit escape to exit if placing_tower: # if we're placing a tower placing_tower = False # not anymore towerplacers.sprite.kill() # kill the placer for t in tower_range_group: t.kill() # destroy the tower_range self.clear_info_menu() elif turret_selected: # if a turret is selected turret_selected = None self.clear_info_menu() # clear all elements on the info menu for r in tower_range_group: # clear the tower range r.kill() elif event.key in [pygame.K_n]: if wave.wave_done: # if the current wave is done wave.start_new_wave() for i in wave_info_group: i.kill() Wave_Info(wave) if not first_wave_started: # check so we only vanish once first_wave_started = True direction_arrow.vanish() # go away elif event.key in [pygame.K_p]: game_paused = True # pause code is at the bottom of the main loop ##### Clicking on stuff ##### elif event.type == pygame.MOUSEBUTTONDOWN: # all the mouse down events if event.button == 3: # right mouse button if placing_tower: # if we're placing a tower placing_tower = False # not anymore towerplacers.sprite.kill() # kill the placer for t in tower_range_group: t.kill() # destroy the tower_range self.clear_info_menu() elif turret_selected: # if a turret is selected turret_selected = None self.clear_info_menu() # clear all elements on the info menu for r in tower_range_group: # clear the tower range r.kill() elif event.button == 1: # left mouse button object_clicked = False click = pygame.mouse.get_pos() # gets position of mouse when clicked #####clicking to place a tower ##### if placing_tower: canceled = False for b in buttons: # click on a in game menu button if b.rect.collidepoint(click): # if we click on a button if b.button_type == 'cancel placement': canceled = True break for button in build_tower_bar.buttons: if button.rect.collidepoint(click): # if we click on a button if towerplacers.sprite.tower_type == button.type: canceled = True break if canceled: placing_tower = False # not anymore towerplacers.sprite.kill() # kill the placer for t in tower_range_group: t.kill() # destroy the tower_range self.clear_info_menu() # clear all elements on the info menu else: for t in towerplacers: if game_map.is_on_map(click) and not game_map.map_collision( t.rect): # if there is no collision with the map game_map.set_collision(click, 'close') # block the tile # build tower on tile Tower(click, t.tower_type) placing_tower = False build_tower_bar.buttons[t.tower_type['id']].is_active = False self.clear_info_menu() # clear all elements on the info menu shapes_display.shape_collection.replace_shape(index=t.tower_type['id']) # clean up and reset t.kill() for tr in tower_range_group: tr.kill() # destroy the tower_range else: info_popup.display_info('You cannot place a tower there!', True) elif upgrading_tower: canceled = False for b in buttons: # click on a in game menu button if b.rect.collidepoint(click): # if we click on a button if b.button_type == 'cancel upgrading': # if its an upgrade button canceled = True break for button in build_tower_bar.buttons: if button.rect.collidepoint(click): # if we click on a button if button.type == UPGRADE: # if its an upgrade button canceled = True break if canceled: upgrading_tower = False # not anymore tower_upgrader.sprite.kill() # kill the placer for t in tower_range_group: t.kill() # destroy the tower_range self.clear_info_menu() # clear all elements on the info menu else: for t in towers: if t.rect.collidepoint(click): # when a turret is clicked on if t.upgrade_counter < MAX_UPGRADE_COUNT: self.clear_info_menu() t.upgrade() tower_upgrader.sprite.kill() build_tower_bar.buttons[UPGRADE['id']].is_active = False # clean up and reset for tr in tower_range_group: tr.kill() # destroy the tower_range upgrading_tower = False else: info_popup.display_info('Upgrade maximum already reached.', True) else: info_popup.display_info('There\'s no tower to upgrade.', True) elif manual_shot_button.is_active: for b in buttons: # click on a in game menu utton if b.rect.collidepoint(click) or manual_shot_button.rect.collidepoint(click): if b.button_type == 'cancel shot': # if its an upgrade button manual_shot_button.is_active = False # not anymore manual_shot_group.sprite.kill() # kill the placer for t in tower_range_group: t.kill() # destroy the tower_range self.clear_info_menu() # clear all elements on the info menu for _ in manual_shot_group: if game_map.is_on_map(click): # if there is no collision with the map manual_shot.shot(click, enemies) else: info_popup.display_info('You cannot shot there!', True) ##### sound on/off button ##### elif sound_toggle_button.rect.collidepoint(click): if music.sound_on: for c in music.channels: c.set_volume(0.0) music.sound_on = False else: for c in music.channels: c.set_volume(1.0) music.sound_on = True sound_toggle_button.change_setting(music.sound_on) #### manual shot button ##### elif manual_shot_button.rect.collidepoint(click): manual_shot_button.is_active = True Button(1, 'cancel shot', None, MANUAL_SHOT) manual_shot = Manual_Shot(click) ##### speed up button ##### elif speed_toggle_button.rect.collidepoint(click): speed_toggle_button.change_setting() self.player.activated_speed = not self.player.activated_speed ##### pause button ##### elif pause_button.rect.collidepoint(click): # if you click on the pause button game_paused = True # pause ##### main menu button ##### elif main_menu_button.rect.collidepoint(click): # if you click on the main menu button self.player.quiting = True ##### next wave button ##### elif next_wave_button.rect.collidepoint(click): # if you click on the next wave button if wave.wave_done: started_next_wave_timer = False next_wave_timer = -1 time_to_next_wave_hud.show_wave_is_coming() wave.start_new_wave() for i in wave_info_group: i.kill() Wave_Info(wave) if not first_wave_started: # check so we only vanish once first_wave_started = True direction_arrow.vanish() # go away ##### check if groups were clicked ##### else: ##### build tower buttons ##### for button in build_tower_bar.buttons: if button.type == UPGRADE and button.rect.collidepoint(click): self.clear_info_menu() # clear all elements on the info menu for t in tower_range_group: # clear the tower range t.kill() TowerUpgrader(click) upgrading_tower = True tower_radius = Upgrade_Stats().radius # get the radius Tower_Range(click, tower_radius) # create a range self.info_menu('tower upgrading', None, UPGRADE) elif button.rect.collidepoint(click): self.clear_info_menu() # clear all elements on the info menu for t in tower_range_group: # clear the tower range t.kill() TowerPlacer(click, button.type) placing_tower = True tower_radius = Tower_Stats(button.type)['radius'] # get the radius Tower_Range(click, tower_radius) # create a range self.info_menu('tower placement', None, button.type) ##### turrets group ##### for t in towers: if t.rect.collidepoint(click): # when a turret is clicked on object_clicked = True turret_selected = t self.clear_info_menu() # clear all elements on the info menu for r in tower_range_group: # clear the tower range r.kill() Tower_Range(t.rect.center, t.range) # create a tower range at the tower center and with range self.info_menu('tower', tower=t) # run the info menu for that tower if not object_clicked: # if we have not clicked on an object if turret_selected: # if a turret is selected turret_selected = None self.clear_info_menu() # clear all elements on the info menu for r in tower_range_group: # clear the tower range r.kill() ############################################################################### # done with user events # ##### controls turret: range/targeting/shooting ##### #put inside a function eventually enemies_by_dist_traveled = self.sort_enemies_group(enemies) for t in towers: # count down till next shot if speed_toggle_button.activated_speed: t.shooting_timer -= 2 else: t.shooting_timer -= 1 if not t.shoots_at_front: # if the tower doesnt shoot at the front of the line if len(enemies) > 0: # if there are enemies on the screen if t.current_target >= len(enemies): # if we are at the end of the enemies list t.current_target = 0 # reset the target that we are testing t.target = enemies.get_sprite(t.current_target) # pick which enemy we are testing if not enemies.has(t.target): # if the target is dead t.current_target += 1 # pick a new target else: # if the target lives # here we get distance from the tower to the target dist = (math.sqrt((t.target.rect.centerx - t.rect.centerx) ** 2 + ( t.target.rect.centery - t.rect.centery) ** 2)) if dist > t.range: # if the target is not in range t.current_target += 1 # test a new target else: # if the target is in range if t.shooting_timer <= 0: # if its time to shoot t.shoot(t.target) # shoot at the target t.shooting_timer = t.speed # reset timer for next shot else: # if the tower shoots at the front of the line if len(enemies_by_dist_traveled) > 0: # if there are enemies on the screen print t.current_target if t.current_target < 0: t.current_target = (len(enemies_by_dist_traveled) - 1) t.target = enemies_by_dist_traveled[t.current_target] # pick which enemy we are testing # here we get distance from the tower to the target dist = (math.sqrt((t.target.rect.centerx - t.rect.centerx) ** 2 + ( t.target.rect.centery - t.rect.centery) ** 2)) if dist > t.range: # if the target is not in range t.current_target -= 1 # test a new target else: # if the target is in range if t.shooting_timer <= 0: # if its time to shoot t.shoot(t.target) # shoot at the target t.shooting_timer = t.speed # reset timer for next shot ##### control the shots ##### for s in shots: # tell every shot which direction to shoot s.move(self.player) ##### creating a new wave ##### if wave.update(self.player): # run the wave update and if it returns true: Enemy(self.player, wave) # create the enemy if wave.wave_done and len(enemies) == 0 and not started_next_wave_timer: next_wave_timer = TIME_TO_NEXT_WAVE started_next_wave_timer = True info_popup.display_info('Finished wave.', True) if started_next_wave_timer: if speed_toggle_button.activated_speed: next_wave_timer -= 2 else: next_wave_timer -= 1 if next_wave_timer < 0: wave.start_new_wave() started_next_wave_timer = False for i in wave_info_group: i.kill() Wave_Info(wave) if not first_wave_started: first_wave_started = True direction_arrow.vanish() ##### when we run out of life ##### if self.player.life <= 0: self.player.game_over = True ##### control game overs ##### if self.player.game_over: info_popup.display_info('GAME OVER', True) # the game is now over music.channel_game.stop() music.play(music.channel_end, music.end_music, True) return "game over" if self.player.game_won: music.channel_game.stop() music.play(music.channel_end, music.end_music, True) #if we beat the game if len(self.player.open_maps) == (self.player.map + 1): return "finished game" else: return "finished_level" if self.player.quiting: return "quit to menu" if game_paused: music.channel_game.pause() music.play(music.channel_end, music.end_music, True) menu = Menu() menu.pause() game_paused = False ##### update the sprites ##### all_update.update(self.player) huds.update(self.player) shapes_display.update() manual_shot_group.update() time_to_next_wave_hud.update(next_wave_timer) if info_popup.displaying_message: info_popup.fade_out() ##### draw everything ##### backgrounds.draw(self.screen) map_draw.draw(self.screen) all_draw.draw(self.screen) enemies.draw(self.screen) life_bars.draw(self.screen) detection_info_group.draw(self.screen) manual_shot_group.draw(self.screen) self.screen.blit(info_bar_background.image, info_bar_background.rect.topleft) self.screen.blit(time_to_next_wave_hud.image, time_to_next_wave_hud.rect.topleft) if placing_tower: # here because it must be drawn on top of everything towerplacers.sprite.move(pygame.mouse.get_pos()) # update the turret placer at the mouse location for t in tower_range_group: t.move(pygame.mouse.get_pos()) elif upgrading_tower: # here because it must be drawn on top of everything tower_upgrader.sprite.move(pygame.mouse.get_pos()) # update the turret placer at the mouse location for t in tower_range_group: t.move(pygame.mouse.get_pos()) elif manual_shot_button.is_active: manual_shot.move(pygame.mouse.get_pos()) huds.draw(self.screen) self.screen.blit(shapes_display.image, shapes_display.rect.topleft) # rotate numpy array 90 degree and switch colors from BGR to RGB self.screen.blit(pygame.surfarray.make_surface(np.rot90(res_img[:, :, ::-1])), (850, 600)) pygame.display.flip()