+ EndLevel screen
This commit is contained in:
parent
5a4bc5f225
commit
6efab241a5
@ -4,8 +4,15 @@
|
|||||||
|
|
||||||
Задача:
|
Задача:
|
||||||
Попробуйте сделать управление объектом, который есть не просто прямоугольник, а, например, рисунок.
|
Попробуйте сделать управление объектом, который есть не просто прямоугольник, а, например, рисунок.
|
||||||
|
|
||||||
|
Решение: призрак в лабиринте, управление стрелками и WASD, выход Esc или Q.
|
||||||
|
|
||||||
|
Картинки берутся из папки assets, если их нет то автоматически скачиваются из репозитория.
|
||||||
|
Если скачать не получилось то будут нарисованы заглушки.
|
||||||
|
|
||||||
Зависимости: pygame pillow
|
Зависимости: pygame pillow
|
||||||
|
|
||||||
|
TODO: отбработка выхода из лабиринта
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@ -248,22 +255,18 @@ class GameObject(ABC):
|
|||||||
return Coords(*self.rect.topleft)
|
return Coords(*self.rect.topleft)
|
||||||
|
|
||||||
def set_coords(self, coords: Coords):
|
def set_coords(self, coords: Coords):
|
||||||
|
new_rect = self.rect.copy()
|
||||||
|
new_rect.topleft = coords
|
||||||
if self.parent:
|
if self.parent:
|
||||||
if self.parent.surface:
|
if self.parent.rect:
|
||||||
if not (
|
if not self.parent.rect.contains(new_rect):
|
||||||
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()
|
|
||||||
):
|
|
||||||
return
|
return
|
||||||
self.rect.topleft = coords
|
self.rect = new_rect
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def draw(self):
|
def draw(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def handle_event(self, event: pygame.event.Event):
|
def handle_event(self, event: pygame.event.Event):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -281,6 +284,7 @@ class Hero(GameObject):
|
|||||||
self._surface = pygame.image.load(self.assets["ghost.png"])
|
self._surface = pygame.image.load(self.assets["ghost.png"])
|
||||||
self.rect = self.surface.get_rect()
|
self.rect = self.surface.get_rect()
|
||||||
self.rect.topleft = coords
|
self.rect.topleft = coords
|
||||||
|
self.active = True
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
self.parent.surface.blit(self.surface, self.rect)
|
self.parent.surface.blit(self.surface, self.rect)
|
||||||
@ -317,17 +321,31 @@ class Hero(GameObject):
|
|||||||
super().set_coords(coords)
|
super().set_coords(coords)
|
||||||
|
|
||||||
def handle_event(self, event: pygame.event.Event):
|
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:
|
if event.type == pygame.KEYDOWN:
|
||||||
match event.key:
|
match event.key:
|
||||||
case pygame.K_UP | pygame.K_w:
|
case pygame.K_UP:
|
||||||
self.coords += Coords(0, -1) * delta
|
self.coords += up * da
|
||||||
case pygame.K_DOWN | pygame.K_s:
|
case pygame.K_DOWN:
|
||||||
self.coords += Coords(0, 1) * delta
|
self.coords += down * da
|
||||||
case pygame.K_LEFT | pygame.K_a:
|
case pygame.K_LEFT:
|
||||||
self.coords += Coords(-1, 0) * delta
|
self.coords += left * da
|
||||||
case pygame.K_RIGHT | pygame.K_d:
|
case pygame.K_RIGHT:
|
||||||
self.coords += Coords(1, 0) * delta
|
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):
|
class WallBlock(GameObject):
|
||||||
@ -347,9 +365,6 @@ class WallBlock(GameObject):
|
|||||||
def draw(self):
|
def draw(self):
|
||||||
self.parent.surface.blit(self.surface, self.rect)
|
self.parent.surface.blit(self.surface, self.rect)
|
||||||
|
|
||||||
def handle_event(self, event: pygame.event.Event):
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
class Walls(GameObject):
|
class Walls(GameObject):
|
||||||
"""объект стен"""
|
"""объект стен"""
|
||||||
@ -380,9 +395,42 @@ class Walls(GameObject):
|
|||||||
return True
|
return True
|
||||||
return False
|
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):
|
def handle_event(self, event: pygame.event.Event):
|
||||||
for block in self.blocks:
|
if not self.active:
|
||||||
block.handle_event(event)
|
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):
|
class Scene(GameObject):
|
||||||
@ -411,25 +459,45 @@ class Scene(GameObject):
|
|||||||
resize_img(assets, "bg1k.png", screen_sz)
|
resize_img(assets, "bg1k.png", screen_sz)
|
||||||
self.background = pygame.image.load(self.assets["bg1k.png"])
|
self.background = pygame.image.load(self.assets["bg1k.png"])
|
||||||
self.done = False
|
self.done = False
|
||||||
|
self.level_completed = False
|
||||||
self.maze = maze_gen(6, 6)
|
self.maze = maze_gen(6, 6)
|
||||||
self.walls = Walls(self, self.maze, box_sz)
|
self.walls = Walls(self, self.maze, box_sz)
|
||||||
print(self.get_exit_rect())
|
self.end = EndLevel(self)
|
||||||
print(self.rect)
|
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:
|
def get_exit_rect(self) -> pygame.Rect:
|
||||||
|
# находим клетку в которой будет выход с карты
|
||||||
maze_sz = get_maze_sz(self.maze)
|
maze_sz = get_maze_sz(self.maze)
|
||||||
coords = (maze_sz - Coords(1, 2)) * self.box_sz
|
coords = (maze_sz - Coords(1, 2)) * self.box_sz
|
||||||
rect = pygame.Rect(coords, coords)
|
rect = pygame.Rect(coords, coords)
|
||||||
rect.width, rect.height = self.box_sz
|
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
|
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):
|
def draw(self):
|
||||||
if self.done:
|
if self.done:
|
||||||
return
|
return
|
||||||
self.surface.blit(self.background, self.coords)
|
self.surface.blit(self.background, self.coords)
|
||||||
pygame.draw.rect(self._surface, pygame.Color("#42c53d25"), self.get_exit_rect())
|
if self.level_completed:
|
||||||
self.hero.draw()
|
self.end.draw()
|
||||||
self.walls.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):
|
def handle_event(self, event: pygame.event.Event):
|
||||||
if self.done:
|
if self.done:
|
||||||
@ -442,6 +510,8 @@ class Scene(GameObject):
|
|||||||
self.done = True
|
self.done = True
|
||||||
if not self.done:
|
if not self.done:
|
||||||
self.hero.handle_event(event)
|
self.hero.handle_event(event)
|
||||||
|
self.check_level_completed()
|
||||||
|
self.end.handle_event(event)
|
||||||
|
|
||||||
def event_loop(self):
|
def event_loop(self):
|
||||||
while not self.done:
|
while not self.done:
|
||||||
@ -457,8 +527,11 @@ def game(assets):
|
|||||||
maze_sz = Coords(6, 6)
|
maze_sz = Coords(6, 6)
|
||||||
pygame.display.set_caption("Движение рисунка на Pygame")
|
pygame.display.set_caption("Движение рисунка на Pygame")
|
||||||
|
|
||||||
scene = Scene(assets, screen_sz, maze_sz)
|
want_new_level = True
|
||||||
scene.event_loop()
|
while want_new_level:
|
||||||
|
scene = Scene(assets, screen_sz, maze_sz)
|
||||||
|
scene.event_loop()
|
||||||
|
want_new_level = scene.want_new_level
|
||||||
|
|
||||||
pygame.quit()
|
pygame.quit()
|
||||||
|
|
||||||
@ -468,6 +541,7 @@ def main():
|
|||||||
"bg1k.png",
|
"bg1k.png",
|
||||||
"ghost.png",
|
"ghost.png",
|
||||||
"brick.png",
|
"brick.png",
|
||||||
|
"win.png",
|
||||||
]
|
]
|
||||||
with get_assets(assets) as assets:
|
with get_assets(assets) as assets:
|
||||||
game(assets)
|
game(assets)
|
||||||
|
Loading…
Reference in New Issue
Block a user