pygame moveimg objects

This commit is contained in:
Dmitry Belyaev 2024-03-29 22:29:54 +03:00
parent 0f7fbc2fca
commit efa19e3398

View File

@ -8,16 +8,17 @@
Зависимости: pygame pillow
"""
import pygame
import os
import shutil
import tempfile
import urllib.request
from abc import ABC, abstractmethod
from contextlib import contextmanager
from typing import NamedTuple
from typing import NamedTuple, Optional
import PIL
from PIL import Image, ImageDraw
import pygame
from PIL import ImageDraw
def download_asset(asset, path):
@ -117,6 +118,10 @@ class Coords(NamedTuple):
def transform(self, ref: "Coords"):
return self * ref
@classmethod
def zero(cls):
return cls(0, 0)
def resize_img(assets: dict, name: str, sz: Coords):
"""
@ -143,41 +148,138 @@ def choose_plural(amount, declensions):
return f"{amount} {declensions[i]}"
def draw_background_image(screen, filename):
background = pygame.image.load(filename)
screen.blit(background, (0, 0))
class GameObject(ABC):
"""обобщение игрового элемента"""
coords = property(
lambda self: self.get_coords(), lambda self, c: self.set_coords(c)
)
def __init__(
self,
coords: Coords,
parent: Optional["GameObject"] = None,
assets: dict | None = None,
):
self.parent = parent
self._coords = coords
self.assets = assets or (parent.assets if parent else None)
self._surface = None
@property
def surface(self) -> pygame.Surface | None:
return self._surface or (self.parent.surface if self.parent else None)
def get_coords(self) -> Coords:
return self._coords
def set_coords(self, coords: Coords):
if self.parent:
if self.parent.surface:
if not (
coords.x >= 0
and coords.x < self.parent.surface.get_width()
and coords.y >= 0
and coords.y < self.parent.surface.get_height()
):
return
self._coords = coords
@abstractmethod
def draw(self):
pass
@abstractmethod
def handle_event(self, event: pygame.event.Event):
pass
class Hero(GameObject):
"""объект главного героя"""
def __init__(
self,
coords: Coords,
parent: GameObject,
assets: dict | None = None,
):
super().__init__(coords, parent, assets)
screen_sz = Coords(*parent.surface.get_size())
ghost_sz = screen_sz // 10
resize_img(self.assets, "ghost.png", ghost_sz)
self._surface = pygame.image.load(self.assets["ghost.png"])
self.rect = self.surface.get_rect()
self.coords = coords
def set_coords(self, coords: Coords):
super().set_coords(coords)
self.rect.topleft = self.coords
def draw(self):
self.parent.surface.blit(self.surface, self.rect)
def handle_event(self, event: pygame.event.Event):
delta = 10
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
class Scene(GameObject):
"""основной игровой объект"""
# кнопки для выхода из игры
exit_keys = (pygame.K_ESCAPE, pygame.K_q)
def __init__(self, assets: dict, sz: Coords):
super().__init__(Coords.zero(), None, assets)
self._surface = pygame.display.set_mode(sz)
self.hero = Hero(Coords(100, 100), self)
resize_img(assets, "bg1k.png", sz)
self.background = pygame.image.load(self.assets["bg1k.png"])
self.done = False
def draw(self):
if self.done:
return
self.surface.blit(self.background, self.coords)
self.hero.draw()
def handle_event(self, event: pygame.event.Event):
if self.done:
return
if (
event.type == pygame.QUIT
or event.type == pygame.KEYDOWN
and event.key in self.exit_keys
):
self.done = True
if not self.done:
self.hero.handle_event(event)
def event_loop(self):
while not self.done:
event = pygame.event.wait()
self.handle_event(event)
self.draw()
pygame.display.flip()
def game(assets):
pygame.init()
width, height = screen_sz = Coords(1000, 1000)
screen = pygame.display.set_mode(screen_sz)
screen_sz = Coords(1000, 1000)
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()
scene = Scene(assets, screen_sz)
scene.event_loop()
pygame.quit()
@ -190,4 +292,5 @@ def main():
with get_assets(assets) as assets:
game(assets)
main()
main()