Merge branch 'release/2.3.2-alpha'
This commit is contained in:
commit
6cc58de054
15
README.md
15
README.md
|
@ -65,7 +65,8 @@ game = EasyGame(
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 在easy game中,打開終端機
|
# 在easy game中,打開終端機
|
||||||
python -m mlgame -i ./ml/ml_play_template.py ./ --time_to_play 1200 --green_food_count 15 --red_food_count 10 --score_to_pass 10 --playground_size 100,200
|
python -m mlgame -i ./ml/ml_play_template.py ./ --level 3
|
||||||
|
python -m mlgame -i ./ml/ml_play_template.py ./ --level_file /path_to_file/level_file.json
|
||||||
```
|
```
|
||||||
|
|
||||||
## AI範例
|
## AI範例
|
||||||
|
@ -100,8 +101,10 @@ class MLPlay:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"frame": 25,
|
"frame": 25,
|
||||||
"ball_x": 425,
|
"player_x": 425,
|
||||||
"ball_y": 306,
|
"player_y": 306,
|
||||||
|
"player_size": 90,
|
||||||
|
"player_vel": 16,
|
||||||
"foods": [
|
"foods": [
|
||||||
{
|
{
|
||||||
"x": 656,
|
"x": 656,
|
||||||
|
@ -124,8 +127,10 @@ class MLPlay:
|
||||||
```
|
```
|
||||||
|
|
||||||
- `frame`:遊戲畫面更新的編號
|
- `frame`:遊戲畫面更新的編號
|
||||||
- `ball_x`:主角方塊的X座標,表示方塊的左邊座標值。
|
- `player_x`:主角方塊的X座標,表示方塊的`中心點`座標值,單位 pixel。
|
||||||
- `ball_y`:主角方塊的Y座標,表示方塊的上方座標值。
|
- `player_y`:主角方塊的Y座標,表示方塊的`中心點`座標值,單位 pixel。
|
||||||
|
- `player_size`:主角方塊的大小,表示方塊的長寬,單位 pixel。
|
||||||
|
- `player_vel`:主角方塊的速度,表示方塊每幀移動的像素,單位 pixel。
|
||||||
- `foods`:食物的清單,清單內每一個物件都是一個食物的左上方座標值,也會提供此食物是什麼類型和分數多少。
|
- `foods`:食物的清單,清單內每一個物件都是一個食物的左上方座標值,也會提供此食物是什麼類型和分數多少。
|
||||||
- `type` 食物類型: `GOOD_1`, `GOOD_2`, `GOOD_3`, `BAD_1`, `BAD_2`, `BAD_3`
|
- `type` 食物類型: `GOOD_1`, `GOOD_2`, `GOOD_3`, `BAD_1`, `BAD_2`, `BAD_3`
|
||||||
- `score`:目前得到的分數
|
- `score`:目前得到的分數
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -9,8 +9,10 @@
|
||||||
"SCENE_INFO": [
|
"SCENE_INFO": [
|
||||||
["scene_info['frame']", "# frame", "# 幀數"],
|
["scene_info['frame']", "# frame", "# 幀數"],
|
||||||
["scene_info['status']", "game status", "遊戲狀態"],
|
["scene_info['status']", "game status", "遊戲狀態"],
|
||||||
["scene_info['ball_x']", "x coordinate of ball", "球的 x 座標"],
|
["scene_info['player_x']", "x coordinate of player", "玩家角色的 x 座標"],
|
||||||
["scene_info['ball_y']", "y coordinate of ball", "球的 y 座標"],
|
["scene_info['player_y']", "y coordinate of player", "玩家角色的 y 座標"],
|
||||||
|
["scene_info['player_size']", "y coordinate of player", "玩家角色的大小"],
|
||||||
|
["scene_info['player_vel']", "velocity of player", "玩家角色的速度"],
|
||||||
["scene_info['score']", "score", "目前的分數"],
|
["scene_info['score']", "score", "目前的分數"],
|
||||||
["scene_info['foods']", "list of foods positions", "點點的位置清單"],
|
["scene_info['foods']", "list of foods positions", "點點的位置清單"],
|
||||||
["scene_info['score_to_pass']", "the score for next level", "通關分數"],
|
["scene_info['score_to_pass']", "the score for next level", "通關分數"],
|
||||||
|
@ -21,8 +23,7 @@
|
||||||
[800, "right boundary", "右邊界"],
|
[800, "right boundary", "右邊界"],
|
||||||
[0, "top boundary", "上邊界"],
|
[0, "top boundary", "上邊界"],
|
||||||
[600, "bottom boundary", "下邊界"],
|
[600, "bottom boundary", "下邊界"],
|
||||||
[30, "ball width", "球身的寬度"],
|
[30, "player size", "玩家角色的初始大小"],
|
||||||
[30, "ball height", "球身的高度"],
|
|
||||||
[8, "food lv1 size", "等級一食物的寬高度"],
|
[8, "food lv1 size", "等級一食物的寬高度"],
|
||||||
[12, "food lv2 size", "等級二食物的高度"],
|
[12, "food lv2 size", "等級二食物的高度"],
|
||||||
[16, "food lv3 size", "等級三食物的高度"]
|
[16, "food lv3 size", "等級三食物的高度"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"game_name": "easy_game",
|
"game_name": "easy_game",
|
||||||
"version": "2.3.1-alpha",
|
"version": "2.3.2-alpha",
|
||||||
"url": "https://github.com/PAIA-Playful-AI-Arena/easy_game",
|
"url": "https://github.com/PAIA-Playful-AI-Arena/easy_game",
|
||||||
"description": "這是一個吃東西小遊戲,除了讓你熟習所有基本操作,也是 PAIA 的遊戲教學範例",
|
"description": "這是一個吃東西小遊戲,除了讓你熟習所有基本操作,也是 PAIA 的遊戲教學範例",
|
||||||
"logo": [
|
"logo": [
|
||||||
|
@ -18,8 +18,8 @@
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"min": -1,
|
"min": -1,
|
||||||
"max": 100,
|
"max": 100,
|
||||||
"default": 1,
|
"default": -1,
|
||||||
"help": "選定內建關卡,預設為 1 選擇第一關。"
|
"help": "選定內建關卡,請注意,使用此設定將會覆蓋掉其他關卡設定,預設為 -1 不選擇任何關卡。"
|
||||||
}, {
|
}, {
|
||||||
"name": "level_file",
|
"name": "level_file",
|
||||||
"verbose": "匯入關卡檔案",
|
"verbose": "匯入關卡檔案",
|
||||||
|
|
|
@ -5,6 +5,6 @@
|
||||||
200
|
200
|
||||||
],
|
],
|
||||||
"score_to_pass": 10,
|
"score_to_pass": 10,
|
||||||
"green_food_count": [3,0,0],
|
"good_food_count": [3,0,0],
|
||||||
"black_food_count": [0,0,0]
|
"bad_food_count": [0,0,0]
|
||||||
}
|
}
|
|
@ -5,6 +5,6 @@
|
||||||
200
|
200
|
||||||
],
|
],
|
||||||
"score_to_pass": 15,
|
"score_to_pass": 15,
|
||||||
"green_food_count": [5,0,0],
|
"good_food_count": [5,0,0],
|
||||||
"black_food_count": [0,0,0]
|
"bad_food_count": [0,0,0]
|
||||||
}
|
}
|
|
@ -5,6 +5,6 @@
|
||||||
300
|
300
|
||||||
],
|
],
|
||||||
"score_to_pass": 15,
|
"score_to_pass": 15,
|
||||||
"green_food_count": [6,0,0],
|
"good_food_count": [6,0,0],
|
||||||
"black_food_count": [2,0,0]
|
"bad_food_count": [2,0,0]
|
||||||
}
|
}
|
|
@ -5,6 +5,6 @@
|
||||||
300
|
300
|
||||||
],
|
],
|
||||||
"score_to_pass": 15,
|
"score_to_pass": 15,
|
||||||
"green_food_count": [8,0,0],
|
"good_food_count": [8,0,0],
|
||||||
"black_food_count": [4,0,0]
|
"bad_food_count": [4,0,0]
|
||||||
}
|
}
|
|
@ -5,6 +5,6 @@
|
||||||
300
|
300
|
||||||
],
|
],
|
||||||
"score_to_pass": 15,
|
"score_to_pass": 15,
|
||||||
"green_food_count": [8,3,0],
|
"good_food_count": [8,3,0],
|
||||||
"black_food_count": [4,0,0]
|
"bad_food_count": [4,0,0]
|
||||||
}
|
}
|
|
@ -5,6 +5,6 @@
|
||||||
400
|
400
|
||||||
],
|
],
|
||||||
"score_to_pass": 15,
|
"score_to_pass": 15,
|
||||||
"green_food_count": [8,4,0],
|
"good_food_count": [8,4,0],
|
||||||
"black_food_count": [5,2,0]
|
"bad_food_count": [5,2,0]
|
||||||
}
|
}
|
|
@ -5,6 +5,6 @@
|
||||||
400
|
400
|
||||||
],
|
],
|
||||||
"score_to_pass": 20,
|
"score_to_pass": 20,
|
||||||
"green_food_count": [8,4,2],
|
"good_food_count": [8,4,2],
|
||||||
"black_food_count": [4,4,0]
|
"bad_food_count": [4,4,0]
|
||||||
}
|
}
|
|
@ -5,6 +5,6 @@
|
||||||
500
|
500
|
||||||
],
|
],
|
||||||
"score_to_pass": 20,
|
"score_to_pass": 20,
|
||||||
"green_food_count": [6,4,2],
|
"good_food_count": [6,4,2],
|
||||||
"black_food_count": [6,4,2]
|
"bad_food_count": [6,4,2]
|
||||||
}
|
}
|
|
@ -5,6 +5,6 @@
|
||||||
500
|
500
|
||||||
],
|
],
|
||||||
"score_to_pass": 25,
|
"score_to_pass": 25,
|
||||||
"green_food_count": [10,5,3],
|
"good_food_count": [10,5,3],
|
||||||
"black_food_count": [12,7,4]
|
"bad_food_count": [12,7,4]
|
||||||
}
|
}
|
|
@ -5,6 +5,6 @@
|
||||||
600
|
600
|
||||||
],
|
],
|
||||||
"score_to_pass": 25,
|
"score_to_pass": 25,
|
||||||
"green_food_count": [12,8,4],
|
"good_food_count": [12,8,4],
|
||||||
"black_food_count": [25,10,5]
|
"bad_food_count": [25,10,5]
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
200
|
200
|
||||||
],
|
],
|
||||||
"score_to_pass": 10,
|
"score_to_pass": 10,
|
||||||
"green_food_count": [3,0,0],
|
"good_food_count": [3,0,0],
|
||||||
"black_food_count": [0,0,0]
|
"bad_food_count": [0,0,0]
|
||||||
|
|
||||||
}
|
}
|
2
main.py
2
main.py
|
@ -9,7 +9,7 @@ from src.game import EasyGame
|
||||||
FPS = 30
|
FPS = 30
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
pygame.init()
|
pygame.init()
|
||||||
game = EasyGame(time_to_play=1000, total_point_count=10, score=5, color="FF9800")
|
game = EasyGame(level=1)
|
||||||
scene_init_info_dict = game.get_scene_init_data()
|
scene_init_info_dict = game.get_scene_init_data()
|
||||||
game_view = PygameView(scene_init_info_dict)
|
game_view = PygameView(scene_init_info_dict)
|
||||||
frame_count = 0
|
frame_count = 0
|
||||||
|
|
10
src/env.py
10
src/env.py
|
@ -10,10 +10,16 @@ PG_COLOR = "#B3E5FC"
|
||||||
|
|
||||||
# ball
|
# ball
|
||||||
BALL_COLOR = "#FFEB3B"
|
BALL_COLOR = "#FFEB3B"
|
||||||
BALL_VEL = 10.5
|
BALL_VEL = 10
|
||||||
BALL_H = 30
|
BALL_H = 30
|
||||||
BALL_W = 30
|
BALL_W = 30
|
||||||
|
BALL_GROWTH_SCORE_STEP = 15
|
||||||
|
BALL_GROWTH_SIZE_STEP=10
|
||||||
|
BALL_GROWTH_VEL_STEP=3
|
||||||
|
BALL_SIZE_MAX = 100
|
||||||
|
BALL_SIZE_MIN = 10
|
||||||
|
BALL_VEL_MAX = 25
|
||||||
|
BALL_VEL_MIN = 10
|
||||||
|
|
||||||
# food
|
# food
|
||||||
class FoodTypeEnum(StringEnum):
|
class FoodTypeEnum(StringEnum):
|
||||||
|
|
84
src/game.py
84
src/game.py
|
@ -36,12 +36,11 @@ class EasyGame(PaiaGame):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
level: int = 1,
|
level: int = -1,
|
||||||
level_file: str = None,
|
level_file: str = "",
|
||||||
sound: str = "off",
|
sound: str = "off",
|
||||||
*args, **kwargs):
|
*args, **kwargs):
|
||||||
super().__init__(user_num=1)
|
super().__init__(user_num=1)
|
||||||
# TODO reduce game config and use level file
|
|
||||||
self.game_result_state = GameResultState.FAIL
|
self.game_result_state = GameResultState.FAIL
|
||||||
self.scene = Scene(width=WIDTH, height=HEIGHT, color=BG_COLOR, bias_x=0, bias_y=0)
|
self.scene = Scene(width=WIDTH, height=HEIGHT, color=BG_COLOR, bias_x=0, bias_y=0)
|
||||||
self._level = level
|
self._level = level
|
||||||
|
@ -49,17 +48,8 @@ class EasyGame(PaiaGame):
|
||||||
self.foods = pygame.sprite.Group()
|
self.foods = pygame.sprite.Group()
|
||||||
self.sound_controller = SoundController(sound)
|
self.sound_controller = SoundController(sound)
|
||||||
|
|
||||||
if path.isfile(self._level_file) or self._level_file == "":
|
self._init_game()
|
||||||
# set by injected file
|
|
||||||
self._init_game_by_file(self._level_file)
|
|
||||||
pass
|
|
||||||
|
|
||||||
else:
|
|
||||||
self._init_game_by_level(self._level)
|
|
||||||
|
|
||||||
def _init_game_by_level(self, level: int):
|
|
||||||
level_file_path = os.path.join(LEVEL_PATH, f"{level:03d}.json")
|
|
||||||
self._init_game_by_file(level_file_path)
|
|
||||||
|
|
||||||
def _init_game_by_file(self, level_file_path: str):
|
def _init_game_by_file(self, level_file_path: str):
|
||||||
try:
|
try:
|
||||||
|
@ -82,8 +72,8 @@ class EasyGame(PaiaGame):
|
||||||
self._playground_w,
|
self._playground_w,
|
||||||
self._playground_h
|
self._playground_h
|
||||||
)
|
)
|
||||||
self._green_food_count = game_params["green_food_count"]
|
self._good_food_count = game_params["good_food_count"]
|
||||||
self._red_food_count = game_params["black_food_count"]
|
self._bad_food_count = game_params["bad_food_count"]
|
||||||
self._score_to_pass = int(game_params["score_to_pass"])
|
self._score_to_pass = int(game_params["score_to_pass"])
|
||||||
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)
|
||||||
|
@ -91,15 +81,19 @@ class EasyGame(PaiaGame):
|
||||||
# init game
|
# init game
|
||||||
self.ball = Ball()
|
self.ball = Ball()
|
||||||
self.foods.empty()
|
self.foods.empty()
|
||||||
self.score = 0
|
|
||||||
|
|
||||||
# todo validate food count
|
if not isinstance(self._good_food_count,list) or len(self._good_food_count)<3:
|
||||||
self._create_foods(GoodFoodLv1, self._green_food_count[0])
|
raise Exception("你的關卡檔案格式有誤,請在'good_food_count' 欄位後面填入一個長度為3的陣列,舉例: [1,2,3]")
|
||||||
self._create_foods(GoodFoodLv2, self._green_food_count[1])
|
elif not isinstance(self._bad_food_count, list) or len(self._bad_food_count) < 3:
|
||||||
self._create_foods(GoodFoodLv3, self._green_food_count[2])
|
raise Exception("你的關卡檔案格式有誤,請在'bad_food_count' 欄位後面填入一個長度為3的陣列,舉例: [1,2,3]")
|
||||||
self._create_foods(BadFoodLv1, self._red_food_count[0])
|
|
||||||
self._create_foods(BadFoodLv2, self._red_food_count[1])
|
else:
|
||||||
self._create_foods(BadFoodLv3, self._red_food_count[2])
|
self._create_foods(GoodFoodLv1, self._good_food_count[0])
|
||||||
|
self._create_foods(GoodFoodLv2, self._good_food_count[1])
|
||||||
|
self._create_foods(GoodFoodLv3, self._good_food_count[2])
|
||||||
|
self._create_foods(BadFoodLv1, self._bad_food_count[0])
|
||||||
|
self._create_foods(BadFoodLv2, self._bad_food_count[1])
|
||||||
|
self._create_foods(BadFoodLv3, self._bad_food_count[2])
|
||||||
|
|
||||||
self.frame_count = 0
|
self.frame_count = 0
|
||||||
self._frame_count_down = self._frame_limit
|
self._frame_count_down = self._frame_limit
|
||||||
|
@ -136,7 +130,9 @@ class EasyGame(PaiaGame):
|
||||||
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:
|
||||||
self.score += food.score
|
# self.ball.score += food.score
|
||||||
|
# growth play special sound
|
||||||
|
self.ball.eat_food_and_change_level_and_play_sound(food,self.sound_controller)
|
||||||
self._create_foods(food.__class__, 1)
|
self._create_foods(food.__class__, 1)
|
||||||
if isinstance(food, (GoodFoodLv1,GoodFoodLv2,GoodFoodLv3,)):
|
if isinstance(food, (GoodFoodLv1,GoodFoodLv2,GoodFoodLv3,)):
|
||||||
self.sound_controller.play_eating_good()
|
self.sound_controller.play_eating_good()
|
||||||
|
@ -151,17 +147,22 @@ class EasyGame(PaiaGame):
|
||||||
to_players_data = {}
|
to_players_data = {}
|
||||||
foods_data = []
|
foods_data = []
|
||||||
for food in self.foods:
|
for food in self.foods:
|
||||||
# TODO add good food and bad food
|
# TODO 確認要提供中心點座標還是左上角座標。
|
||||||
|
|
||||||
foods_data.append({"x": food.rect.x, "y": food.rect.y, "type": food.type, "score": food.score})
|
foods_data.append({"x": food.rect.x, "y": food.rect.y, "type": food.type, "score": food.score})
|
||||||
|
|
||||||
data_to_1p = {
|
data_to_1p = {
|
||||||
"frame": self.frame_count,
|
"frame": self.frame_count,
|
||||||
"ball_x": self.ball.rect.centerx,
|
# TODO 確認要提供中心點座標還是左上角座標。
|
||||||
"ball_y": self.ball.rect.centery,
|
"player_x": self.ball.rect.centerx,
|
||||||
|
"player_y": self.ball.rect.centery,
|
||||||
|
"player_size":self.ball.rect.width,
|
||||||
|
"player_vel":self.ball.vel,
|
||||||
"foods": foods_data,
|
"foods": foods_data,
|
||||||
"score": self.score,
|
|
||||||
|
"score": self.ball.score,
|
||||||
"score_to_pass":self._score_to_pass,
|
"score_to_pass":self._score_to_pass,
|
||||||
"status": self.get_game_status()
|
"status": self.get_game_status()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
to_players_data[get_ai_name(0)] = data_to_1p
|
to_players_data[get_ai_name(0)] = data_to_1p
|
||||||
|
@ -182,22 +183,27 @@ class EasyGame(PaiaGame):
|
||||||
def reset(self):
|
def reset(self):
|
||||||
|
|
||||||
if self.is_passed:
|
if self.is_passed:
|
||||||
self.sound_controller.play_cheer()
|
|
||||||
|
|
||||||
if self._level_file:
|
|
||||||
pass
|
|
||||||
elif self.is_passed and self._level != -1:
|
|
||||||
# win and use level will enter next level
|
|
||||||
self._level += 1
|
self._level += 1
|
||||||
self._init_game_by_level(self._level)
|
self.sound_controller.play_cheer()
|
||||||
|
|
||||||
self._init_game()
|
self._init_game()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def _init_game(self):
|
||||||
|
if path.isfile(self._level_file):
|
||||||
|
# set by injected file
|
||||||
|
self._init_game_by_file(self._level_file)
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
level_file_path = os.path.join(LEVEL_PATH, f"{self._level:03d}.json")
|
||||||
|
self._init_game_by_file(level_file_path)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_passed(self):
|
def is_passed(self):
|
||||||
return self.score > self._score_to_pass
|
return self.ball.score > self._score_to_pass
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_running(self):
|
def is_running(self):
|
||||||
|
@ -239,7 +245,7 @@ class EasyGame(PaiaGame):
|
||||||
|
|
||||||
]
|
]
|
||||||
toggle_objs = [
|
toggle_objs = [
|
||||||
create_text_view_data(f"Score:{self.score:04d}", 600, 50, "#A5D6A7", "24px Arial BOLD"),
|
create_text_view_data(f"Score:{self.ball.score:04d}", 600, 50, "#A5D6A7", "24px Arial BOLD"),
|
||||||
create_text_view_data(f" Next:{self._score_to_pass:04d}", 600, 100, "#FF4081", "24px Arial BOLD"),
|
create_text_view_data(f" Next:{self._score_to_pass:04d}", 600, 100, "#FF4081", "24px Arial BOLD"),
|
||||||
create_text_view_data(f" Time:{self._frame_count_down:04d}", 600, 150, "#FF5722", "24px Arial BOLD"),
|
create_text_view_data(f" Time:{self._frame_count_down:04d}", 600, 150, "#FF5722", "24px Arial BOLD"),
|
||||||
|
|
||||||
|
@ -262,7 +268,7 @@ class EasyGame(PaiaGame):
|
||||||
{
|
{
|
||||||
"player": get_ai_name(0),
|
"player": get_ai_name(0),
|
||||||
"rank": 1,
|
"rank": 1,
|
||||||
"score": self.score,
|
"score": self.ball.score,
|
||||||
"passed": self.is_passed
|
"passed": self.is_passed
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
|
import math
|
||||||
|
|
||||||
import pygame.sprite
|
import pygame.sprite
|
||||||
|
|
||||||
from games.easy_game.src.env import BALL_COLOR, BALL_VEL, BALL_H, BALL_W
|
from games.easy_game.src.env import BALL_COLOR, BALL_VEL, BALL_H, BALL_W, BALL_GROWTH_SCORE_STEP, BALL_GROWTH_SIZE_STEP, \
|
||||||
|
BALL_SIZE_MAX, BALL_GROWTH_VEL_STEP, BALL_VEL_MAX, BALL_SIZE_MIN, BALL_VEL_MIN
|
||||||
from games.easy_game.src.foods import Food
|
from games.easy_game.src.foods import Food
|
||||||
|
from games.easy_game.src.sound_controller import SoundController
|
||||||
from mlgame.view.view_model import create_rect_view_data
|
from mlgame.view.view_model import create_rect_view_data
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,20 +17,23 @@ class Ball(pygame.sprite.Sprite):
|
||||||
self.color = BALL_COLOR
|
self.color = BALL_COLOR
|
||||||
self.rect = self.image.get_rect()
|
self.rect = self.image.get_rect()
|
||||||
self.rect.center = (400, 300)
|
self.rect.center = (400, 300)
|
||||||
|
self._score = 0
|
||||||
|
self._vel = BALL_VEL
|
||||||
|
self._lv =1
|
||||||
|
|
||||||
def update(self, motion):
|
def update(self, motion):
|
||||||
# for motion in motions:
|
# for motion in motions:
|
||||||
if motion == "UP":
|
if motion == "UP":
|
||||||
self.rect.centery -= BALL_VEL
|
self.rect.centery -= self._vel
|
||||||
elif motion == "DOWN":
|
elif motion == "DOWN":
|
||||||
self.rect.centery += BALL_VEL
|
self.rect.centery += self._vel
|
||||||
elif motion == "LEFT":
|
elif motion == "LEFT":
|
||||||
self.rect.centerx -= BALL_VEL
|
self.rect.centerx -= self._vel
|
||||||
# self.angle += 5
|
# self.angle += 5
|
||||||
elif motion == "RIGHT":
|
elif motion == "RIGHT":
|
||||||
self.rect.centerx += BALL_VEL
|
self.rect.centerx += self._vel
|
||||||
# self.angle -= 5
|
# self.angle -= 5
|
||||||
|
|
||||||
# self.image = pygame.transform.rotate(self.origin_image, self.angle)
|
# self.image = pygame.transform.rotate(self.origin_image, self.angle)
|
||||||
# print(self.angle)
|
# print(self.angle)
|
||||||
# center = self.rect.center
|
# center = self.rect.center
|
||||||
|
@ -44,4 +51,22 @@ class Ball(pygame.sprite.Sprite):
|
||||||
self.color
|
self.color
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def eat_food_and_change_level_and_play_sound(self, food: Food,sound_controller:SoundController):
|
||||||
|
self._score += food.score
|
||||||
|
new_lv = math.ceil((self._score-BALL_GROWTH_SCORE_STEP + 1) / BALL_GROWTH_SCORE_STEP)
|
||||||
|
self.rect.width = max(BALL_SIZE_MIN,min(BALL_W + new_lv * BALL_GROWTH_SIZE_STEP, BALL_SIZE_MAX))
|
||||||
|
self.rect.height = max(BALL_SIZE_MIN,min(BALL_H + new_lv * BALL_GROWTH_SIZE_STEP, BALL_SIZE_MAX))
|
||||||
|
self._vel = max(BALL_VEL_MIN,min(BALL_VEL + new_lv * BALL_GROWTH_VEL_STEP, BALL_VEL_MAX))
|
||||||
|
if new_lv > self._lv:
|
||||||
|
sound_controller.play_lv_up()
|
||||||
|
elif new_lv < self._lv:
|
||||||
|
sound_controller.play_lv_down()
|
||||||
|
self._lv=new_lv
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def score(self):
|
||||||
|
return self._score
|
||||||
|
@property
|
||||||
|
def vel(self):
|
||||||
|
return self._vel
|
|
@ -25,6 +25,8 @@ class SoundController():
|
||||||
self._eating_good = pygame.mixer.Sound(path.join(SOUND_PATH, "Coin.wav"))
|
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"))
|
self._eating_bad = pygame.mixer.Sound(path.join(SOUND_PATH, "Low Boing.wav"))
|
||||||
self._cheer = pygame.mixer.Sound(path.join(SOUND_PATH, "Cheer.wav"))
|
self._cheer = pygame.mixer.Sound(path.join(SOUND_PATH, "Cheer.wav"))
|
||||||
|
self._lv_up = pygame.mixer.Sound(path.join(SOUND_PATH, "lv_up.wav"))
|
||||||
|
self._lv_down = pygame.mixer.Sound(path.join(SOUND_PATH, "lv_down.wav"))
|
||||||
except Exception:
|
except Exception:
|
||||||
self._is_sound_on = False
|
self._is_sound_on = False
|
||||||
|
|
||||||
|
@ -42,3 +44,11 @@ class SoundController():
|
||||||
@sound_enabled
|
@sound_enabled
|
||||||
def play_cheer(self):
|
def play_cheer(self):
|
||||||
self._cheer.play()
|
self._cheer.play()
|
||||||
|
|
||||||
|
@sound_enabled
|
||||||
|
def play_lv_up(self):
|
||||||
|
self._lv_up.play()
|
||||||
|
|
||||||
|
@sound_enabled
|
||||||
|
def play_lv_down(self):
|
||||||
|
self._lv_down.play()
|
Loading…
Reference in New Issue