pygame: add moveimg
This commit is contained in:
parent
5bb3bb6213
commit
1eb9fa48fe
193
mod_pygame/moveimg.py
Normal file
193
mod_pygame/moveimg.py
Normal file
@ -0,0 +1,193 @@
|
||||
"""
|
||||
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()
|
Loading…
Reference in New Issue
Block a user