示例#1
0
    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
示例#2
0
    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()