+ EndLevel screen

This commit is contained in:
Dmitry Belyaev 2024-03-30 20:10:57 +03:00
parent 5a4bc5f225
commit 6efab241a5

View File

@ -4,8 +4,15 @@
Задача:
Попробуйте сделать управление объектом, который есть не просто прямоугольник, а, например, рисунок.
Решение: призрак в лабиринте, управление стрелками и WASD, выход Esc или Q.
Картинки берутся из папки assets, если их нет то автоматически скачиваются из репозитория.
Если скачать не получилось то будут нарисованы заглушки.
Зависимости: pygame pillow
TODO: отбработка выхода из лабиринта
"""
import os
@ -248,22 +255,18 @@ class GameObject(ABC):
return Coords(*self.rect.topleft)
def set_coords(self, coords: Coords):
new_rect = self.rect.copy()
new_rect.topleft = coords
if self.parent:
if self.parent.surface:
if not (
coords.x >= 0
and coords.x + self.rect.width <= self.parent.surface.get_width()
and coords.y >= 0
and coords.y + self.rect.height < self.parent.surface.get_height()
):
if self.parent.rect:
if not self.parent.rect.contains(new_rect):
return
self.rect.topleft = coords
self.rect = new_rect
@abstractmethod
def draw(self):
pass
@abstractmethod
def handle_event(self, event: pygame.event.Event):
pass
@ -281,6 +284,7 @@ class Hero(GameObject):
self._surface = pygame.image.load(self.assets["ghost.png"])
self.rect = self.surface.get_rect()
self.rect.topleft = coords
self.active = True
def draw(self):
self.parent.surface.blit(self.surface, self.rect)
@ -317,17 +321,31 @@ class Hero(GameObject):
super().set_coords(coords)
def handle_event(self, event: pygame.event.Event):
delta = 30
if not self.active:
return
up, down = Coords(0, -1), Coords(0, 1)
left, right = Coords(-1, 0), Coords(1, 0)
da, db = 30, 5
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
case pygame.K_UP:
self.coords += up * da
case pygame.K_DOWN:
self.coords += down * da
case pygame.K_LEFT:
self.coords += left * da
case pygame.K_RIGHT:
self.coords += right * da
case pygame.K_w:
self.coords += up * db
case pygame.K_s:
self.coords += down * db
case pygame.K_a:
self.coords += left * db
case pygame.K_d:
self.coords += right * db
class WallBlock(GameObject):
@ -347,9 +365,6 @@ class WallBlock(GameObject):
def draw(self):
self.parent.surface.blit(self.surface, self.rect)
def handle_event(self, event: pygame.event.Event):
...
class Walls(GameObject):
"""объект стен"""
@ -380,9 +395,42 @@ class Walls(GameObject):
return True
return False
class EndLevel(GameObject):
def __init__(self, scene: GameObject):
super().__init__(Coords.zero(), scene, scene.assets)
self.image = pygame.image.load(scene.assets["win.png"])
self.active = False
# надпись завершения игры
font = pygame.font.SysFont("Arial", 70)
text = "Конец игры!"
self._surface = font.render(text, 1, "#1b10a8c4")
self.rect = self._surface.get_rect()
self.rect.center = self.parent.rect.center
# совет по кнопкам
hint = "Для новой игры нажмите N, для выхода Q"
font_hint = pygame.font.SysFont("Arial", 27)
self.hint = font_hint.render(hint, 1, "#24053da4")
self.hint_rect = self.hint.get_rect()
self.hint_rect.center = self.parent.rect.center
self.hint_rect = self.hint_rect.move(Coords(0, 300))
def draw(self):
if not self.active:
return
self.parent.surface.blit(self.image, self.rect)
self.parent.surface.blit(self.surface, self.rect)
self.parent.surface.blit(self.hint, self.hint_rect)
def handle_event(self, event: pygame.event.Event):
for block in self.blocks:
block.handle_event(event)
if not self.active:
return
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_n:
self.parent.want_new_level = True
self.parent.done = True
class Scene(GameObject):
@ -411,25 +459,45 @@ class Scene(GameObject):
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.walls = Walls(self, self.maze, box_sz)
print(self.get_exit_rect())
print(self.rect)
self.end = EndLevel(self)
self.end.active = False
self.want_new_level = False
self.exit_rect = self.get_exit_rect()
# для тестирования экрана конца уровня
# self.hero.coords = Coords(*self.exit_rect.topleft) + Coords(
# -self.box_sz.x // 2, 5
# )
def get_exit_rect(self) -> pygame.Rect:
# находим клетку в которой будет выход с карты
maze_sz = get_maze_sz(self.maze)
coords = (maze_sz - Coords(1, 2)) * self.box_sz
rect = pygame.Rect(coords, coords)
rect.width, rect.height = self.box_sz
# уменьшаем размер клетки и перемещаем её вправо
rect.width = self.box_sz.x // 4
rect = rect.move(Coords(self.box_sz.x // 2, 0))
return rect
def check_level_completed(self):
self.level_completed = self.exit_rect.colliderect(self.hero.rect)
if self.level_completed:
self.end.active = True
self.hero.active = False
def draw(self):
if self.done:
return
self.surface.blit(self.background, self.coords)
pygame.draw.rect(self._surface, pygame.Color("#42c53d25"), self.get_exit_rect())
self.hero.draw()
self.walls.draw()
if self.level_completed:
self.end.draw()
else:
# pygame.draw.rect(self._surface, pygame.Color("#42c53d25"), self.get_exit_rect())
self.hero.draw()
self.walls.draw()
def handle_event(self, event: pygame.event.Event):
if self.done:
@ -442,6 +510,8 @@ class Scene(GameObject):
self.done = True
if not self.done:
self.hero.handle_event(event)
self.check_level_completed()
self.end.handle_event(event)
def event_loop(self):
while not self.done:
@ -457,8 +527,11 @@ def game(assets):
maze_sz = Coords(6, 6)
pygame.display.set_caption("Движение рисунка на Pygame")
scene = Scene(assets, screen_sz, maze_sz)
scene.event_loop()
want_new_level = True
while want_new_level:
scene = Scene(assets, screen_sz, maze_sz)
scene.event_loop()
want_new_level = scene.want_new_level
pygame.quit()
@ -468,6 +541,7 @@ def main():
"bg1k.png",
"ghost.png",
"brick.png",
"win.png",
]
with get_assets(assets) as assets:
game(assets)