feat: improve game music
This commit is contained in:
10
config.yaml
10
config.yaml
@@ -4,9 +4,13 @@ window:
|
||||
title: "Tetri5"
|
||||
|
||||
sound:
|
||||
main-music: "resource/sound/main_music.ogg"
|
||||
row-completion: "resource/sound/row_completion.wav"
|
||||
piece-set: "resource/sound/piece_set_3.wav"
|
||||
theme-music: "resource/sound/theme_music.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"
|
||||
|
||||
image:
|
||||
title-screen: "resource/image/title_screen.png"
|
||||
|
||||
BIN
resource/sound/four_lines_complete.ogg
Normal file
BIN
resource/sound/four_lines_complete.ogg
Normal file
Binary file not shown.
BIN
resource/sound/level_up.ogg
Normal file
BIN
resource/sound/level_up.ogg
Normal file
Binary file not shown.
BIN
resource/sound/line_complete.ogg
Normal file
BIN
resource/sound/line_complete.ogg
Normal file
Binary file not shown.
Binary file not shown.
BIN
resource/sound/piece_rotate.ogg
Normal file
BIN
resource/sound/piece_rotate.ogg
Normal file
Binary file not shown.
BIN
resource/sound/piece_set.ogg
Normal file
BIN
resource/sound/piece_set.ogg
Normal file
Binary file not shown.
Binary file not shown.
@@ -6,6 +6,7 @@ from typing import List, Tuple
|
||||
from types import FunctionType
|
||||
from tetri5.util import ConfigurationManager
|
||||
from tetri5.util import Controller
|
||||
from tetri5.util import SoundManager
|
||||
|
||||
"""
|
||||
TODO description
|
||||
@@ -85,7 +86,6 @@ class Piece(Entity):
|
||||
super().__init__(Piece._get_points(shape, position), color, border_color)
|
||||
self._inner_border_color = inner_border_color
|
||||
self._center = self._get_center(shape, position)
|
||||
self._piece_set_sound = mixer.Channel(2)
|
||||
self._previous_points = None
|
||||
self._previous_center = None
|
||||
|
||||
@@ -118,6 +118,8 @@ class Piece(Entity):
|
||||
self.rotate()
|
||||
if well and self.collide(well) or stack and self.collide(stack):
|
||||
self.revert()
|
||||
else:
|
||||
SoundManager.play_piece_rotate_sfx()
|
||||
if Controller.key_down(pygame.K_LEFT):
|
||||
self.move((-self._tile_size, 0))
|
||||
if well and self.collide(well) or stack and self.collide(stack):
|
||||
@@ -223,7 +225,7 @@ class Piece(Entity):
|
||||
if self._current_set_time >= self._set_time:
|
||||
self._current_set_time = 0
|
||||
if self._entity_is_below(well) or self._entity_is_below(stack):
|
||||
self._play_piece_set_sound()
|
||||
SoundManager.play_piece_set_sfx()
|
||||
stack.add_piece(self)
|
||||
clear_current_piece()
|
||||
else:
|
||||
@@ -240,10 +242,6 @@ class Piece(Entity):
|
||||
|
||||
return mimic_points
|
||||
|
||||
def _play_piece_set_sound(self) -> None:
|
||||
piece_set_sound_file = ConfigurationManager.get("sound", "piece-set")
|
||||
self._piece_set_sound.play(mixer.Sound(piece_set_sound_file))
|
||||
|
||||
def _entity_is_below(self, entity: Entity) -> bool:
|
||||
mimic_points = self._mimic_move((0, self._tile_size))
|
||||
return entity and entity._collide(mimic_points)
|
||||
@@ -275,7 +273,6 @@ class Stack(Entity):
|
||||
super().__init__([], color, border_color)
|
||||
self.total_lines = 0
|
||||
self.lines_completed_last = 0
|
||||
self.line_completed_sound = mixer.Channel(1)
|
||||
|
||||
def update(self, elapsed_time: int) -> None: # TODO remove scene argument
|
||||
super().update(elapsed_time)
|
||||
@@ -305,7 +302,11 @@ class Stack(Entity):
|
||||
if not squares_to_exclude:
|
||||
return 0
|
||||
|
||||
self._play_line_completed_sound()
|
||||
if len(rows_completed) == 4:
|
||||
SoundManager.play_four_lines_complete_sfx()
|
||||
else:
|
||||
SoundManager.play_line_complete_sfx()
|
||||
|
||||
new_points = []
|
||||
for square in self._points:
|
||||
if square not in squares_to_exclude:
|
||||
@@ -314,17 +315,12 @@ class Stack(Entity):
|
||||
vertex[1] <= row_completed
|
||||
for row_completed in rows_completed
|
||||
)
|
||||
|
||||
vertex[1] += self._tile_size * distance_to_move
|
||||
new_points.append(square)
|
||||
self._points = new_points
|
||||
|
||||
return len(rows_completed)
|
||||
|
||||
def _play_line_completed_sound(self) -> None:
|
||||
line_completed_sound_file = ConfigurationManager.get("sound", "row-completion")
|
||||
self.line_completed_sound.play(mixer.Sound(line_completed_sound_file))
|
||||
|
||||
"""
|
||||
TODO description
|
||||
"""
|
||||
|
||||
@@ -2,21 +2,19 @@ import sys
|
||||
import pygame
|
||||
from tetri5.util import ConfigurationManager
|
||||
from tetri5.util import TextGenerator
|
||||
from tetri5.util import SoundManager
|
||||
from tetri5.scene import Scene, TitleScene
|
||||
|
||||
# TODO improve game assets https://www.spriters-resource.com/nes/tetris/
|
||||
# TODO should be a singleton and refactor the whole file?
|
||||
# TODO create a util that manages sfx
|
||||
class Game:
|
||||
|
||||
_current_scene = None
|
||||
|
||||
@classmethod
|
||||
def change_scene(cls, scene: Scene) -> None:
|
||||
cls._current_scene = scene
|
||||
|
||||
@classmethod
|
||||
def init(cls) -> None:
|
||||
pygame.init()
|
||||
SoundManager.init()
|
||||
TextGenerator.init(ConfigurationManager.get("image", "font"), (20, 20))
|
||||
cls._current_scene = TitleScene(Game.change_scene)
|
||||
|
||||
@@ -32,7 +30,6 @@ class Game:
|
||||
pygame.display.set_caption(win_title)
|
||||
pygame.display.set_icon(pygame.image.load(win_icon))
|
||||
|
||||
# gets called from the games main loop
|
||||
@classmethod
|
||||
def update(cls) -> None:
|
||||
# TODO write not initialized exception
|
||||
@@ -49,12 +46,15 @@ class Game:
|
||||
@classmethod
|
||||
def draw(cls) -> None:
|
||||
# TODO write not initialized exception
|
||||
|
||||
if cls._current_scene:
|
||||
cls._current_scene.draw(cls.screen)
|
||||
|
||||
# update display
|
||||
pygame.display.update()
|
||||
|
||||
@classmethod
|
||||
def change_scene(cls, scene: Scene) -> None:
|
||||
cls._current_scene = scene
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import sys
|
||||
import pygame
|
||||
from pygame import mixer
|
||||
from types import FunctionType
|
||||
from tetri5.util import ConfigurationManager
|
||||
from tetri5.util import TextGenerator
|
||||
from tetri5.util import Controller
|
||||
from tetri5.util import SoundManager
|
||||
from tetri5.entity import Well
|
||||
from tetri5.entity import Stack
|
||||
from tetri5.entity import PieceGenerator
|
||||
@@ -39,7 +39,6 @@ class TitleScene(Scene):
|
||||
self._option_one_position = ConfigurationManager.get("position", "option-one")
|
||||
self._option_two_position = ConfigurationManager.get("position", "option-two")
|
||||
self._is_multiplayer = False
|
||||
|
||||
self._change_scence = change_scene
|
||||
|
||||
def draw(self, surface: pygame.Surface) -> None:
|
||||
@@ -53,12 +52,18 @@ class TitleScene(Scene):
|
||||
pygame.draw.circle(surface, self._cursor_color, self._cursor_position, self._tile_size // 3)
|
||||
|
||||
def update(self, elapsed_time: int) -> None:
|
||||
if Controller.key_pressed(pygame.K_UP):
|
||||
option_change = False
|
||||
if Controller.key_pressed(pygame.K_UP) and self._is_multiplayer:
|
||||
self._cursor_position = self._cursor_position_one
|
||||
self._is_multiplayer = False
|
||||
if Controller.key_pressed(pygame.K_DOWN):
|
||||
option_change = True
|
||||
if Controller.key_pressed(pygame.K_DOWN) and not self._is_multiplayer:
|
||||
self._cursor_position = self._cursor_position_two
|
||||
self._is_multiplayer = True
|
||||
option_change = True
|
||||
|
||||
if option_change:
|
||||
SoundManager.play_option_change_sfx() # TODO add cool down
|
||||
|
||||
self._cursor_blink_time += elapsed_time
|
||||
if self._cursor_blink_time >= self._cursor_blink_interval:
|
||||
@@ -66,7 +71,7 @@ class TitleScene(Scene):
|
||||
self._cursor_off = not self._cursor_off
|
||||
|
||||
if Controller.key_pressed(pygame.K_RETURN):
|
||||
self._change_scence(SinglePlayerScene(self._change_scence))
|
||||
self._change_scence(SinglePlayerScene(self._change_scence)) # TODO implement multiplayer
|
||||
|
||||
"""
|
||||
TODO
|
||||
@@ -77,17 +82,14 @@ class SinglePlayerScene(Scene):
|
||||
self._tile_size = ConfigurationManager.get("engine", "tile-size")
|
||||
self._background_color = pygame.Color(ConfigurationManager.get("color", "window-bg"))
|
||||
self._score = 0
|
||||
self._level = 0
|
||||
self._previous_level = 0
|
||||
self._well = Well((280, 80), ConfigurationManager.get("color", "well-1"), ConfigurationManager.get("color", "well-border-1")) # TODO calculate position later and redo color config for well
|
||||
self._stack = Stack(ConfigurationManager.get("color", "stack-1"), ConfigurationManager.get("color", "stack-border-1"))
|
||||
self._current_piece = None
|
||||
self._next_piece = PieceGenerator.get_piece((620, 160))
|
||||
self._main_music = mixer.Channel(0)
|
||||
self._main_music.set_volume(0.7) # TODO add volume to the config
|
||||
self._main_music.play(mixer.Sound(ConfigurationManager.get("sound", "main-music")), -1)
|
||||
self._points_table = ConfigurationManager.get("engine", "points-table")
|
||||
|
||||
self._change_scence = change_scene
|
||||
SoundManager.play_theme_music()
|
||||
|
||||
def draw(self, surface: pygame.Surface) -> None:
|
||||
surface.fill(self._background_color)
|
||||
@@ -132,6 +134,10 @@ class SinglePlayerScene(Scene):
|
||||
self._stack.update(elapsed_time)
|
||||
|
||||
self._score += self._points_table[self._stack.lines_completed_last] * (self._get_level() + 1)
|
||||
|
||||
if self._previous_level != self._get_level():
|
||||
self._previous_level = self._get_level()
|
||||
SoundManager.play_level_up_sfx()
|
||||
|
||||
def _get_level(self) -> int:
|
||||
lines_per_level = ConfigurationManager.get("engine", "lines-per-level")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import yaml
|
||||
import pygame
|
||||
from typing import KeysView, Tuple
|
||||
from typing import Tuple
|
||||
|
||||
"""
|
||||
TODO description
|
||||
@@ -22,6 +22,77 @@ class ConfigurationManager:
|
||||
else:
|
||||
return cls._configuration[key]
|
||||
|
||||
"""
|
||||
TODO description
|
||||
"""
|
||||
class SoundManager:
|
||||
|
||||
# Channels
|
||||
_theme_music_ch = None
|
||||
_option_change_sfx_ch = None
|
||||
_piece_rotate_sfx_ch = None
|
||||
_piece_set_sfx_ch = None
|
||||
_line_complete_sfx_ch = None
|
||||
_four_lines_complete_sfx_ch = None
|
||||
|
||||
# Sounds
|
||||
_theme_music = None
|
||||
_option_change_sfx = None
|
||||
_piece_rotate_sfx = None
|
||||
_piece_set_sfx = None
|
||||
_line_complete_sfx = None
|
||||
_four_lines_complete_sfx = None
|
||||
|
||||
@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 = pygame.mixer.Sound(ConfigurationManager.get("sound", "theme-music"))
|
||||
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"))
|
||||
|
||||
@classmethod
|
||||
def play_theme_music(cls) -> None:
|
||||
cls._theme_music_ch.set_volume(0.7)
|
||||
cls._theme_music_ch.play(cls._theme_music, -1)
|
||||
|
||||
@classmethod
|
||||
def play_option_change_sfx(cls) -> None:
|
||||
cls._option_change_sfx_ch.set_volume(0.8)
|
||||
cls._option_change_sfx_ch.play(cls._option_change_sfx)
|
||||
|
||||
@classmethod
|
||||
def play_piece_rotate_sfx(cls) -> None:
|
||||
cls._piece_rotate_sfx_ch.set_volume(0.7)
|
||||
cls._piece_rotate_sfx_ch.play(cls._piece_rotate_sfx)
|
||||
|
||||
@classmethod
|
||||
def play_piece_set_sfx(cls) -> None:
|
||||
cls._piece_set_sfx_ch.play(cls._piece_set_sfx)
|
||||
|
||||
@classmethod
|
||||
def play_line_complete_sfx(cls) -> None:
|
||||
cls._line_complete_sfx_ch.play(cls._line_complete_sfx)
|
||||
|
||||
@classmethod
|
||||
def play_four_lines_complete_sfx(cls) -> None:
|
||||
cls._four_lines_complete_sfx_ch.play(cls._four_lines_complete_sfx)
|
||||
|
||||
@classmethod
|
||||
def play_level_up_sfx(cls) -> None:
|
||||
cls._level_up_sfx_ch.play(cls._level_up_sfx)
|
||||
|
||||
"""
|
||||
TODO description
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user