py_stepik/pygame-wasm/phantomcastle/game/scene.py

144 lines
4.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import asyncio
import pygame
from maze import maze_gen, get_maze_sz
from coords import Coords
from common import DrawableGameObject, EventHandler, IS_WASM
from game.hero import Hero
from game.wall import Walls
from game.coins import Coins
from game.endlevelmenu import EndLevelMenu
from sound import BackgroundSound
class Scene(DrawableGameObject, EventHandler):
"""основной игровой объект"""
# кнопки для выхода из игры
exit_keys = (pygame.K_ESCAPE, pygame.K_q)
def __init__(
self,
assets: dict,
screen_sz: Coords,
maze_sz: Coords,
coins_count: int,
fps: int,
):
super().__init__(Coords.zero(), None, assets)
self.maze = maze_gen(*maze_sz)
maze_sz = get_maze_sz(self.maze)
box_sz = screen_sz // get_maze_sz(self.maze)
self.box_sz = box_sz
self._surface = pygame.display.set_mode(screen_sz)
self.surface.fill("white")
self.rect = self.surface.get_rect()
self.background = pygame.image.load(self.assets["bg1k.png"])
self.background = pygame.transform.scale(self.background, self.rect.size)
double_bg = pygame.Surface((screen_sz.x * 2, screen_sz.y))
double_bg.blit(self.background, (0, 0))
double_bg.blit(self.background, (screen_sz.x, 0))
self.background = double_bg
self.bg_shift = 0
self.total_levels, self.total_coins = 0, 0
hero_sz = Coords(*map(int, box_sz * 0.8))
hero_y_offset = (box_sz.y - hero_sz.y) // 2 + box_sz.y
self.hero = Hero(Coords(0, hero_y_offset), self)
self.done = False
self.level_completed = False
self.maze = maze_gen(6, 6)
self.walls = Walls(self, self.maze, box_sz)
self.coins = Coins(self, self.maze, box_sz, coins_count)
self.end = EndLevelMenu(self)
self.end.active = False
self.want_new_level = False
self.exit_rect = self.get_exit_rect()
self.fps = fps
self.sound = BackgroundSound(self.assets["bg.ogg"])
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 = 1, self.box_sz.y
return rect.move((self.box_sz.x, 0))
def check_level_completed(self):
level_completed = self.exit_rect.colliderect(self.hero.rect)
if level_completed and not self.level_completed:
self.total_coins += self.coins.coins_collected
self.total_levels += 1
self.end.active = True
self.hero.active = False
self.level_completed = True
def draw(self):
if self.done:
return
self.surface.fill("white")
self.surface.blit(self.background, (-self.bg_shift, 0))
if self.level_completed:
self.end.draw()
else:
self.hero.draw()
self.walls.draw()
self.coins.draw()
def scale_box(
self, surface: pygame.Surface, rect: pygame.Rect, scale_factor: Coords
):
rect.size = self.box_sz
rect.scale_by_ip(*scale_factor)
surface = pygame.transform.scale(surface, rect.size)
return surface, rect
def handle_keys(self, keys_pressed):
if self.done:
return
if not self.done:
self.hero.handle_keys(keys_pressed)
self.check_level_completed()
self.end.handle_keys(keys_pressed)
def handle_exit(self, event: pygame.event.Event):
if IS_WASM:
return
if (
event.type == pygame.QUIT
or event.type == pygame.KEYDOWN
and event.key in self.exit_keys
):
self.done = True
def handle_event(self, event: pygame.event.Event):
self.handle_exit(event)
if self.done:
return
if event.type == pygame.KEYDOWN and event.key == pygame.K_m:
self.sound.toggle_mute()
self.hero.handle_event(event)
self.check_level_completed()
self.end.handle_event(event)
async def event_loop(self):
self.sound.play()
clock = pygame.time.Clock()
while not self.done:
for event in pygame.event.get():
self.handle_event(event)
self.handle_keys(pygame.key.get_pressed())
self.draw()
self.bg_shift = (self.bg_shift + 1) % self.rect.width
pygame.display.flip()
await asyncio.sleep(0)
clock.tick(self.fps)