py_stepik/mod_pygame/moveimg.py
2024-03-29 16:54:28 +03:00

193 lines
6.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
3.5 Вставка рисунков. Управление рисунков
https://stepik.org/lesson/937437/step/2?unit=943412
Задача:
Попробуйте сделать управление объектом, который есть не просто прямоугольник, а, например, рисунок.
Зависимости: pygame pillow
"""
import pygame
import os
import shutil
import tempfile
import urllib.request
from contextlib import contextmanager
from typing import NamedTuple
import PIL
from PIL import Image, ImageDraw
def download_asset(asset, path):
"""
Загрузка картинок из репозитория
"""
prefix = "https://gitea.b4tman.ru/temp/py_stepik/raw/branch/master/assets/"
print("Качаю картинку", asset, end=" ... ", flush=True)
try:
urllib.request.urlretrieve(prefix + asset, path)
except Exception:
print("не смог :(")
return False
print("скачал!")
return True
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)
@contextmanager
def get_assets(names):
"""Получение соответствия с расположением файлов картинок
Размер картинок нужно менять поэтому они всегда сохраняются во временные файлы.
"""
assets_dir = "assets"
files = {}
# поиск файлов (загрузка если их нет) и создание временных
for asset in names:
_, ext = os.path.splitext(asset)
temppath = tempfile.mktemp(suffix=ext)
filepath = os.path.join(assets_dir, asset)
if os.path.isfile(filepath):
shutil.copyfile(filepath, temppath)
else:
if not download_asset(asset, temppath):
make_stub_image(temppath, asset)
files[asset] = temppath
# передача управления
yield files
# очистка
for _, filename in files.items():
try:
os.remove(filename)
except FileNotFoundError:
pass
class Coords(NamedTuple):
"""
Вспомогательный класс для упрощения работы с координатами
"""
x: int | float
y: int | float
def __add__(self, other):
if isinstance(other, self.__class__):
return self.__class__(self.x + other.x, self.y + other.y)
if isinstance(other, (int, float)):
return self.__class__(self.x + other, self.y + other)
return NotImplemented
def __sub__(self, other):
if isinstance(other, self.__class__):
return self.__class__(self.x - other.x, self.y - other.y)
if isinstance(other, (int, float)):
return self.__class__(self.x - other, self.y - other)
return NotImplemented
def __floordiv__(self, other):
if isinstance(other, self.__class__):
return self.__class__(self.x // other.x, self.y // other.y)
if isinstance(other, (int, float)):
return self.__class__(self.x // other, self.y // other)
return NotImplemented
def __mul__(self, other):
if isinstance(other, self.__class__):
return self.__class__(self.x * other.x, self.y * other.y)
if isinstance(other, (int, float)):
return self.__class__(self.x * other, self.y * other)
return NotImplemented
def transform(self, ref: "Coords"):
return self * ref
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 копейка и т.д.
"""
a = amount % 100
i = 2
if 10 < a < 20:
pass
elif a % 10 == 1:
i = 0
elif 1 < a % 10 < 5:
i = 1
return f"{amount} {declensions[i]}"
def draw_background_image(screen, filename):
background = pygame.image.load(filename)
screen.blit(background, (0, 0))
def game(assets):
pygame.init()
width, height = screen_sz = Coords(1000, 1000)
screen = pygame.display.set_mode(screen_sz)
pygame.display.set_caption("Движение рисунка на Pygame")
ghost_sz = screen_sz // 10
resize_img(assets, "bg1k.png", screen_sz)
speed = [2, 2]
resize_img(assets, "ghost.png", ghost_sz)
ghost = pygame.image.load(assets["ghost.png"])
ghostrect = ghost.get_rect()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
ghostrect = ghostrect.move(speed)
if ghostrect.left < 0 or ghostrect.right > width:
speed[0] = -speed[0]
if ghostrect.top < 0 or ghostrect.bottom > height:
speed[1] = -speed[1]
draw_background_image(screen, assets["bg1k.png"])
screen.blit(ghost, ghostrect)
pygame.display.flip()
pygame.quit()
def main():
assets = [
"bg1k.png",
"ghost.png",
]
with get_assets(assets) as assets:
game(assets)
main()