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