feat: add bgm and sounds

This commit is contained in:
Kylin_on_Mac 2023-09-23 10:23:17 +08:00
parent 36864f494d
commit bfc5ab7c9a
9 changed files with 96 additions and 32 deletions

BIN
asset/music/bgm.wav Normal file

Binary file not shown.

BIN
asset/sounds/Coin.wav Normal file

Binary file not shown.

BIN
asset/sounds/Low Boing.wav Normal file

Binary file not shown.

View File

@ -82,7 +82,18 @@
"min": -1, "min": -1,
"max": 5, "max": 5,
"default": "-1", "default": "-1",
"help": "選定內建關卡,請注意,使用此設定將會覆蓋掉其他設定,預設為 -1 不選擇任何關卡。" "help": "選定內建關卡,請注意,使用此設定將會覆蓋掉其他關卡設定,預設為 -1 不選擇任何關卡。"
},
{
"name": "sound",
"verbose": "遊戲音效",
"type": "str",
"choices": [
"on",
"off"
],
"help": "'on' can turn on the sound.",
"default": "on"
} }
] ]
} }

View File

@ -1,6 +0,0 @@
from enum import auto
from mlgame.utils.enum import StringEnum
class FoodTypeEnum(StringEnum):
GREEN = auto()
RED = auto()

31
src/env.py Normal file
View File

@ -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")

View File

@ -1,7 +1,6 @@
import copy import copy
import json import json
import os.path import os.path
from os import path
import pygame 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.utils.enum import get_ai_name
from mlgame.view.decorator import check_game_progress, check_game_result from mlgame.view.decorator import check_game_progress, check_game_result
from mlgame.view.view_model import * from mlgame.view.view_model import *
from .enums import FoodTypeEnum from .env import *
from .env import FoodTypeEnum
from .game_object import Ball, Food from .game_object import Ball, Food
from .sound_controller import SoundController
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")
class EasyGame(PaiaGame): class EasyGame(PaiaGame):
@ -30,7 +23,8 @@ class EasyGame(PaiaGame):
self, time_to_play, score_to_pass, green_food_count, red_food_count, self, time_to_play, score_to_pass, green_food_count, red_food_count,
playground_size: list, playground_size: list,
level: int = -1, level: int = -1,
# level_file, level_file=None,
sound: str = "off",
*args, **kwargs): *args, **kwargs):
super().__init__(user_num=1) super().__init__(user_num=1)
@ -56,10 +50,11 @@ class EasyGame(PaiaGame):
self.playground.center = (WIDTH / 2, HEIGHT / 2) self.playground.center = (WIDTH / 2, HEIGHT / 2)
self.foods = pygame.sprite.Group() self.foods = pygame.sprite.Group()
self.sound_controller = SoundController(sound)
self.init_game() self.init_game()
def set_game_params_by_level(self, level): 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 os.path.exists(level_file_path):
# If the file exists, load parameters from the file # If the file exists, load parameters from the file
with open(level_file_path) as f: 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: with open(os.path.join(LEVEL_PATH, "001.json")) as f:
game_params = json.load(f) game_params = json.load(f)
self._level=1 self._level = 1
self._playground_w = int(game_params["playground_size"][0]) self._playground_w = int(game_params["playground_size"][0])
self._playground_h = int(game_params["playground_size"][1]) 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._frame_limit = int(game_params["time_to_play"])
self.playground.center = (WIDTH / 2, HEIGHT / 2) self.playground.center = (WIDTH / 2, HEIGHT / 2)
def init_game(self): def init_game(self):
self.ball = Ball() self.ball = Ball()
self.foods.empty() self.foods.empty()
@ -94,6 +87,7 @@ class EasyGame(PaiaGame):
self._create_foods(self._red_food_count, FoodTypeEnum.RED) self._create_foods(self._red_food_count, FoodTypeEnum.RED)
self.frame_count = 0 self.frame_count = 0
self._frame_count_down = self._frame_limit self._frame_count_down = self._frame_limit
self.sound_controller.play_music()
def update(self, commands): def update(self, commands):
# handle command # handle command
@ -111,12 +105,15 @@ class EasyGame(PaiaGame):
# handle collision # handle collision
hits = pygame.sprite.spritecollide(self.ball, self.foods, True) hits = pygame.sprite.spritecollide(self.ball, self.foods, True)
if hits: if hits:
for food in hits: for food in hits:
if food.type == FoodTypeEnum.GREEN: if food.type == FoodTypeEnum.GREEN:
self.sound_controller.play_eating_good()
self.score += 1 self.score += 1
self._create_foods(1, FoodTypeEnum.GREEN) self._create_foods(1, FoodTypeEnum.GREEN)
elif food.type == FoodTypeEnum.RED: elif food.type == FoodTypeEnum.RED:
self.sound_controller.play_eating_bad()
self._create_foods(1, FoodTypeEnum.RED) self._create_foods(1, FoodTypeEnum.RED)
self.score -= 1 self.score -= 1
# self._timer = round(time.time() - self._begin_time, 3) # self._timer = round(time.time() - self._begin_time, 3)

View File

@ -1,17 +1,8 @@
import pygame.sprite 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 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): class Ball(pygame.sprite.Sprite):
def __init__(self): def __init__(self):

40
src/sound_controller.py Normal file
View File

@ -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()