From 512bd42572eafe36c764863e57cc49c585fdb5d2 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sat, 30 Mar 2024 23:28:23 +0300 Subject: [PATCH] moveimg: add game title and remove pillow dependency --- mod_pygame/moveimg.py | 102 +++++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 47 deletions(-) diff --git a/mod_pygame/moveimg.py b/mod_pygame/moveimg.py index 9ec663a..ff58856 100644 --- a/mod_pygame/moveimg.py +++ b/mod_pygame/moveimg.py @@ -10,7 +10,7 @@ Картинки берутся из папки assets, если их нет то автоматически скачиваются из репозитория. Если скачать не получилось то будут нарисованы заглушки. - Зависимости: pygame pillow + Зависимости: pygame """ import os @@ -22,9 +22,7 @@ from contextlib import contextmanager from random import choice, randrange, sample from typing import NamedTuple, Optional -import PIL import pygame -from PIL import ImageDraw def download_asset(asset, path): @@ -45,13 +43,20 @@ def download_asset(asset, path): def make_stub_image(path, name): """Создание пустой картинки, на случай если скачать не получилось""" - img = PIL.Image.new("RGBA", (200, 200)) - draw = ImageDraw.Draw(img) - draw.rectangle([(50, 50), (150, 150)], outline="black", width=2) - draw.line((50, 50, 150, 150), fill="red", width=2) - draw.line((50, 150, 150, 50), fill="red", width=2) - draw.text((50, 170), name, fill="blue") - img.save(path) + img = pygame.surface.Surface((200, 200), flags=pygame.SRCALPHA) + img.fill((255, 255, 255, 0)) + pygame.draw.line(img, "#ff000065", (5, 5), (195, 195), 2) + pygame.draw.line(img, "#ff000065", (195, 5), (5, 195), 2) + + rect = pygame.Rect(5, 5, 190, 190) + pygame.draw.rect(img, "black", rect, 3) + + font = pygame.font.SysFont("Arial", 44) + text1 = font.render(name, True, "blue") + text1_rect = text1.get_rect() + text1_rect.center = img.get_rect().center + img.blit(text1, text1_rect) + pygame.image.save(img, path) @contextmanager @@ -129,16 +134,6 @@ class Coords(NamedTuple): return cls(0, 0) -def resize_img(assets: dict, name: str, sz: Coords): - """ - Изменение размера картинки и сохранение в файл - """ - img = PIL.Image.open(assets[name]) - if img.size != sz: - img = img.resize(sz) - img.save(assets[name]) - - def choose_plural(amount, declensions): """Возвращает количество объектов в виде строки например 5 копеек, 1 копейка и т.д. @@ -281,6 +276,8 @@ class Hero(GameObject): super().__init__(coords, parent, assets) self._surface = pygame.image.load(self.assets["ghost.png"]) self.rect = self.surface.get_rect() + sf = Coords(0.8, 0.8) + self._surface, self.rect = self.scene.scale_box(self.surface, self.rect, sf) self.rect.topleft = coords self.active = True self.looking_right = False @@ -324,7 +321,7 @@ class Hero(GameObject): def flip(self): self.looking_right = not self.looking_right self._surface = pygame.transform.flip(self.surface, True, False) - + def move(self, direction: Coords, step: int = 1): if direction.x != 0: going_right = direction.x > 0 @@ -335,15 +332,15 @@ class Hero(GameObject): def move_left(self, step: int = 1): self.move(Coords(-1, 0), step) - + def move_right(self, step: int = 1): self.move(Coords(1, 0), step) def move_up(self, step: int = 1): self.move(Coords(0, -1), step) - + def move_down(self, step: int = 1): - self.move(Coords(0, 1), step) + self.move(Coords(0, 1), step) def handle_event(self, event: pygame.event.Event): if not self.active: @@ -383,6 +380,9 @@ class WallBlock(GameObject): self._surface = pygame.image.load(self.assets["brick.png"]) self.rect = self.surface.get_rect() self.rect.topleft = coords + # уменьшаем размер монетки + sf = Coords(1, 1) + self._surface, self.rect = self.scene.scale_box(self.surface, self.rect, sf) def draw(self): self.parent.surface.blit(self.surface, self.rect) @@ -417,6 +417,7 @@ class Walls(GameObject): return True return False + class Coin(GameObject): """объект монетки""" @@ -431,13 +432,13 @@ class Coin(GameObject): self.rect = self.surface.get_rect() self.rect.topleft = coords # уменьшаем размер монетки - new_rect = self.rect.scale_by(0.7, 0.7) - self._surface = pygame.transform.scale(self._surface, new_rect.size) - self.rect = new_rect + sf = Coords(0.7, 0.7) + self._surface, self.rect = self.scene.scale_box(self.surface, self.rect, sf) def draw(self): self.parent.surface.blit(self.surface, self.rect) + class Coins(GameObject): """объект коллекции монеток""" @@ -452,7 +453,7 @@ class Coins(GameObject): super().__init__(Coords.zero(), parent, assets) self.box_sz = box_sz self._capacity = count - + free_points = [] excluded = Coords(0, 1), get_maze_sz(maze) - Coords(1, 2) for i, row in enumerate(maze): @@ -461,11 +462,10 @@ class Coins(GameObject): if item < 1 and p not in excluded: free_points.append(p) continue - + coin_points = sample(free_points, min(count, len(free_points))) self.coins = [ - Coin(point.transform(box_sz), self, self.assets) - for point in coin_points + Coin(point.transform(box_sz), self, self.assets) for point in coin_points ] self.collected_coins = [] @@ -475,11 +475,11 @@ class Coins(GameObject): self.done_txt = font.render(text, 1, "#050366e3") self.done_txt_rect = self.done_txt.get_rect() self.done_txt_rect.topleft = Coords(10, 10) - + @property def capacity(self): return self._capacity - + @property def coins_left(self): return len(self.coins) @@ -487,7 +487,7 @@ class Coins(GameObject): @property def coins_collected(self): return self.capacity - self.coins_left - + @property def all_collected(self): return self.coins_left == 0 @@ -514,6 +514,7 @@ class Coins(GameObject): self.coins.remove(coin) self.add_to_collected(coin) + class EndLevel(GameObject): def __init__(self, scene: GameObject): super().__init__(Coords.zero(), scene, scene.assets) @@ -566,30 +567,28 @@ class Scene(GameObject): # кнопки для выхода из игры exit_keys = (pygame.K_ESCAPE, pygame.K_q) - def __init__(self, assets: dict, screen_sz: Coords, maze_sz: Coords, coins_count: int): + def __init__( + self, assets: dict, screen_sz: Coords, maze_sz: Coords, coins_count: int + ): super().__init__(Coords.zero(), None, assets) self.maze = maze_gen(*maze_sz) maze_sz = get_maze_sz(self.maze) box_sz = screen_sz // get_maze_sz(self.maze) self.box_sz = box_sz - resize_img(self.assets, "brick.png", box_sz) - resize_img(self.assets, "coin.png", box_sz) + self._surface = pygame.display.set_mode(screen_sz) + self.surface.fill("white") + self.rect = self._surface.get_rect() + self.background = pygame.image.load(self.assets["bg1k.png"]) + self.background = pygame.transform.scale(self.background, self.rect.size) hero_sz = Coords(*map(int, box_sz * 0.8)) - resize_img(self.assets, "ghost.png", hero_sz) - hero_y_offset = (box_sz.y - hero_sz.y) // 2 + box_sz.y - - self._surface = pygame.display.set_mode(screen_sz) - self.rect = self._surface.get_rect() self.hero = Hero(Coords(0, hero_y_offset), self) - 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.maze = maze_gen(6, 6) self.walls = Walls(self, self.maze, box_sz) self.coins = Coins(self, self.maze, box_sz, coins_count) @@ -622,6 +621,7 @@ class Scene(GameObject): def draw(self): if self.done: return + self.surface.fill("white") self.surface.blit(self.background, self.coords) if self.level_completed: self.end.draw() @@ -630,6 +630,14 @@ class Scene(GameObject): self.walls.draw() self.coins.draw() + def scale_box( + self, surface: pygame.Surface, rect: pygame.Rect, scale_factor: Coords + ): + rect.size = self.box_sz + rect.scale_by_ip(*scale_factor) + surface = pygame.transform.scale(surface, rect.size) + return surface, rect + def handle_event(self, event: pygame.event.Event): if self.done: return @@ -653,11 +661,10 @@ class Scene(GameObject): def game(assets): - pygame.init() screen_sz = Coords(1000, 1000) maze_sz = Coords(6, 6) coins_count = 10 - pygame.display.set_caption("Движение рисунка на Pygame") + pygame.display.set_caption("Призрачный лабиринт: сокровища небесного замка") want_new_level = True while want_new_level: @@ -669,6 +676,7 @@ def game(assets): def main(): + pygame.init() assets = [ "bg1k.png", "ghost.png",