diff --git a/asset/music/bgm.wav b/asset/music/bgm.wav new file mode 100644 index 0000000..85fbd6c Binary files /dev/null and b/asset/music/bgm.wav differ diff --git a/asset/sounds/Coin.wav b/asset/sounds/Coin.wav new file mode 100644 index 0000000..ca52ea4 Binary files /dev/null and b/asset/sounds/Coin.wav differ diff --git a/asset/sounds/Low Boing.wav b/asset/sounds/Low Boing.wav new file mode 100644 index 0000000..cb62397 Binary files /dev/null and b/asset/sounds/Low Boing.wav differ diff --git a/game_config.json b/game_config.json index bd1b77b..a80230c 100644 --- a/game_config.json +++ b/game_config.json @@ -82,7 +82,18 @@ "min": -1, "max": 5, "default": "-1", - "help": "選定內建關卡,請注意,使用此設定將會覆蓋掉其他設定,預設為 -1 不選擇任何關卡。" + "help": "選定內建關卡,請注意,使用此設定將會覆蓋掉其他關卡設定,預設為 -1 不選擇任何關卡。" + }, + { + "name": "sound", + "verbose": "遊戲音效", + "type": "str", + "choices": [ + "on", + "off" + ], + "help": "'on' can turn on the sound.", + "default": "on" } ] } \ No newline at end of file diff --git a/src/enums.py b/src/enums.py deleted file mode 100644 index 67d67c9..0000000 --- a/src/enums.py +++ /dev/null @@ -1,6 +0,0 @@ - -from enum import auto -from mlgame.utils.enum import StringEnum -class FoodTypeEnum(StringEnum): - GREEN = auto() - RED = auto() diff --git a/src/env.py b/src/env.py new file mode 100644 index 0000000..82de125 --- /dev/null +++ b/src/env.py @@ -0,0 +1,31 @@ +from enum import auto +from os import path + +from mlgame.utils.enum import StringEnum +# game +WIDTH = 800 +HEIGHT = 600 +BG_COLOR = "#111111" +PG_COLOR = "#B3E5FC" + +# ball +BALL_COLOR = "#FFEB3B" +BALL_VEL = 10.5 +BALL_H = 30 +BALL_W = 30 + + +# food +class FoodTypeEnum(StringEnum): + GREEN = auto() + RED = auto() +FOOD_COLOR_MAP = {FoodTypeEnum.GREEN: "#009688", + FoodTypeEnum.RED: "#FF1744"} + +# path of assets +ASSET_PATH = path.join(path.dirname(__file__), "..", "asset") +LEVEL_PATH = path.join(path.dirname(__file__), "..", "levels") +SOUND_PATH = path.join(path.dirname(__file__), "..", "asset", "sounds") +MUSIC_PATH = path.join(path.dirname(__file__), "..", "asset", "music") + + diff --git a/src/game.py b/src/game.py index f69c57d..c77694a 100644 --- a/src/game.py +++ b/src/game.py @@ -1,7 +1,6 @@ import copy import json import os.path -from os import path import pygame @@ -9,16 +8,10 @@ from mlgame.game.paia_game import PaiaGame, GameResultState, GameStatus from mlgame.utils.enum import get_ai_name from mlgame.view.decorator import check_game_progress, check_game_result from mlgame.view.view_model import * -from .enums import FoodTypeEnum +from .env import * +from .env import FoodTypeEnum from .game_object import Ball, Food - -BG_COLOR = "#111111" -PG_COLOR = "#B3E5FC" - -WIDTH = 800 -HEIGHT = 600 -ASSET_PATH = path.join(path.dirname(__file__), "../asset") -LEVEL_PATH = path.join(path.dirname(__file__), "../levels") +from .sound_controller import SoundController class EasyGame(PaiaGame): @@ -30,7 +23,8 @@ class EasyGame(PaiaGame): self, time_to_play, score_to_pass, green_food_count, red_food_count, playground_size: list, level: int = -1, - # level_file, + level_file=None, + sound: str = "off", *args, **kwargs): super().__init__(user_num=1) @@ -56,10 +50,11 @@ class EasyGame(PaiaGame): self.playground.center = (WIDTH / 2, HEIGHT / 2) self.foods = pygame.sprite.Group() + self.sound_controller = SoundController(sound) self.init_game() def set_game_params_by_level(self, level): - level_file_path =os.path.join(LEVEL_PATH, f"{level:03d}.json") + level_file_path = os.path.join(LEVEL_PATH, f"{level:03d}.json") if os.path.exists(level_file_path): # If the file exists, load parameters from the file with open(level_file_path) as f: @@ -69,8 +64,7 @@ class EasyGame(PaiaGame): with open(os.path.join(LEVEL_PATH, "001.json")) as f: game_params = json.load(f) - self._level=1 - + self._level = 1 self._playground_w = int(game_params["playground_size"][0]) self._playground_h = int(game_params["playground_size"][1]) @@ -85,7 +79,6 @@ class EasyGame(PaiaGame): self._frame_limit = int(game_params["time_to_play"]) self.playground.center = (WIDTH / 2, HEIGHT / 2) - def init_game(self): self.ball = Ball() self.foods.empty() @@ -94,6 +87,7 @@ class EasyGame(PaiaGame): self._create_foods(self._red_food_count, FoodTypeEnum.RED) self.frame_count = 0 self._frame_count_down = self._frame_limit + self.sound_controller.play_music() def update(self, commands): # handle command @@ -111,12 +105,15 @@ class EasyGame(PaiaGame): # handle collision hits = pygame.sprite.spritecollide(self.ball, self.foods, True) if hits: + for food in hits: if food.type == FoodTypeEnum.GREEN: + self.sound_controller.play_eating_good() self.score += 1 self._create_foods(1, FoodTypeEnum.GREEN) elif food.type == FoodTypeEnum.RED: + self.sound_controller.play_eating_bad() self._create_foods(1, FoodTypeEnum.RED) self.score -= 1 # self._timer = round(time.time() - self._begin_time, 3) diff --git a/src/game_object.py b/src/game_object.py index bda8172..e7c316a 100644 --- a/src/game_object.py +++ b/src/game_object.py @@ -1,17 +1,8 @@ import pygame.sprite -from games.easy_game.src.enums import FoodTypeEnum +from games.easy_game.src.env import FoodTypeEnum, FOOD_COLOR_MAP, BALL_COLOR, BALL_VEL, BALL_H, BALL_W from mlgame.view.view_model import create_rect_view_data -FOOD_COLOR_MAP = {FoodTypeEnum.GREEN: "#009688", - FoodTypeEnum.RED: "#FF1744"} -BALL_COLOR = "#FFEB3B" -BALL_VEL = 10.5 - -BALL_H = 30 - -BALL_W = 30 - class Ball(pygame.sprite.Sprite): def __init__(self): diff --git a/src/sound_controller.py b/src/sound_controller.py new file mode 100644 index 0000000..b6688b5 --- /dev/null +++ b/src/sound_controller.py @@ -0,0 +1,40 @@ +import pygame + +from .env import * + + +def sound_enabled(func): + def wrapper(self, *args, **kwargs): + if self._is_sound_on: + return func(self, *args, **kwargs) + + return wrapper + + +class SoundController(): + def __init__(self, is_sound_on): + self._is_sound_on = bool(is_sound_on == "on") + if self._is_sound_on: + self.load_sounds() + + def load_sounds(self): + try: + pygame.mixer.init() + pygame.mixer.music.load(path.join(MUSIC_PATH, "bgm.wav")) + pygame.mixer.music.set_volume(0.6) + self._eating_good = pygame.mixer.Sound(path.join(SOUND_PATH, "Coin.wav")) + self._eating_bad = pygame.mixer.Sound(path.join(SOUND_PATH, "Low Boing.wav")) + except Exception: + self._is_sound_on = False + + @sound_enabled + def play_music(self): + pygame.mixer.music.play(-1) + + @sound_enabled + def play_eating_good(self): + self._eating_good.play() + + @sound_enabled + def play_eating_bad(self): + self._eating_bad.play()