diff --git a/assets/bg.ogg b/assets/bg.ogg new file mode 100644 index 0000000..397bde9 Binary files /dev/null and b/assets/bg.ogg differ diff --git a/pygame-wasm/phantomcastle/Makefile b/pygame-wasm/phantomcastle/Makefile index 2420985..22ccc43 100644 --- a/pygame-wasm/phantomcastle/Makefile +++ b/pygame-wasm/phantomcastle/Makefile @@ -1,11 +1,11 @@ -assets_files = assets/bg1k.png assets/brick.png assets/coin.png assets/ghost.png assets/win.png +assets_files = assets/bg1k.png assets/brick.png assets/coin.png assets/ghost.png assets/win.png assets/bg.ogg all: build/web.zip assets: mkdir assets -assets/%.png: assets $(../../assets/*.png) +assets/%: assets $(../../assets/*) cp ../../$@ assets/ build/web: Makefile main.py $(assets_files) diff --git a/pygame-wasm/phantomcastle/common.py b/pygame-wasm/phantomcastle/common.py index f6cac23..dfeffe0 100644 --- a/pygame-wasm/phantomcastle/common.py +++ b/pygame-wasm/phantomcastle/common.py @@ -12,6 +12,15 @@ import pygame from coords import Coords +class SingletonMeta(type): + _instances = {} + + def __call__(cls, *args, **kwargs): + if cls not in cls._instances: + cls._instances[cls] = super(SingletonMeta, cls).__call__(*args, **kwargs) + return cls._instances[cls] + + class SurfaceWithRect(NamedTuple): surface: pygame.Surface rect: pygame.Rect diff --git a/pygame-wasm/phantomcastle/game/scene.py b/pygame-wasm/phantomcastle/game/scene.py index a3818fd..3b0b6fc 100644 --- a/pygame-wasm/phantomcastle/game/scene.py +++ b/pygame-wasm/phantomcastle/game/scene.py @@ -8,6 +8,7 @@ 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): @@ -60,6 +61,8 @@ class Scene(DrawableGameObject, EventHandler): 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) @@ -119,11 +122,14 @@ class Scene(DrawableGameObject, EventHandler): 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(): diff --git a/pygame-wasm/phantomcastle/main.py b/pygame-wasm/phantomcastle/main.py index b2d4f8f..d58ff05 100644 --- a/pygame-wasm/phantomcastle/main.py +++ b/pygame-wasm/phantomcastle/main.py @@ -6,6 +6,7 @@ После прохождения уровня можно начать новый (кнопкой N) или выйти из игры. Также можно управлять мышкой, перетаскивая героя (зажав ЛКМ) и кликая на надпись, для начала новой игры. + Музыку можно заглушить (или вернуть), нажав на кнопку M. Это универсальная версия. Подходит для сборки в виде WASM (для браузера) игры, с помощью pygbag и для запуска напрямую. @@ -61,6 +62,7 @@ async def main(): "brick.png", "win.png", "coin.png", + "bg.ogg", ] with get_assets_direct(required_assets) as assets: await game(assets) diff --git a/pygame-wasm/phantomcastle/sound.py b/pygame-wasm/phantomcastle/sound.py new file mode 100644 index 0000000..1ba8458 --- /dev/null +++ b/pygame-wasm/phantomcastle/sound.py @@ -0,0 +1,37 @@ +import pygame +from common import SingletonMeta + + +class BackgroundSound(pygame.mixer.Sound, metaclass=SingletonMeta): + def __init__(self, filename): + super().__init__(filename) + self.set_volume(0.5) + self._muted = False + self._played = False + + def play(self): + if not self._played: + super().play(loops=-1) + self._played = True + + def mute(self): + self._muted = True + self.set_volume(0) + + def unmute(self): + self._muted = False + self.set_volume(0.5) + + @property + def muted(self): + return self._muted + + @muted.setter + def muted(self, value): + if value: + self.mute() + else: + self.unmute() + + def toggle_mute(self): + self.muted = not self.muted