Exemple #1
0
class Game(Foundation):
    """
    A class that is responsible for running the game and handling all the
    game related activities.
    """
    def __init__(self, caption=None, icon=None):
        super().__init__(caption, icon)
        self.snake = Snake()
        self.food = Food()
        self.food_consumed_sound = Sound("consumed.wav")
        self.death_sound = Sound("death.mp3")
        self.bg_sound = Sound("background.mp3")
        self.background = Background()
        self.play = False
        self.score = 0
        self.game_over = False
        self.delay = 3
        self.snake_die_time = None
        # self.bg = pygame.Surface((440, 440))

    def draw_grid(self):
        border = 0  # Settings.BLOCK_SIZE * 2 - 1
        h = Settings.SCREEN_HEIGHT - border
        w = Settings.SCREEN_WIDTH - border

        for row in range(border, h, Settings.BLOCK_SIZE):
            pygame.draw.line(self.screen, Colors.GREY.value, (border, row),
                             (w, row))

        for col in range(border, w, Settings.BLOCK_SIZE):
            pygame.draw.line(self.screen, Colors.GREY.value, (col, border),
                             (col, h))

    def play_game(self, key_pressed):
        """
        Start game on pressing the space bar key.
        :param key_pressed:
        :return: None
        """

        if key_pressed == K_SPACE and not self.play:
            self.snake.head_direction = 'Left'
            self.play = True
            # Setup the background sound but pause it by default
            self.bg_sound.play_sound(loops=-1, vol=0.01)
            self.bg_sound.pause_sound()
            self.background.create_background()

    def quit_game(self, key_pressed):
        """
        Quit game on pressing the escape key.
        :return: None
        """

        if key_pressed == K_ESCAPE:
            self.running = False

    def render_score(self):
        text = "Score: " + str(self.score)
        score_surf = self.font.render(text, True, Colors.GREY.value)
        score_surf.set_alpha(127)
        self.screen.blit(score_surf, (0, 0))

    def game_over_render_delay(self):
        current_time = pygame.time.get_ticks()
        if current_time >= self.snake_die_time + self.delay*1000:
            self.running = False

    def render_game_over(self):
        text = "Game Over!"
        game_over_surf = self.font.render(text, True, Colors.RED.value)
        surf_rect = game_over_surf.get_rect(center=self.screen.get_rect().center)
        self.screen.blit(game_over_surf, surf_rect)
        self.game_over_render_delay()

    def snake_hit_food(self):
        head = self.snake.blocks_pos[0]
        if head == self.food.position:
            self.food_consumed_sound.play_sound(vol=0.1)
            self.snake.increase_snake_length()
            self.score += 1
            return True
        return False

    def snake_hit_itself(self):
        head = self.snake.blocks_pos[0]
        if head in self.snake.blocks_pos[1:]:
            self.death_sound.play_sound(vol=0.3)
            pygame.time.delay(1000)
            # self.running = False
            self.play = False
            self.game_over = True
            self.snake_die_time = pygame.time.get_ticks()
            return True
        return False

    def update_game_state(self):
        """
        Update states of the game objects.
        :return: None
        """
        if self.play:
            self.background.update()
            hit_food = self.snake_hit_food()
            hit_itself = self.snake_hit_itself()
            if not hit_food and not hit_itself:
                self.snake.update()
            # Update food position until food is not one of the snake block
            if hit_food and not hit_itself:
                while True:
                    self.food.update()
                    if self.food.position not in self.snake.blocks_pos:
                        break

    def render_objects(self):
        """
        Draw all the game objects to the main game window/screen
        :return: None
        """

        self.screen.fill(Settings.BG_COLOR)  # Not needed if creating tiles.
        if self.play:
            # self.draw_grid()
            self.background.render(self.screen)
            self.snake.render(self.screen)
            self.food.render(self.screen)
            self.render_score()

        elif self.game_over:
            self.render_game_over()

        # Todo: Dirty rectangles
        pygame.display.flip()  # Updates the entire screen

    def handle_keydown_events(self, event):
        """
        Handle all key press events.
        :param event: Event requested by user
        :return: None
        """

        self.play_game(event.key)
        self.quit_game(event.key)

        if self.play:
            if event.key == K_RIGHT and self.snake.head_direction != 'Left':
                self.snake.head_direction = 'Right'
            elif event.key == K_LEFT and self.snake.head_direction != 'Right':
                self.snake.head_direction = 'Left'
            elif event.key == K_DOWN and self.snake.head_direction != 'Up':
                self.snake.head_direction = 'Down'
            elif event.key == K_UP and self.snake.head_direction != 'Down':
                self.snake.head_direction = 'Up'
            elif event.key == K_p:
                self.bg_sound.pause_sound()

    def handle_keyup_events(self, event):
        """
        Handle all key release events.
        :param event: Event requested by user
        :return: None
        """

        pass