feat: add game over modal
This commit is contained in:
@@ -4,13 +4,16 @@ window:
|
|||||||
title: "Tetri5"
|
title: "Tetri5"
|
||||||
|
|
||||||
sound:
|
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"
|
option-change: "resource/sound/option_change.wav"
|
||||||
piece-rotate: "resource/sound/piece_rotate.ogg"
|
piece-rotate: "resource/sound/piece_rotate.ogg"
|
||||||
piece-set: "resource/sound/piece_set.ogg"
|
piece-set: "resource/sound/piece_set.ogg"
|
||||||
line-complete: "resource/sound/line_complete.ogg"
|
line-complete: "resource/sound/line_complete.ogg"
|
||||||
four-lines-complete: "resource/sound/four_lines_complete.ogg"
|
four-lines-complete: "resource/sound/four_lines_complete.ogg"
|
||||||
level-up: "resource/sound/level_up.ogg"
|
level-up: "resource/sound/level_up.ogg"
|
||||||
|
game-over: "resource/sound/game_over.ogg"
|
||||||
|
you-win: "resource/sound/you_win.ogg"
|
||||||
|
|
||||||
image:
|
image:
|
||||||
title-screen: "resource/image/title_screen.png"
|
title-screen: "resource/image/title_screen.png"
|
||||||
|
|||||||
BIN
resource/sound/game_over.ogg
Normal file
BIN
resource/sound/game_over.ogg
Normal file
Binary file not shown.
BIN
resource/sound/theme_music_single.ogg
Normal file
BIN
resource/sound/theme_music_single.ogg
Normal file
Binary file not shown.
BIN
resource/sound/you_win.ogg
Normal file
BIN
resource/sound/you_win.ogg
Normal file
Binary file not shown.
27
tetri5/modal.py
Normal file
27
tetri5/modal.py
Normal file
@@ -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
|
||||||
@@ -9,6 +9,7 @@ from tetri5.entity import SquareColor, Well
|
|||||||
from tetri5.entity import Stack
|
from tetri5.entity import Stack
|
||||||
from tetri5.entity import PieceGenerator
|
from tetri5.entity import PieceGenerator
|
||||||
from tetri5.online import *
|
from tetri5.online import *
|
||||||
|
from tetri5.modal import GameOverModal
|
||||||
|
|
||||||
"""
|
"""
|
||||||
TODO
|
TODO
|
||||||
@@ -104,10 +105,16 @@ class SinglePlayerScene(Scene):
|
|||||||
ConfigurationManager.get("color", "well-border-1"))
|
ConfigurationManager.get("color", "well-border-1"))
|
||||||
self._stack = Stack()
|
self._stack = Stack()
|
||||||
|
|
||||||
|
self._game_over_modal = GameOverModal()
|
||||||
|
|
||||||
self._change_scence = change_scene
|
self._change_scence = change_scene
|
||||||
SoundManager.play_theme_music()
|
SoundManager.play_theme_music_single()
|
||||||
|
|
||||||
def draw(self, surface: pygame.Surface) -> None:
|
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)
|
surface.fill(self._background_color)
|
||||||
|
|
||||||
if self._stack:
|
if self._stack:
|
||||||
@@ -132,6 +139,10 @@ class SinglePlayerScene(Scene):
|
|||||||
TextGenerator.draw("LVL " + level, self._level_label_pos, surface)
|
TextGenerator.draw("LVL " + level, self._level_label_pos, surface)
|
||||||
|
|
||||||
def update(self, elapsed_time: int) -> None:
|
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:
|
if self._current_piece:
|
||||||
self._current_piece.update(elapsed_time,\
|
self._current_piece.update(elapsed_time,\
|
||||||
self._well,\
|
self._well,\
|
||||||
@@ -144,8 +155,8 @@ class SinglePlayerScene(Scene):
|
|||||||
self._next_piece = PieceGenerator.get_piece(self._next_piece_pos)
|
self._next_piece = PieceGenerator.get_piece(self._next_piece_pos)
|
||||||
# TODO create game over scene
|
# TODO create game over scene
|
||||||
if self._stack and self._current_piece.collide(self._stack):
|
if self._stack and self._current_piece.collide(self._stack):
|
||||||
pygame.quit()
|
SoundManager.stop_theme_music_single()
|
||||||
sys.exit()
|
self._game_over_modal.show(False)
|
||||||
|
|
||||||
if self._stack:
|
if self._stack:
|
||||||
self._stack.update(elapsed_time)
|
self._stack.update(elapsed_time)
|
||||||
@@ -308,9 +319,17 @@ class MultiplayerScene(Scene):
|
|||||||
self._current_piece_player_one = None
|
self._current_piece_player_one = None
|
||||||
self._current_piece_player_two = None
|
self._current_piece_player_two = None
|
||||||
|
|
||||||
|
self._game_over_modal = GameOverModal()
|
||||||
|
self._well_full = False
|
||||||
|
|
||||||
self._change_scence = change_scene
|
self._change_scence = change_scene
|
||||||
|
SoundManager.play_theme_music_multi()
|
||||||
|
|
||||||
def draw(self, surface: pygame.Surface) -> None:
|
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)
|
surface.fill(self._background_color)
|
||||||
|
|
||||||
# stacks
|
# stacks
|
||||||
@@ -352,6 +371,10 @@ class MultiplayerScene(Scene):
|
|||||||
TextGenerator.draw("NEXT", self._next_label_player_one_pos, surface)
|
TextGenerator.draw("NEXT", self._next_label_player_one_pos, surface)
|
||||||
|
|
||||||
def update(self, elapsed_time: int) -> None:
|
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_one(elapsed_time)
|
||||||
self._update_piece_player_two()
|
self._update_piece_player_two()
|
||||||
|
|
||||||
@@ -364,8 +387,10 @@ class MultiplayerScene(Scene):
|
|||||||
if opponent_stats is not None:
|
if opponent_stats is not None:
|
||||||
self._score_player_two = opponent_stats.score
|
self._score_player_two = opponent_stats.score
|
||||||
self._total_lines_player_two = opponent_stats.lines
|
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:
|
if self._current_piece_player_one is not None:
|
||||||
MultiplayerService.send_piece(PieceDto(self._current_piece_player_one._points,\
|
MultiplayerService.send_piece(PieceDto(self._current_piece_player_one._points,\
|
||||||
self._current_piece_player_one._center,\
|
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:
|
def _update_piece_player_one(self, elapsed_time: int) -> None:
|
||||||
if self._current_piece_player_one is not 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)
|
self._next_piece_player_one = PieceGenerator.get_piece(self._next_piece_player_one_pos)
|
||||||
|
|
||||||
# TODO create game over scene
|
# TODO create game over scene
|
||||||
if self._stack_player_one and self._current_piece_player_one.collide(self._stack_player_one):
|
if self._stack_player_one and self._current_piece_player_one.collide(self._stack_player_one):
|
||||||
pygame.quit()
|
self._well_full = True
|
||||||
MultiplayerService.quit()
|
SoundManager.stop_theme_music_multi()
|
||||||
sys.exit()
|
self._game_over_modal.show(False)
|
||||||
|
|
||||||
def _update_piece_player_two(self) -> None:
|
def _update_piece_player_two(self) -> None:
|
||||||
if self._current_piece_player_two is not None:
|
if self._current_piece_player_two is not None:
|
||||||
|
|||||||
@@ -46,26 +46,43 @@ class SoundManager:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def init(cls) -> None:
|
def init(cls) -> None:
|
||||||
pygame.mixer.init()
|
pygame.mixer.init()
|
||||||
cls._theme_music_ch = pygame.mixer.Channel(0)
|
cls._theme_music_single_ch = pygame.mixer.Channel(0)
|
||||||
cls._option_change_sfx_ch = pygame.mixer.Channel(1)
|
cls._theme_music_multi_ch = pygame.mixer.Channel(1)
|
||||||
cls._piece_rotate_sfx_ch = pygame.mixer.Channel(2)
|
cls._option_change_sfx_ch = pygame.mixer.Channel(2)
|
||||||
cls._piece_set_sfx_ch = pygame.mixer.Channel(3)
|
cls._piece_rotate_sfx_ch = pygame.mixer.Channel(3)
|
||||||
cls._line_complete_sfx_ch = pygame.mixer.Channel(4)
|
cls._piece_set_sfx_ch = pygame.mixer.Channel(4)
|
||||||
cls._four_lines_complete_sfx_ch = pygame.mixer.Channel(5)
|
cls._line_complete_sfx_ch = pygame.mixer.Channel(5)
|
||||||
cls._level_up_sfx_ch = pygame.mixer.Channel(6)
|
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._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_rotate_sfx = pygame.mixer.Sound(ConfigurationManager.get("sound", "piece-rotate"))
|
||||||
cls._piece_set_sfx = pygame.mixer.Sound(ConfigurationManager.get("sound", "piece-set"))
|
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._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._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._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
|
@classmethod
|
||||||
def play_theme_music(cls) -> None:
|
def play_theme_music_single(cls) -> None:
|
||||||
cls._theme_music_ch.set_volume(0.7)
|
cls._theme_music_single_ch.set_volume(0.7)
|
||||||
cls._theme_music_ch.play(cls._theme_music, -1)
|
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
|
@classmethod
|
||||||
def play_option_change_sfx(cls) -> None:
|
def play_option_change_sfx(cls) -> None:
|
||||||
@@ -93,6 +110,16 @@ class SoundManager:
|
|||||||
def play_level_up_sfx(cls) -> None:
|
def play_level_up_sfx(cls) -> None:
|
||||||
cls._level_up_sfx_ch.play(cls._level_up_sfx)
|
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
|
TODO description
|
||||||
"""
|
"""
|
||||||
@@ -152,6 +179,7 @@ class TextGenerator:
|
|||||||
cls._characters[":"] = (2 * glyph_size[0], 11 * glyph_size[1])
|
cls._characters[":"] = (2 * glyph_size[0], 11 * glyph_size[1])
|
||||||
cls._characters["_"] = (3 * glyph_size[0], 5 * 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["."] = (2 * glyph_size[0], 1 * glyph_size[1])
|
||||||
|
cls._characters["!"] = (1 * glyph_size[0], 0 * glyph_size[1])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def draw(cls, text: str, position: Tuple, surface: pygame.Surface) -> None:
|
def draw(cls, text: str, position: Tuple, surface: pygame.Surface) -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user