class GameStateManager(): def __init__(self): pygame.init() pygame.display.set_mode([WIDTH, HEIGHT]) pygame.display.set_caption("Pygame Tilebased RPG") pygame.key.set_repeat(100) self.SURFACE = pygame.display.get_surface() self.current_state = HUMS_STATE self.input_handler = InputHandler() self.camera = Camera(32, 24) self.states = self.create_states() self.player = Player(self, 18, 18, 100, 5, 5) self.walls = self.states[self.current_state].walls self.doors = self.states[self.current_state].doors self.npcs = self.states[self.current_state].npcs def update(self): self.draw_grid() self.draw_map() self.player.update() #self.player.draw(self.camera.apply(self.player)) self.player.draw() self.camera.update(self.player) def change_state(self, state): self.current_state = state self.walls = self.states[self.current_state].walls self.doors = self.states[self.current_state].doors self.npcs = self.states[self.current_state].npcs def create_states(self): states = [None] * NUM_STATES states[HUMS_STATE] = HumsState(self) states[HUMS_INN_STATE] = HumsInnState(self) return states def draw_grid(self): for x in range(0, WIDTH, TILESIZE): pygame.draw.line(pygame.display.get_surface(), BLACK, (x, 0), (x, HEIGHT)) for y in range(0, HEIGHT, TILESIZE): pygame.draw.line(pygame.display.get_surface(), BLACK, (0, y), (WIDTH, y)) def draw_map(self): for x in range(len(self.walls)): self.walls[x].update() self.walls[x].draw(RED) for x in range(len(self.doors)): self.doors[x].update() self.doors[x].draw(BLUE) for x in range(len(self.npcs)): self.npcs[x].update() self.npcs[x].draw() def clear_screen(self): pygame.display.get_surface().fill((255, 255, 255))
class Game: def __init__(self, window, first=True): self.window = window self.window_width, self.window_height = window.get_size() self.running = True self.willTabQuit = True self.score = 0 self.bg = pygame.image.load(str(Path('./assets/bg.jpg'))) self.font = pygame.font.SysFont('Hack', 14, True) self.midFont = pygame.font.SysFont('Hack', 24, True) self.bigFont = pygame.font.SysFont('Hack', 80, True) self.player = Player(self.window) self.bullet = Bullet(self.window, self.player) self.enemy = Enemy(self.window) self.display = True self.count = 0 self.state = 'menu' if first else 'start' # Main Game State def run(self): if self.state == 'menu': self.menu() elif self.state == 'start': self.start() elif self.state == 'over': self.game_over() # Starts game def start(self): for event in pygame.event.get(): if event.type is pygame.QUIT: self.running = False if event.type is pygame.KEYDOWN: if event.key is pygame.K_TAB and self.willTabQuit: self.running = False if event.key is pygame.K_a: self.player.toggleMoving(True) self.player.moveLeft() if event.key is pygame.K_d: self.player.toggleMoving(True) self.player.moveRight() if event.key is pygame.K_w: self.player.toggleMoving(True) self.player.moveUp() if event.key is pygame.K_s: self.player.toggleMoving(True) self.player.moveDown() if event.key is pygame.K_SPACE: if self.bullet.bullet_state == 'ready': self.bullet.setShootingPos(self.player.playerX) self.bullet.bullet_state = 'shoot' if event.type is pygame.KEYUP: self.player.toggleMoving(False) # Draw Entities self.draw_window() # Draws All Entities On Window def draw_window(self): # Moves Player When Key Pressed if self.player.moving: self.player.move() # Draws Bullet On State self.bullet.draw() # Draws Enemy self.enemy.move() self.enemy.draw() # Checks Bullet-Enemy Collide if self.bullet.checkCollide(self.enemy): self.enemy.randomizePosition() self.score += 1 # Game Over State if self.enemy.isGameOver(): self.state = 'over' # Draws Player self.player.draw() # Update Player Position self.window.blit(self.update_pos(), (self.window_width - 140, 0)) # Draw Score self.window.blit(self.update_score(), (5, 20)) # Start Menu def menu(self): for event in pygame.event.get(): if event.type is pygame.QUIT: self.running = False if event.type is pygame.KEYDOWN: if event.key is pygame.K_TAB and self.willTabQuit: self.running = False if event.key is pygame.K_SPACE: self.__init__(self.window, False) self.state = 'start' # Game Title text title = 'Space Shooter' title_text = self.bigFont.render(title, 1, pygame.Color('white')) title_width, title_height = title_text.get_size() title_x, title_y = self.window_width / 2 - title_width / \ 2, self.window_height/2 - title_height/2 # Start Prompt Text start = 'Press Space To Start' start_text = self.midFont.render(start, 1, pygame.Color('white')) start_width, start_height = start_text.get_size() start_x, start_y = self.window_width / 2 - start_width / \ 2, self.window_height/2 - start_height/2 + (title_height/2) + 10 self.window.blit(title_text, (title_x, title_y)) # Blinking text self.count += 1 if self.count > 30: self.count = 0 self.display = not self.display if self.display: self.window.blit(start_text, (start_x, start_y)) # Game Over Menu def game_over(self): for event in pygame.event.get(): if event.type is pygame.QUIT: self.running = False if event.type is pygame.KEYDOWN: if event.key is pygame.K_TAB and self.willTabQuit: self.running = False if event.key is pygame.K_SPACE: self.__init__(self.window, False) self.state = 'start' # Game Over Text over = 'GAME OVER' game_over_text = self.bigFont.render(over, 1, pygame.Color('white')) over_width, over_height = game_over_text.get_size() over_x, over_y = self.window_width / 2 - over_width / \ 2, self.window_height/2 - over_height/2 # Continue Prompt Text con = 'Press Space To Continue' continue_text = self.midFont.render(con, 1, pygame.Color('white')) con_width, con_height = continue_text.get_size() con_x, con_y = self.window_width / 2 - con_width / \ 2, self.window_height/2 - con_height/2 + (over_height/2) + 10 # Score Text score = f'Score: {self.score}' score_text = self.midFont.render(score, 1, pygame.Color('white')) score_width, score_height = score_text.get_size() score_x, score_y = self.window_width / 2 - score_width / \ 2, self.window_height/2 - score_height/2 - (over_height/2) - 10 self.window.blit(game_over_text, (over_x, over_y)) self.window.blit(score_text, (score_x, score_y)) # Blinking Text self.count += 1 if self.count > 30: self.count = 0 self.display = not self.display if self.display: self.window.blit(continue_text, (con_x, con_y)) def update_pos(self): pos = f'X: {self.player.playerX} Y: {self.player.playerY}' pos_text = self.font.render(pos, 1, pygame.Color("white")) return pos_text def update_score(self): score = f'Score: {self.score}' score_text = self.font.render(score, 1, pygame.Color("white")) return score_text
class World(object): def __init__(self, amount_tiles_x, amount_tiles_y, audio_manager, score): self.audio_manager = audio_manager self.score = score self.amount_tiles_x = amount_tiles_x self.amount_tiles_y = amount_tiles_y self.grid = Grid(self.amount_tiles_x, self.amount_tiles_y, self) self.player = Player(self, audio_manager) self.zombie_handler = ZombieHandler(self) self.dog_handler = DogHandler(self) self.emitter_handler = EmitterHandler(self.zombie_handler) self.destination = Destination(self) self.destination_flag = DestinationFlag(self) self.compass = Compass(self) self.delivery_status = DeliveryStatus(self) self.inventory = Inventory(self) self.health_bar = HealthBar(self.player) self.pizza = None self.populated_tiles = [[False for _ in range(Constant.GRID_HEIGHT)] for _ in range(Constant.GRID_WIDTH)] self._update_spawn_regions( convert_world_to_grid_position(self.player.x, self.player.y)) def handle_input(self, event): self.player.handle_input(event) def step(self): self.emitter_handler.step() player_grid_location_before = convert_world_to_grid_position( self.player.x, self.player.y) self.player.step() player_grid_location_after = convert_world_to_grid_position( self.player.x, self.player.y) if player_grid_location_after != player_grid_location_before: self._update_spawn_regions(player_grid_location_after) self.destination.step() self.zombie_handler.step() self.dog_handler.step() if self.pizza: self.pizza.step() def draw(self, screen: Surface, camera: Camera): # Grid self.grid.draw(screen, camera) self.destination_flag.draw(screen, camera) # Sound circle self.emitter_handler.draw(screen, camera) if self.pizza: self.pizza.draw(screen, camera) # Moving entites self.dog_handler.draw(screen, camera) self.player.draw(screen, camera) self.zombie_handler.draw(screen, camera) # UI self.compass.draw(screen, camera) self.delivery_status.draw(screen) self.inventory.draw(screen, camera) self.health_bar.draw(screen) def _update_spawn_regions(self, pos): x, y = pos new_grid = [[False for _ in range(Constant.GRID_HEIGHT)] for _ in range(Constant.GRID_WIDTH)] new_regions = set() for dx in range(-Constant.GRID_SPAWN_RANGE, Constant.GRID_SPAWN_RANGE + 1): for dy in range(-Constant.GRID_SPAWN_RANGE, Constant.GRID_SPAWN_RANGE + 1): if self.grid.is_in_grid(x + dx, y + dy): new_grid[x + dx][y + dy] = True if not self.populated_tiles[x + dx][y + dy]: new_regions.add((x + dx, y + dy)) for region in new_regions: self._spawn_in_tile(region) del self.populated_tiles self.populated_tiles = new_grid def _spawn_in_tile(self, region): dist_to_center = distance( region, (Constant.GRID_WIDTH // 2, Constant.GRID_HEIGHT // 2)) world_x, world_y = region[0] * Constant.TILE_SIZE, region[ 1] * Constant.TILE_SIZE if self.grid.grid[region[0]][region[1]].type in { CellType.NATURE, CellType.ROAD } and dist_to_center > 4: zombies = 0 if int(Constant.AVG_ZOMBIES_PER_TILE_DISTANCE_FROM_CENTER * dist_to_center) > 0: zombies = random.randint( 0, int(Constant.AVG_ZOMBIES_PER_TILE_DISTANCE_FROM_CENTER * dist_to_center)) blue_zombie = Constant.BLUE_ZOMBIE_PROB_INCREASE_PER_TILE_DISTANCE_FROM_CENTER * dist_to_center > random.random( ) dog = Constant.DOG_PROB_INCREASE_PER_TILE_DISTANCE_FROM_CENTER * dist_to_center > random.random( ) for _ in range(zombies): x, y = int(world_x + random.random() * Constant.TILE_SIZE), int( world_y + random.random() * Constant.TILE_SIZE) self.zombie_handler.add_zombie(Zombie(x, y, self)) if blue_zombie: x, y = int(world_x + random.random() * Constant.TILE_SIZE), int( world_y + random.random() * Constant.TILE_SIZE) self.zombie_handler.add_zombie( Zombie(x, y, self, is_super_zombie=True)) if dog: x, y = int(world_x + random.random() * Constant.TILE_SIZE), int( world_y + random.random() * Constant.TILE_SIZE) self.dog_handler.add_dog(Dog(x, y, self.player, self))
def game(): fps = 60 game_loop = True # player player = Player(width, height) # ball ball = Ball(width, height) game_over = False # blocks blocks = [] b_width, b_height = width // 5 - 20, height // (4 * 5) - 10 x, y = 30, 10 for i in range(5): for j in range(5): blocks.append(Block(height, width, b_width, b_height, x, y, (random.randint(20, 255), random.randint(20, 255), random.randint(20, 255)))) # block color never black x += 10 + b_width y += 10 + b_height x = 30 # score max_score = len(blocks) while game_loop: for e in pygame.event.get(): if e.type == pygame.QUIT: return # check for user input keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: player.moveX(player.velocity * -1) if keys[pygame.K_RIGHT]: player.moveX(player.velocity) if not game_over: game_over = ball.move(player) ball.check_collision(blocks) if not game_over: game_over = len(blocks) == 0 # clearing screen window.fill((0, 0, 0)) if game_over: # Game Over text go_label = font.render("Game Over!", True, (255, 255, 255)) score_label = font.render("Score: " + str(max_score - len(blocks)), True, (255, 255, 0)) window.blit(go_label, ((width - 150) // 2, (height - 150) // 2)) window.blit(score_label, ((width - 120) // 2, (height - 60) // 2)) # Try Again button if _render_btn("Try again", ((width - btn_width) // 2, 0.75 * height), pygame.mouse.get_pos()): game_loop = False continue else: # drawing entities player.draw(window) ball.draw(window) for block in blocks: block.draw(window) # updates pygame.display.update() clock.tick(fps)
def play(screen: pygame.surface.Surface, level_number: int = 1, user_seed: str = None) -> int: """ Функция запуска игрового процесса :param screen: Экран для отрисовки :param level_number: Номер текущего уровня :param user_seed: Сид карты. Если он есть, по нему создаются уровни, раставляются враги и прочее :return: Код завершения игры (значения описаны в main.py) """ # Псевдо загрузочный экран (для красоты) loading_screen(screen) # Размеры экрана screen_width, screen_height = screen.get_size() # Группа со всеми спрайтами all_sprites = pygame.sprite.Group() # Группа со спрайтами тайлов пола tiles_group = pygame.sprite.Group() # Группа со спрайтами ящиков и бочек # (они отдельно, т.к. это разрушаемые объекты) furniture_group = pygame.sprite.Group() # Группа со спрайтами преград (т.е. все физические объекты) collidable_tiles_group = pygame.sprite.Group() # Группа со спрайтами врагов enemies_group = pygame.sprite.Group() # Группа со спрайтами дверей doors_group = pygame.sprite.Group() # Группа со спрайтами факелов torches_group = pygame.sprite.Group() # Группа со спрайтом конца уровня (т.е. с лестницой перехода вниз) end_of_level = pygame.sprite.Group() # Группа с предметаими, которые находятся на полу GroundItem.sprites_group = pygame.sprite.Group() # Группа с сундуками Chest.chest_group = pygame.sprite.Group() is_open = True # Поверхность для эффекта затемнения transparent_grey = pygame.surface.Surface((screen_width, screen_height), pygame.SRCALPHA).convert_alpha() clock = pygame.time.Clock() # Часы current_seed = user_seed # текущий сид # Создаем уровень с помощью функции из generation_map level, level_seed = generate_new_level( current_seed.split('\n')[0].split() if current_seed else 0) # Игрок (None, т.к. будет переопределён либо при инициализации, либо при по) player = None if current_seed: data = current_seed.split('\n') # Данные из сида # Получение данных об игроке из сида и создание игрока _, _, player_level, health, mana, money = data[3].split()[:-1] player = Player(0, 0, player_level, all_sprites, health, mana, money) # Получение данных об асистентах игрока for n in range(int(data[3].split()[-1])): # Получениев параметров асистента и его создание x1, y1, health, mana, *name = data[4 + n].split() assistant = PlayerAssistant(0, 0, player, all_sprites, health, mana, name) # Добавление асистента player.add_assistant(assistant) # Необходимые аргументы для инициализации уровня args = (level, level_number, all_sprites, tiles_group, furniture_group, collidable_tiles_group, enemies_group, doors_group, torches_group, end_of_level, current_seed.split('\n')[1].split() if current_seed else [], current_seed.split('\n')[2].split() if current_seed else [], player) # Инициализация уровня и получение данных об игроке и частях сида player, monsters_seed, boxes_seed = initialise_level(*args) if current_seed: # Если сид был передан, сдвигаем игрока на расстояние от начала уровня (лестницы) # Которое было записано в сид x_from_start, y_from_start = map( float, current_seed.split('\n')[3].split()[:2]) player.rect.center = player.rect.centerx + x_from_start, player.rect.centery + y_from_start # Смещение всех асистентов игрока for assistant in player.assistants: assistant.rect.center = player.rect.center # Обновление и сохранение сида после инициализации уровня current_seed = '\n'.join([ ' '.join(level_seed), ' '.join(monsters_seed), ' '.join(boxes_seed), str(player), str(level_number) ]) save(current_seed) camera = Camera(screen.get_size()) # камера # Инициализация начальной позиции прицела игрока player.scope.init_scope_position((screen_width * 0.5, screen_height * 0.5)) # Шрифт для вывода фпс в левом верхнем углу fps_font = load_game_font(48) # Иконка рядом с номером уровня (в правом верхнем углу) level_number_icon = load_tile('DOWNSTAIRS.png') # Иконка рядом с количеством врагов на уровне (в правом верхнем углу) monster_number_icon = load_image( 'assets/sprites/UI/icons/monster_number.png', (TILE_SIZE, ) * 2) # Шрифт для вывода номера уровня и количества врагов level_and_enemies_font = load_game_font(64) # Сообщение, которое будет появлятся при приближении игрока к сундуку chest_title = Message(screen, 'Нажмите Е (или L2), чтобы открыть сундук', screen.get_height() * 0.1) # Сообщение, которое будет появлятся при приближении игрока к спуску вниз downstairs_title = Message( screen, 'Нажмите Е (или L2), чтобы перейти на следующий уровень', screen.get_height() * 0.1) # Иконки для отображения иконок (контейнеров) с заклинаниями внизу экрана spells_containers = ( SpellContainer("fire_spell.png", FireSpell, player), SpellContainer("ice_spell.png", IceSpell, player), SpellContainer("poison_spell.png", PoisonSpell, player), SpellContainer("void_spell.png", VoidSpell, player), SpellContainer("light_spell.png", FlashSpell, player), SpellContainer("teleport_spell.png", TeleportSpell, player), ) # Панель с иконкой и информацией об игроке в левом верхнем углу player_icon = PlayerIcon(player) # Высота для высчитывания позиции отрисовки иконки асистента assistants_height = 180 # Отступ для вывода иконки игрока и его ассистентов indent = 20 # Фоновая музыка pygame.mixer.music.load("assets/audio/music/game_bg.ogg") pygame.mixer.music.play(-1) pygame.mixer.music.set_volume(DEFAULT_MUSIC_VOLUME) # Установка событий, обрабатываемых pygame, чтобы не тратить # время на обработку ненужных событий (это относится ко всей игре в целом, # где обрабатываются события) pygame.event.set_allowed(( pygame.QUIT, pygame.MOUSEBUTTONUP, pygame.KEYDOWN, )) # Игровой цикл while is_open: was_pause_activated = False # была ли активирована пауза keys = pygame.key.get_pressed() # нажатые клавиши buttons = pygame.mouse.get_pressed(5) # нажатые кнопки мыши for event in pygame.event.get(): if event.type == pygame.QUIT: is_open = False if event.type == pygame.KEYDOWN: if event.key == CONTROLS["KEYBOARD_PAUSE"]: was_pause_activated = True # Провверка использования заклинаний с джойстика if player.joystick: if player.joystick.get_button(CONTROLS["JOYSTICK_UI_PAUSE"]): was_pause_activated = True if player.joystick.get_button(CONTROLS["JOYSTICK_SPELL_FIRE"]): player.shoot('fire', enemies_group) if player.joystick.get_button(CONTROLS["JOYSTICK_SPELL_ICE"]): player.shoot('ice', enemies_group) if player.joystick.get_button(CONTROLS["JOYSTICK_SPELL_LIGHT"]): player.shoot('flash', enemies_group) if player.joystick.get_button(CONTROLS["JOYSTICK_SPELL_POISON"]): player.shoot('poison', enemies_group) if player.joystick.get_button(CONTROLS["JOYSTICK_SPELL_VOID"]): player.shoot('void', enemies_group) # Используется ось, т.к. назначен триггер R2 if player.joystick.get_axis(CONTROLS["JOYSTICK_SPELL_TELEPORT"] ) > JOYSTICK_SENSITIVITY: player.shoot('teleport', tiles_group) # Иначе ввод с клавиатуры else: if keys[CONTROLS["KEYBOARD_SPELL_FIRE"]] or buttons[ CONTROLS["MOUSE_SPELL_FIRE"]]: player.shoot('fire', enemies_group) if keys[CONTROLS["KEYBOARD_SPELL_ICE"]] or buttons[ CONTROLS["MOUSE_SPELL_ICE"]]: player.shoot('ice', enemies_group) if keys[CONTROLS["KEYBOARD_SPELL_LIGHT"]] or buttons[ CONTROLS["MOUSE_SPELL_LIGHT"]]: player.shoot('flash', enemies_group) if keys[CONTROLS["KEYBOARD_SPELL_POISON"]] or buttons[ CONTROLS["MOUSE_SPELL_POISON"]]: player.shoot('poison', enemies_group) if keys[CONTROLS["KEYBOARD_SPELL_VOID"]]: player.shoot('void', enemies_group) if keys[CONTROLS["KEYBOARD_SPELL_TELEPORT"]]: player.shoot('teleport', tiles_group) # Обработка паузы if was_pause_activated: # # Остановка звуков и музыки pygame.mixer.pause() pygame.mixer.music.pause() # Запуск меню паузы code = game_menu.execute(screen) if code == 1: # Псевдо экран загрузки перед следующими действиями (для красоты) loading_screen(screen) # Очищаем все группы со спрайтами all_sprites.empty() tiles_group.empty() furniture_group.empty() collidable_tiles_group.empty() enemies_group.empty() doors_group.empty() torches_group.empty() end_of_level.empty() Chest.chest_group.empty() GroundItem.sprites_group.empty() Entity.damages_group.empty() # Сохранение данных перед выходом save('') return 2 if code is not None: # Ставим экран загрузки перед следующими действиями loading_screen(screen) # Очищаем все группы со спрайтами all_sprites.empty() tiles_group.empty() furniture_group.empty() collidable_tiles_group.empty() enemies_group.empty() doors_group.empty() torches_group.empty() end_of_level.empty() Chest.chest_group.empty() GroundItem.sprites_group.empty() Entity.damages_group.empty() # Сохранение данных перед выходом if player.alive: current_seed = '\n'.join([ ' '.join(level_seed), ' '.join(monsters_seed), ' '.join(boxes_seed), str(player), str(level_number) ]) save(current_seed) else: save('') return -1 # Возвращение звука и мызыки так, как было до паузы pygame.mixer.unpause() pygame.mixer.music.unpause() screen.fill(BACKGROUND_COLOR) # Очистка экрана player.update() # Обновление игрока # Если игрок умер, то открывается экран конца игры if player.destroyed: # Остановка звуков и музыки pygame.mixer.pause() pygame.mixer.music.pause() # Подсчёт количества живых асистентов у игрока (для вывода статистики) count_of_alive_assistants = 0 for sprite in player.assistants.sprites(): sprite: PlayerAssistant # Если асистент живой увеличиваем счётчик count_of_alive_assistants += int(sprite.alive) # Запуск экрана с концом end_screen.execute(screen, player.money, count_of_alive_assistants) return -1 # Проверка на столкновение с любым сундуком if pygame.sprite.spritecollideany(player, Chest.chest_group): # Обновление времени столкновения с сундуком для # красивой отрисовки сообщения chest_title.last_collide_time = pygame.time.get_ticks() # Проверка на использование (с джойстика или клавиатуры) if ((player.joystick and player.joystick.get_axis( CONTROLS['JOYSTICK_USE']) > JOYSTICK_SENSITIVITY) or (keys[CONTROLS['KEYBOARD_USE']])): pygame.sprite.spritecollide(player, Chest.chest_group, False)[0].open() enemies_group.update(player) # обновление врагов player.assistants.update(enemies_group) # обновление асистентов Entity.spells_group.update() # обновление заклинаний # Обновление факелов (для звука огня по расстоянию до факела) torches_group.update(player) # Обновление всех дверей doors_group.update(player, enemies_group, [player] + list(player.assistants)) Chest.chest_group.update() # обновление сундуков Entity.damages_group.update() # обновление текста с выводом урона # Проверка перехода на следующий уровень, при соприкосновении с лестницой вниз if pygame.sprite.spritecollideany(player.collider, end_of_level): # Обновление времени столкновения с лестницой вниз для # красивой отрисовки сообщения downstairs_title.last_collide_time = pygame.time.get_ticks() if (keys[pygame.K_e] or (player.joystick and player.joystick.get_axis( CONTROLS['JOYSTICK_USE']) > JOYSTICK_SENSITIVITY)): # Затухание музыки и звуком pygame.mixer.fadeout(1000) pygame.mixer.music.fadeout(1000) # Псевдо загрузочный экран для красоты loading_screen(screen) # Если игрок прошёл 10 уровней, то это победа if level_number == 10: # Подсчёт количества живых асистентов у игрока (для вывода статистики) count_of_alive_assistants = 0 for sprite in player.assistants.sprites(): sprite: PlayerAssistant # Если асистент живой увеличиваем счётчик count_of_alive_assistants += int(sprite.alive) # Победный экран end_screen.execute(screen, player.money, count_of_alive_assistants, is_win=True) return -1 # Иначе перезагружаются параметры для нового уровня else: # Очистка всех групп со спрайтами all_sprites.empty() tiles_group.empty() furniture_group.empty() collidable_tiles_group.empty() enemies_group.empty() doors_group.empty() torches_group.empty() end_of_level.empty() Chest.chest_group.empty() GroundItem.sprites_group.empty() Entity.damages_group.empty() level_number += 1 # увеличение номер уровня # Создание целиком нового уровень функцией из generation_map level, level_seed = generate_new_level(0) # Необходимые аргументы для инициализации уровня args = (level, level_number, all_sprites, tiles_group, furniture_group, collidable_tiles_group, enemies_group, doors_group, torches_group, end_of_level, [], []) # Инициализация уровня и получение данных об игроке и частях сида player, monsters_seed, boxes_seed = initialise_level( *args, player=player) # Добавление игрока и асистентов all_sprites.add(player) all_sprites.add(player.assistants) # Смещение асистентов к игроку for assistant in player.assistants: assistant.rect.center = player.rect.center # Изменение текущего сида и файла сохранения current_seed = '\n'.join([ ' '.join(level_seed), ' '.join(monsters_seed), ' '.join(boxes_seed), str(player), str(level_number) ]) save(current_seed) # Установка начальной позиции приуела player.scope.init_scope_position( (screen_width * 0.5, screen_height * 0.5)) # Иконки для отображения иконок (контейнеров) с заклинаниями внизу экрана spells_containers = ( SpellContainer("fire_spell.png", FireSpell, player), SpellContainer("ice_spell.png", IceSpell, player), SpellContainer("poison_spell.png", PoisonSpell, player), SpellContainer("void_spell.png", VoidSpell, player), SpellContainer("light_spell.png", FlashSpell, player), SpellContainer("teleport_spell.png", TeleportSpell, player), ) # Включение музыки после обновления параметров pygame.mixer.music.play(-1) continue # Применение смещения камеры относительно игрока camera.update(player) for sprite in all_sprites: camera.apply(sprite) # Отрисовка спрайтов в определённом порядке, # чтобы они не перекрывали друг друга tiles_group.draw(screen) # тайлы пола torches_group.draw(screen) # факеда # Сундуки for chest in Chest.chest_group: chest.draw_back_image(screen) # предметы на земле (мясо и деньги) GroundItem.sprites_group.draw(screen) collidable_tiles_group.draw( screen) # физические объекты не являющиеся стенами doors_group.draw(screen) # двери enemies_group.draw(screen) # враги player.assistants.draw(screen) # асистенты # Шкалы здоровья у асистентов for assistant in player.assistants: assistant.draw_health_bar(screen) player.draw(screen) # игрок Entity.spells_group.draw(screen) # заклинания player.draw_health_bar(screen) # шкала здоровья у игрока # Шкала здоровья у врагов for enemy in enemies_group: enemy.draw_health_bar(screen) Entity.damages_group.draw(screen) # текст с уроном chest_title.draw(screen) # сообщение по мере приближении к сундуку # сообщение по мере приближении к лестнице вниз downstairs_title.draw(screen) # Значения для определения того, какие иконки текст, # нужно отображать на иконках с заклинаниями (нужно, чтобы игроку было # проще привыкнуть к управлению) is_joystick = player.joystick is not None if is_joystick: spell_args = ("o", "x", "triangle", "square", "L1", "L2") else: spell_args = ("1", "2", "3", "4", "5", "Space") # Контейнеры с заклинаниями for i in range(len(spells_containers) - 1, -1, -1): pos = (screen_width * (0.375 + 0.05 * i), screen_height * 0.9) spells_containers[i].draw(screen, pos, is_joystick, spell_args[i]) # Панель с игроком в левом верхнем углу player_icon.draw(screen, (indent, indent)) # Иконоки у асистентов for number_of_assistant, assistant in enumerate(player.assistants): if not assistant.icon: assistant.icon = PlayerIcon(assistant) assistant.icon.draw( screen, (indent + 20, assistants_height + number_of_assistant * 80), 0.5) # фпс fps_text = fps_font.render(str(round(clock.get_fps())), True, (100, 255, 100)) screen.blit(fps_text, (2, 2)) # Иконка и количество врагов на уровне monster_number_text = level_and_enemies_font.render( str(len(enemies_group)), True, (255, 255, 255)) screen.blit(monster_number_icon, (screen_width - 70, 80)) screen.blit(monster_number_text, (screen_width - 120, 80)) # Иконка и номер уровня level_number_text = level_and_enemies_font.render( str(level_number), True, (255, 255, 255)) screen.blit(level_number_icon, (screen_width - 70, 10)) screen.blit(level_number_text, (screen_width - 120, 10)) # Прицел игрока player.scope.draw(screen) clock.tick(FPS) pygame.display.flip() # Запись сохранения после закрытия игры save(current_seed) return 0
else: poison.remove(p) for f in food: for enemy in enemies: if (is_colliding(enemy, f)): enemy.increase_size(f.get_size()) f.deactivate() if (is_colliding(player, f)): player.increase_size(f.get_size()) f.deactivate() for p in poison: for enemy in enemies: if (is_colliding(enemy, p)): enemy.decrease_size(p.get_size()) p.deactivate() if (is_colliding(player, p)): player.decrease_size(p.get_size()) p.deactivate() for enemy in enemies: enemy.update(player, enemy.get_distance_from_food(food)) enemy.draw(screen) player.update() player.draw(screen) pygame.display.flip()