diff --git a/config.yaml b/config.yaml index c0ed94e..ac00579 100644 --- a/config.yaml +++ b/config.yaml @@ -4,13 +4,16 @@ window: title: "Tetri5" sound: - theme-music: "resource/sound/theme_music.ogg" + theme-music-single: "resource/sound/theme_music_single.ogg" + theme-music-multi: "resource/sound/theme_music_multi.ogg" option-change: "resource/sound/option_change.wav" piece-rotate: "resource/sound/piece_rotate.ogg" piece-set: "resource/sound/piece_set.ogg" line-complete: "resource/sound/line_complete.ogg" four-lines-complete: "resource/sound/four_lines_complete.ogg" level-up: "resource/sound/level_up.ogg" + game-over: "resource/sound/game_over.ogg" + you-win: "resource/sound/you_win.ogg" image: title-screen: "resource/image/title_screen.png" diff --git a/resource/sound/game_over.ogg b/resource/sound/game_over.ogg new file mode 100644 index 0000000..df93f1a Binary files /dev/null and b/resource/sound/game_over.ogg differ diff --git a/resource/sound/theme_music.ogg b/resource/sound/theme_music_multi.ogg similarity index 100% rename from resource/sound/theme_music.ogg rename to resource/sound/theme_music_multi.ogg diff --git a/resource/sound/theme_music_single.ogg b/resource/sound/theme_music_single.ogg new file mode 100644 index 0000000..9e6c177 Binary files /dev/null and b/resource/sound/theme_music_single.ogg differ diff --git a/resource/sound/you_win.ogg b/resource/sound/you_win.ogg new file mode 100644 index 0000000..554299d Binary files /dev/null and b/resource/sound/you_win.ogg differ diff --git a/tetri5/modal.py b/tetri5/modal.py new file mode 100644 index 0000000..075c5ed --- /dev/null +++ b/tetri5/modal.py @@ -0,0 +1,27 @@ +import pygame +from pygame import Surface +from tetri5.util import SoundManager, TextGenerator + +class GameOverModal: + def __init__(self): + self.is_open = False + self.is_winner = False + self.music_played = False + + def show(self, is_winner: bool) -> None: + self.is_open = True + self.is_winner = is_winner + + def draw(self, surface: Surface) -> None: + pygame.draw.rect(surface, "black", pygame.Rect(290, 240, 220, 100)) + pygame.draw.rect(surface, "white", pygame.Rect(290, 240, 220, 100), 3, 5) + TextGenerator.draw("YOU LOSE" if not self.is_winner else "YOU WIN!", (320, 260), surface) + TextGenerator.draw("GAME OVER", (310, 300), surface) + + def update(self, _: int) -> None: + if not self.music_played: + if self.is_winner: + SoundManager.play_you_win_sfx() + else: + SoundManager.play_game_over_sfx() + self.music_played = True \ No newline at end of file diff --git a/tetri5/scene.py b/tetri5/scene.py index c9dbadf..c7ca716 100644 --- a/tetri5/scene.py +++ b/tetri5/scene.py @@ -9,6 +9,7 @@ from tetri5.entity import SquareColor, Well from tetri5.entity import Stack from tetri5.entity import PieceGenerator from tetri5.online import * +from tetri5.modal import GameOverModal """ TODO @@ -104,10 +105,16 @@ class SinglePlayerScene(Scene): ConfigurationManager.get("color", "well-border-1")) self._stack = Stack() + self._game_over_modal = GameOverModal() + self._change_scence = change_scene - SoundManager.play_theme_music() + SoundManager.play_theme_music_single() def draw(self, surface: pygame.Surface) -> None: + if self._game_over_modal.is_open: + self._game_over_modal.draw(surface) + return + surface.fill(self._background_color) if self._stack: @@ -132,6 +139,10 @@ class SinglePlayerScene(Scene): TextGenerator.draw("LVL " + level, self._level_label_pos, surface) def update(self, elapsed_time: int) -> None: + if self._game_over_modal.is_open: + self._game_over_modal.update(elapsed_time) + return + if self._current_piece: self._current_piece.update(elapsed_time,\ self._well,\ @@ -144,8 +155,8 @@ class SinglePlayerScene(Scene): self._next_piece = PieceGenerator.get_piece(self._next_piece_pos) # TODO create game over scene if self._stack and self._current_piece.collide(self._stack): - pygame.quit() - sys.exit() + SoundManager.stop_theme_music_single() + self._game_over_modal.show(False) if self._stack: self._stack.update(elapsed_time) @@ -308,9 +319,17 @@ class MultiplayerScene(Scene): self._current_piece_player_one = None self._current_piece_player_two = None + self._game_over_modal = GameOverModal() + self._well_full = False + self._change_scence = change_scene + SoundManager.play_theme_music_multi() def draw(self, surface: pygame.Surface) -> None: + if self._game_over_modal.is_open: + self._game_over_modal.draw(surface) + return + surface.fill(self._background_color) # stacks @@ -352,6 +371,10 @@ class MultiplayerScene(Scene): TextGenerator.draw("NEXT", self._next_label_player_one_pos, surface) def update(self, elapsed_time: int) -> None: + if self._game_over_modal.is_open: + self._game_over_modal.update(elapsed_time) + return + self._update_piece_player_one(elapsed_time) self._update_piece_player_two() @@ -364,8 +387,10 @@ class MultiplayerScene(Scene): if opponent_stats is not None: self._score_player_two = opponent_stats.score self._total_lines_player_two = opponent_stats.lines + if opponent_stats.is_well_full: + SoundManager.stop_theme_music_multi() + self._game_over_modal.show(True) - # SEND TO SERVER if self._current_piece_player_one is not None: MultiplayerService.send_piece(PieceDto(self._current_piece_player_one._points,\ self._current_piece_player_one._center,\ @@ -382,7 +407,7 @@ class MultiplayerScene(Scene): ], ) ) - MultiplayerService.send_stats(StatsDto(self._score_player_one, self._stack_player_one.total_lines, False)) + MultiplayerService.send_stats(StatsDto(self._score_player_one, self._stack_player_one.total_lines, self._well_full)) def _update_piece_player_one(self, elapsed_time: int) -> None: if self._current_piece_player_one is not None: @@ -397,10 +422,10 @@ class MultiplayerScene(Scene): self._next_piece_player_one = PieceGenerator.get_piece(self._next_piece_player_one_pos) # TODO create game over scene - if self._stack_player_one and self._current_piece_player_one.collide(self._stack_player_one): - pygame.quit() - MultiplayerService.quit() - sys.exit() + if self._stack_player_one and self._current_piece_player_one.collide(self._stack_player_one): + self._well_full = True + SoundManager.stop_theme_music_multi() + self._game_over_modal.show(False) def _update_piece_player_two(self) -> None: if self._current_piece_player_two is not None: diff --git a/tetri5/util.py b/tetri5/util.py index 3060aa5..fc4747b 100644 --- a/tetri5/util.py +++ b/tetri5/util.py @@ -46,26 +46,43 @@ class SoundManager: @classmethod def init(cls) -> None: pygame.mixer.init() - cls._theme_music_ch = pygame.mixer.Channel(0) - cls._option_change_sfx_ch = pygame.mixer.Channel(1) - cls._piece_rotate_sfx_ch = pygame.mixer.Channel(2) - cls._piece_set_sfx_ch = pygame.mixer.Channel(3) - cls._line_complete_sfx_ch = pygame.mixer.Channel(4) - cls._four_lines_complete_sfx_ch = pygame.mixer.Channel(5) - cls._level_up_sfx_ch = pygame.mixer.Channel(6) + cls._theme_music_single_ch = pygame.mixer.Channel(0) + cls._theme_music_multi_ch = pygame.mixer.Channel(1) + cls._option_change_sfx_ch = pygame.mixer.Channel(2) + cls._piece_rotate_sfx_ch = pygame.mixer.Channel(3) + cls._piece_set_sfx_ch = pygame.mixer.Channel(4) + cls._line_complete_sfx_ch = pygame.mixer.Channel(5) + cls._four_lines_complete_sfx_ch = pygame.mixer.Channel(6) + cls._level_up_sfx_ch = pygame.mixer.Channel(7) - cls._theme_music = pygame.mixer.Sound(ConfigurationManager.get("sound", "theme-music")) + cls._theme_music_single = pygame.mixer.Sound(ConfigurationManager.get("sound", "theme-music-single")) + cls._theme_music_multi = pygame.mixer.Sound(ConfigurationManager.get("sound", "theme-music-multi")) cls._option_change_sfx = pygame.mixer.Sound(ConfigurationManager.get("sound", "option-change")) cls._piece_rotate_sfx = pygame.mixer.Sound(ConfigurationManager.get("sound", "piece-rotate")) cls._piece_set_sfx = pygame.mixer.Sound(ConfigurationManager.get("sound", "piece-set")) cls._line_complete_sfx = pygame.mixer.Sound(ConfigurationManager.get("sound", "line-complete")) cls._four_lines_complete_sfx = pygame.mixer.Sound(ConfigurationManager.get("sound", "four-lines-complete")) cls._level_up_sfx = pygame.mixer.Sound(ConfigurationManager.get("sound", "level-up")) + cls._game_over_sfx = pygame.mixer.Sound(ConfigurationManager.get("sound", "game-over")) + cls._you_win_sfx = pygame.mixer.Sound(ConfigurationManager.get("sound", "you-win")) @classmethod - def play_theme_music(cls) -> None: - cls._theme_music_ch.set_volume(0.7) - cls._theme_music_ch.play(cls._theme_music, -1) + def play_theme_music_single(cls) -> None: + cls._theme_music_single_ch.set_volume(0.7) + cls._theme_music_single_ch.play(cls._theme_music_single, -1) + + @classmethod + def stop_theme_music_single(cls) -> None: + cls._theme_music_single_ch.stop() + + @classmethod + def play_theme_music_multi(cls) -> None: + cls._theme_music_multi_ch.set_volume(0.7) + cls._theme_music_multi_ch.play(cls._theme_music_multi, -1) + + @classmethod + def stop_theme_music_multi(cls) -> None: + cls._theme_music_multi_ch.stop() @classmethod def play_option_change_sfx(cls) -> None: @@ -93,6 +110,16 @@ class SoundManager: def play_level_up_sfx(cls) -> None: cls._level_up_sfx_ch.play(cls._level_up_sfx) + @classmethod + def play_game_over_sfx(cls) -> None: + cls._game_over_sfx.set_volume(0.7) + cls._game_over_sfx.play() + + @classmethod + def play_you_win_sfx(cls) -> None: + cls._you_win_sfx.set_volume(0.7) + cls._you_win_sfx.play() + """ TODO description """ @@ -152,6 +179,7 @@ class TextGenerator: cls._characters[":"] = (2 * glyph_size[0], 11 * glyph_size[1]) cls._characters["_"] = (3 * glyph_size[0], 5 * glyph_size[1]) cls._characters["."] = (2 * glyph_size[0], 1 * glyph_size[1]) + cls._characters["!"] = (1 * glyph_size[0], 0 * glyph_size[1]) @classmethod def draw(cls, text: str, position: Tuple, surface: pygame.Surface) -> None: