+ EndLevel screen
This commit is contained in:
parent
5a4bc5f225
commit
6efab241a5
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user