Código fonte para game.level

import pygame
from game.layout import import_csv_layout
from game.square import StaticSquare, ColisionSquare, CoinSquare, LevelDoor
from entities.player import Player
from entities.enemy import Enemy, EnemyShooter
from game.const import *
from entities.final_boss import FinalBoss
from os import path
from entities.princess import PrincessPinho, Smoke

[documentos] class Level: """Principal fase do jogo a ser carregada. """ def __init__(self, surface:pygame.display, player: Player, level_path='./level/level_1'): """Inicializa a fase Parameters ---------- surface : pygame.display a tela do jogo player : Player o personagem do jogo level_path : str, optional o caminho para o arquivo, by default 'level' """ #setup geral self.display_surface = surface self.player = player self.player_group = pygame.sprite.Group(self.player) self.level_path = level_path self.fonte = pygame.font.Font(None, 36) # terrain setup terrain_layout = import_csv_layout(f'{level_path}/terrain.csv') # fall blocks setup fall_blocks_layout = import_csv_layout(f'{level_path}/fall_blocks.csv') self.terrain_position = pygame.sprite.Group(self.create_terrain(terrain_layout, 'terrain'), self.create_terrain(fall_blocks_layout, 'fall_blocks')) # coins coin_layout = import_csv_layout(f'{level_path}/coins.csv') self.coin_position = self.create_terrain(coin_layout, 'coins') # enemy enemy_layout = import_csv_layout(f'{level_path}/enemies.csv') self.bullet_group = pygame.sprite.Group() self.explosion_group = pygame.sprite.Group() self.enemy_position = self.create_enemies(enemy_layout) # decor_door decor_door_layout = import_csv_layout(f'{level_path}/decor_door.csv') self.decor_door_position = self.create_terrain(decor_door_layout, 'decor_door') # princess princess_layout = import_csv_layout(f'{level_path}/pinho.csv') self.princess_position = self.create_terrain(princess_layout, 'pinho') # door door_layout = import_csv_layout(f'{level_path}/door.csv') self.door_position = self.create_terrain(door_layout, 'door') player_position = import_csv_layout(f'{level_path}/player.csv') self.set_player_position(player_position) self.world_shift = 0 self.first_x = 0 self.last_x = SQUARE_SIZE * len(terrain_layout[0]) self.level_completed = False self.end_timer = 0 self.winning_song = pygame.mixer.Sound('./media/sounds/level_completed.mp3') self.winning_song.set_volume(0.3)
[documentos] def reset(self) -> None: """Reseta o nível do início """ self.__init__(self.display_surface, self.player, self.level_path)
[documentos] def create_terrain(self, layout, type:str) -> pygame.sprite.Group: """Adiciona os elementos ao mapa Parameters ---------- layout : _type_ o layout desejado type : str tipo dos elementos gerados Returns ------- pygame.sprite.Group o grupo do terreno gerado """ squares = pygame.sprite.Group() self.doors = list() for row_index, row in enumerate(layout): for col_index, val in enumerate(row): if val != '-1': x = col_index * SQUARE_SIZE y = row_index * SQUARE_SIZE if type == 'terrain': try: square = StaticSquare(x, y, SQUARE_SIZE, f'./media/blocos/bloco__{val}.png') except: square = ColisionSquare(x, y, SQUARE_SIZE, './media/blocos/bloco__0.png', self.player) elif type == 'fall_blocks': square = ColisionSquare(x, y, SQUARE_SIZE, './media/blocos/bloco_11.png', self.player) elif type == 'coins': square = CoinSquare(x, y, SQUARE_SIZE, './media/coin.png', self.player) elif type == 'door': square = LevelDoor(x, y, SQUARE_SIZE * 2, './media/porta.png', self.player) self.doors.append(square) elif type == 'decor_door': square = ColisionSquare(x, y, SQUARE_SIZE * 2, './media/porta.png', self.player) elif type == "pinho": square = PrincessPinho((x, y)) squares.add(square) return squares
[documentos] def set_player_position(self, layout) -> None: """Define a posição inicial do player Parameters ---------- layout : _type_ o layout desejado """ for row_index, row in enumerate(layout): for col_index, val in enumerate(row): if val == "0": x = col_index * SQUARE_SIZE y = row_index * SQUARE_SIZE self.player.rect.center = (x, y)
[documentos] def create_enemies(self, layout) -> pygame.sprite.Group: """Gera o grupo dos inimigos Parameters ---------- layout : _type_ o layout desejado Returns ------- pygame.sprite.Group o grupo dos inimigos """ enemies = pygame.sprite.Group() for row_index, row in enumerate(layout): for col_index, val in enumerate(row): x = col_index * SQUARE_SIZE y = row_index * SQUARE_SIZE if val == '0': enemies.add(Enemy((x, y))) elif val == '2': enemies.add(EnemyShooter((x, y), self.bullet_group)) elif val == '3': enemies.add(FinalBoss((x, y), self.player, self.bullet_group, self.explosion_group)) enemies.add(enemies.sprites()[-1].gun) return enemies
def _update_world_shift(self) -> None: """Atualiza o deslocamento horizontal dos elementos """ player_pos = self.player.rect.left if player_pos < SCREEN_WIDTH/2 - 50 and self.first_x < 0: self.world_shift = 5 elif player_pos > SCREEN_WIDTH/2 + 50 and self.last_x > SCREEN_WIDTH: self.world_shift = -5 else: self.world_shift = 0 self.first_x += self.world_shift self.last_x += self.world_shift
[documentos] def update_elements(self): """Atualiza todos os elementos """ if not self.player.alive(): self.player.reset() self.reset() self.terrain_position.update(self.world_shift) self.enemy_position.update(self.terrain_position, self.world_shift) self.coin_position.update(self.world_shift) self.door_position.update(self.world_shift) self.decor_door_position.update(self.world_shift) self.player.collide_with_enemy(self.enemy_position) self.player.update(self.terrain_position, self.world_shift) self.bullet_group.update(self.player, self.world_shift) self.explosion_group.update() self.princess_position.update()
def _draw_coin_text(self): """Gera o contador de moedas na tela """ texto = self.fonte.render(f"Coins: {self.player.coin_count}", True, "#f0f8ff") text_rect = texto.get_rect(topleft=(10, 10)) self.display_surface.blit(texto, text_rect)
[documentos] def draw_elements(self): """Adiciona os elementos a tela """ self.princess_position.draw(self.display_surface) self.terrain_position.draw(self.display_surface) self.coin_position.draw(self.display_surface) self.door_position.draw(self.display_surface) self.decor_door_position.draw(self.display_surface) self.enemy_position.draw(self.display_surface) self.player_group.draw(self.display_surface) self.bullet_group.draw(self.display_surface) self.explosion_group.draw(self.display_surface) self._draw_coin_text()
[documentos] def game_run(self): """Faz o jogo rodar """ self.draw_elements() self._update_world_shift() self.update_elements()
def _check_game_completed(self) -> bool: """Checa se o jogo foi completado Returns ------- bool True caso sim e False caso não """ state = False for level_door in self.doors: if level_door.level_completed: state = True return state def _play_winning_song(self): """Toca a música de vitória """ self.winning_song.play() def _game_finishing(self): """Realiza a cena de finalização do jogo """ self._play_winning_song() self.draw_elements() self._fill_screen(0.3) self.end_timer += 1 if self.end_timer >= FPS * 1.5: self.level_completed = True def _fill_screen(self, timer_factor:float, reverse=False): """Preenche a tela de preto aos poucos Parameters ---------- timer_factor : float o fator de velocidade, quanto maior mais lento reverse : bool, optional Se ele deve escurecer ou clarear, by default False """ fade_image = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT)).convert_alpha() fade_image.fill("black") fade = fade_image.get_rect() if reverse: fade_alpha = 255 - int(self.end_timer/timer_factor) else: fade_alpha = int(self.end_timer/timer_factor) fade_image.set_alpha(fade_alpha) self.display_surface.blit(fade_image, fade)
[documentos] def run(self): """Faz o jogo rodar """ if not self._check_game_completed(): self.game_run() else: self._game_finishing()
[documentos] class BossLevel(Level): """A fase do boss a ser derrotado """ def __init__(self, surface:pygame.display, player: Player, level_path='./level/boss_level'): """Inicializa a fase Parameters ---------- surface : pygame.display a tela do jogo player : Player o personagem do jogo level_path : str, optional o caminho para o arquivo, by default 'boss_level' """ super().__init__(surface, player, level_path) self.boss = FinalBoss((1250,0), self.player, self.bullet_group, self.explosion_group) self.enemy_position.add(self.boss) self.enemy_position.add(self.boss.gun) self.boss.initial_pos = SQUARE_SIZE * 10 self.boss.x_vel *= 3 self.boss.move_range = 1200 self.started = False self.princess = self.princess_position.sprites()[-1]
[documentos] def init_run(self): self.boss.facing = -1 self.update_elements() self.boss.move_counter = 0 self.boss.shot_time = 0 self.draw_elements() if self.boss.rect.x <= self.boss.initial_pos: self.boss.move_range = INITIAL_RANGE self.boss.x_vel /= 3 self.player.x_vel = PLAYER_X_VEL self.started = True
[documentos] def run(self): if self.started: self.game_run() else: self.player.x_vel = 0 self.init_run() self.initialized = True
def _update_world_shift(self) -> None: """Atualiza o deslocamento horizontal dos elementos """ self.world_shift = 0
[documentos] def game_run(self): super().game_run() if self.boss.health <= 0 and self.princess.animation_list == 0: self.princess.change_list() self.princess_position.add(Smoke(self.princess.rect.center))