diff --git a/mod_pygame/moveimg.py b/mod_pygame/moveimg.py index be8cb52..99a1eb4 100644 --- a/mod_pygame/moveimg.py +++ b/mod_pygame/moveimg.py @@ -4,8 +4,15 @@ Задача: Попробуйте сделать управление объектом, который есть не просто прямоугольник, а, например, рисунок. + + Решение: призрак в лабиринте, управление стрелками и WASD, выход Esc или Q. + + Картинки берутся из папки assets, если их нет то автоматически скачиваются из репозитория. + Если скачать не получилось то будут нарисованы заглушки. Зависимости: pygame pillow + + TODO: отбработка выхода из лабиринта """ import os @@ -248,22 +255,18 @@ class GameObject(ABC): return Coords(*self.rect.topleft) def set_coords(self, coords: Coords): + new_rect = self.rect.copy() + new_rect.topleft = coords if self.parent: - if self.parent.surface: - if not ( - coords.x >= 0 - and coords.x + self.rect.width <= self.parent.surface.get_width() - and coords.y >= 0 - and coords.y + self.rect.height < self.parent.surface.get_height() - ): + if self.parent.rect: + if not self.parent.rect.contains(new_rect): return - self.rect.topleft = coords + self.rect = new_rect @abstractmethod def draw(self): pass - @abstractmethod def handle_event(self, event: pygame.event.Event): pass @@ -281,6 +284,7 @@ class Hero(GameObject): self._surface = pygame.image.load(self.assets["ghost.png"]) self.rect = self.surface.get_rect() self.rect.topleft = coords + self.active = True def draw(self): self.parent.surface.blit(self.surface, self.rect) @@ -317,17 +321,31 @@ class Hero(GameObject): super().set_coords(coords) def handle_event(self, event: pygame.event.Event): - delta = 30 + if not self.active: + return + + up, down = Coords(0, -1), Coords(0, 1) + left, right = Coords(-1, 0), Coords(1, 0) + + da, db = 30, 5 if event.type == pygame.KEYDOWN: match event.key: - case pygame.K_UP | pygame.K_w: - self.coords += Coords(0, -1) * delta - case pygame.K_DOWN | pygame.K_s: - self.coords += Coords(0, 1) * delta - case pygame.K_LEFT | pygame.K_a: - self.coords += Coords(-1, 0) * delta - case pygame.K_RIGHT | pygame.K_d: - self.coords += Coords(1, 0) * delta + case pygame.K_UP: + self.coords += up * da + case pygame.K_DOWN: + self.coords += down * da + case pygame.K_LEFT: + self.coords += left * da + case pygame.K_RIGHT: + self.coords += right * da + case pygame.K_w: + self.coords += up * db + case pygame.K_s: + self.coords += down * db + case pygame.K_a: + self.coords += left * db + case pygame.K_d: + self.coords += right * db class WallBlock(GameObject): @@ -347,9 +365,6 @@ class WallBlock(GameObject): def draw(self): self.parent.surface.blit(self.surface, self.rect) - def handle_event(self, event: pygame.event.Event): - ... - class Walls(GameObject): """объект стен""" @@ -380,9 +395,42 @@ class Walls(GameObject): return True return False + +class EndLevel(GameObject): + def __init__(self, scene: GameObject): + super().__init__(Coords.zero(), scene, scene.assets) + self.image = pygame.image.load(scene.assets["win.png"]) + self.active = False + + # надпись завершения игры + font = pygame.font.SysFont("Arial", 70) + text = "Конец игры!" + self._surface = font.render(text, 1, "#1b10a8c4") + self.rect = self._surface.get_rect() + self.rect.center = self.parent.rect.center + + # совет по кнопкам + hint = "Для новой игры нажмите N, для выхода Q" + font_hint = pygame.font.SysFont("Arial", 27) + self.hint = font_hint.render(hint, 1, "#24053da4") + self.hint_rect = self.hint.get_rect() + self.hint_rect.center = self.parent.rect.center + self.hint_rect = self.hint_rect.move(Coords(0, 300)) + + def draw(self): + if not self.active: + return + self.parent.surface.blit(self.image, self.rect) + self.parent.surface.blit(self.surface, self.rect) + self.parent.surface.blit(self.hint, self.hint_rect) + def handle_event(self, event: pygame.event.Event): - for block in self.blocks: - block.handle_event(event) + if not self.active: + return + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_n: + self.parent.want_new_level = True + self.parent.done = True class Scene(GameObject): @@ -411,25 +459,45 @@ class Scene(GameObject): resize_img(assets, "bg1k.png", screen_sz) self.background = pygame.image.load(self.assets["bg1k.png"]) self.done = False + self.level_completed = False self.maze = maze_gen(6, 6) self.walls = Walls(self, self.maze, box_sz) - print(self.get_exit_rect()) - print(self.rect) + self.end = EndLevel(self) + self.end.active = False + self.want_new_level = False + self.exit_rect = self.get_exit_rect() + # для тестирования экрана конца уровня + # self.hero.coords = Coords(*self.exit_rect.topleft) + Coords( + # -self.box_sz.x // 2, 5 + # ) def get_exit_rect(self) -> pygame.Rect: + # находим клетку в которой будет выход с карты maze_sz = get_maze_sz(self.maze) coords = (maze_sz - Coords(1, 2)) * self.box_sz rect = pygame.Rect(coords, coords) rect.width, rect.height = self.box_sz + # уменьшаем размер клетки и перемещаем её вправо + rect.width = self.box_sz.x // 4 + rect = rect.move(Coords(self.box_sz.x // 2, 0)) return rect + def check_level_completed(self): + self.level_completed = self.exit_rect.colliderect(self.hero.rect) + if self.level_completed: + self.end.active = True + self.hero.active = False + def draw(self): if self.done: return self.surface.blit(self.background, self.coords) - pygame.draw.rect(self._surface, pygame.Color("#42c53d25"), self.get_exit_rect()) - self.hero.draw() - self.walls.draw() + if self.level_completed: + self.end.draw() + else: + # pygame.draw.rect(self._surface, pygame.Color("#42c53d25"), self.get_exit_rect()) + self.hero.draw() + self.walls.draw() def handle_event(self, event: pygame.event.Event): if self.done: @@ -442,6 +510,8 @@ class Scene(GameObject): self.done = True if not self.done: self.hero.handle_event(event) + self.check_level_completed() + self.end.handle_event(event) def event_loop(self): while not self.done: @@ -457,8 +527,11 @@ def game(assets): maze_sz = Coords(6, 6) pygame.display.set_caption("Движение рисунка на Pygame") - scene = Scene(assets, screen_sz, maze_sz) - scene.event_loop() + want_new_level = True + while want_new_level: + scene = Scene(assets, screen_sz, maze_sz) + scene.event_loop() + want_new_level = scene.want_new_level pygame.quit() @@ -468,6 +541,7 @@ def main(): "bg1k.png", "ghost.png", "brick.png", + "win.png", ] with get_assets(assets) as assets: game(assets)