Пример #1
0
class Game:
    def __init__(self, canvas):

        self.canvas = canvas
        self.font = pygame.font.SysFont('Arial', 48)

        self.components = None
        self.route = None
        self.wealth = 100
        self.score = 0
        self.start_time = None
        self.level_name = ''

        self.levels = ['level01', 'level02', 'level03']
        self.start_level(self.levels[0])

    def next_level(self):
        del self.levels[0]
        self.start_level(self.levels[0])

    def score_point(self):
        self.score += 1
        if self.score >= Settings.target_score:
            self.draw()
            time.sleep(2)
            self.next_level()

    def start_level(self, level):
        self.components = Components(self, level)

        self.route = self.calculate_route()
        self.components.new_runner(self)
        self.level_name = f'Level {level[5:]}'
        self.wealth = 100
        self.score = 0
        self.start_time = datetime.datetime.now()

    @property
    def time(self):
        duration = datetime.datetime.now() - self.start_time
        minutes, seconds = divmod(duration.seconds, 60)
        return f'{minutes}:{seconds:02}'

    @property
    def runners(self):
        return self.components.runners

    def handle_mouse_event(self, event):
        self.components.handle_mouse_event(event)

    def show_wealth(self):
        self.canvas.blit(
            self.font.render(f'{self.wealth}', True, pygame.Color('yellow')),
            utils.cell_to_isometric(Settings.wealth_location).as_int_list
        )

    def show_score(self):
        self.canvas.blit(
            self.font.render(f'{self.score}/{Settings.target_score}', True, pygame.Color('white')),
            utils.cell_to_isometric(Settings.score_location).as_int_list
        )

    def show_time(self):
        time = self.time
        self.canvas.blit(
            self.font.render(time, True, pygame.Color('white')),
            utils.cell_to_isometric(Settings.time_location).as_int_list
        )

    def show_level_name(self):
        self.canvas.blit(
            self.font.render(self.level_name, True, pygame.Color('white')),
            utils.cell_to_isometric(Settings.level_name_location).as_int_list
        )

    def draw(self):
        # TODO: Create background image
        self.canvas.fill((0, 0, 0))

        self.components.draw()

        self.show_wealth()
        self.show_score()
        self.show_time()
        self.show_level_name()

        pygame.display.flip()

    def find_start_tile(self):
        for tile in self.components.filter(type=StaticTile):
            if tile.abstract_tile.is_start:
                return tile

    def neighbours(self, x, y):
        for i, j in [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)]:
            if 0 <= i < self.grid_size[0] and 0 <= j < self.grid_size[1]:
                yield i, j

    def find_neighbour_tile_on_path(self, tile):
        for tile in self.components.filter(type=StaticTile, neighbour=tile):
            if tile.abstract_tile.is_path:
                return tile

    def find_next_step(self, step):
        if step.tile.abstract_tile.is_end:
            return None

        delta = {
            'E': Vector(1, 0),
            'S': Vector(0, 1),
            'W': Vector(-1, 0),
            'N': Vector(0, -1)
        }[step.exit_side]
        next_location = step.grid_location + delta
        next_tile = self.components.filter(type=StaticTile, grid_location=next_location)[0]
        assert next_tile.is_path

        next_entry_side = {
            'E': 'W',
            'W': 'E',
            'N': 'S',
            'S': 'N'
        }[step.exit_side]

        if next_tile.direction in ['EW', 'NS']:
            # Can move in a straight line
            next_exit_side = step.exit_side
        else:
            # Take code (consisting in entry + exit side, but may be in wrong order)
            # remove the entry side, to be left with the exit side
            next_exit_side = [c for c in next_tile.direction if c is not next_entry_side][0]

        return Step(next_location, next_entry_side, next_exit_side, next_tile)

    def calculate_route(self):
        route = []
        start_tile = self.find_start_tile()
        next_tile = self.find_neighbour_tile_on_path(start_tile)
        delta_to_next = next_tile.grid_location -start_tile.grid_location
        exit_side = {
            (1, 0): 'E',
            (0, 1): 'S',
            (-1, 0): 'W',
            (0, -1): 'N'
        }[delta_to_next.as_tuple]

        step = Step(grid_location=start_tile.grid_location, entry_side=None, exit_side=exit_side, tile=start_tile)

        while step is not None:
            route.append(step)
            step = self.find_next_step(step)

        return route

    def tick(self):
        if random.randint(1, 100) == 1:
            self.components.new_runner(self)
        for runner in self.runners:
            runner.take_a_step()
        for tile in self.components.filter(type=TowerTile):
            tile.support_runners()