diff --git a/levels/001.json b/levels/001.json index 42701af..a3dfcd9 100644 --- a/levels/001.json +++ b/levels/001.json @@ -1,10 +1,10 @@ { "time_to_play": 300, - "playground_size": [ - 100, - 200 - ], + "playground_size_w":100, + "playground_size_h":200, "score_to_pass": 10, - "good_food_count": [3,0,0], - "bad_food_count": [0,0,0] + "good_food_count": [0,0,0], + "bad_food_count": [0,0,0], + "fish": 3 + } \ No newline at end of file diff --git a/levels/template.json b/levels/template.json index 3a25bec..40324ee 100644 --- a/levels/template.json +++ b/levels/template.json @@ -1,11 +1,10 @@ { "time_to_play": 300, - "playground_size": [ - 100, - 200 - ], + "playground_w":100, + "playground_h":200, "score_to_pass": 10, "good_food_count": [3,0,0], - "bad_food_count": [0,0,0] + "bad_food_count": [0,0,0], + "fish": 0 } \ No newline at end of file diff --git a/src/foods.py b/src/foods.py index 3d8ea19..7fae64f 100644 --- a/src/foods.py +++ b/src/foods.py @@ -1,4 +1,8 @@ +import math +import random + import pygame.sprite +from pygame import Rect from .env import FoodTypeEnum, FOOD_COLOR_MAP, FOOD_LV1_SIZE, FOOD_LV2_SIZE, FOOD_LV3_SIZE from mlgame.view.view_model import create_rect_view_data @@ -14,8 +18,10 @@ class Food(pygame.sprite.Sprite): self.rect = self.image.get_rect() self.angle = 0 - - def update(self) -> None: + def set_center_x_and_y(self,x:int,y:int): + self.rect.centerx = x + self.rect.centery = y + def update(self,*args,**kwargs) -> None: pass @property @@ -38,6 +44,7 @@ class GoodFoodLv1(Food): self.color = FOOD_COLOR_MAP[self.type] self.score = 1 self.rect = self.image.get_rect() + class GoodFoodLv2(Food): def __init__(self, group): super().__init__(group) @@ -57,7 +64,48 @@ class GoodFoodLv3(Food): self.color = FOOD_COLOR_MAP[self.type] self.score = 4 self.rect = self.image.get_rect() +class Fish(Food): + def __init__(self, group): + super().__init__(group) + self.image = pygame.Surface([FOOD_LV1_SIZE, FOOD_LV1_SIZE]) + self.type = FoodTypeEnum.GOOD_1 + self.color = FOOD_COLOR_MAP[self.type] + self.score = 1 + self.rect = self.image.get_rect() + self._target_x=400 + self._target_y=400 + self._direction = 1 + self._vel=2 + self._vely=1 + def update(self,playground:Rect): + + + if self._direction==1: + if self.rect.centerx > self._target_x: + # change + self._direction= - self._direction + self._target_x = random.randint(playground.left, playground.right) + self._target_y = self.rect.centery + random.randint(-20,20) + self._vely = self._vel * ((self._target_y - self.rect.centery)/(self._target_x - self.rect.centerx) ) + + pass + # move to right + self.rect.centerx += self._vel + self.rect.centery = self.rect.centery +self._vely + elif self._direction==-1: + if self.rect.centerx < self._target_x: + # change + self._direction= - self._direction + self._target_x = random.randint(playground.left, playground.right) + self._target_y = self.rect.centery + random.randint(-50,50) + self.rect.centery = self.rect.centery + self._vely + + pass + self.rect.centerx -= self._vel + self.rect.centery -= math.sin(self.rect.centerx) + pass + pass diff --git a/src/game.py b/src/game.py index 91561a8..2646639 100644 --- a/src/game.py +++ b/src/game.py @@ -3,14 +3,16 @@ import json import os.path import pygame +from orjson import orjson from mlgame.game.paia_game import PaiaGame, GameResultState, GameStatus from mlgame.utils.enum import get_ai_name +from mlgame.utils.prof import timeit_in_perf from mlgame.view.decorator import check_game_progress, check_game_result from mlgame.view.view_model import * from .env import * from .foods import * -from .game_object import Ball +from .game_object import Ball, LevelParams from .sound_controller import SoundController @@ -51,10 +53,12 @@ class EasyGame(PaiaGame): self._init_game() + @timeit_in_perf def _init_game_by_file(self, level_file_path: str): try: with open(level_file_path) as f: - game_params = json.load(f) + game_params = LevelParams(**json.load(f)) + except: # If the file doesn't exist, use default parameters print("此關卡檔案不存在,遊戲將會會自動使用第一關檔案 001.json。") @@ -65,17 +69,15 @@ class EasyGame(PaiaGame): self._level_file = "" finally: # set game params - self._playground_w = int(game_params["playground_size"][0]) - self._playground_h = int(game_params["playground_size"][1]) self.playground = pygame.Rect( 0, 0, - self._playground_w, - self._playground_h + game_params.playground_w, + game_params.playground_h ) - self._good_food_count = game_params["good_food_count"] - self._bad_food_count = game_params["bad_food_count"] - self._score_to_pass = int(game_params["score_to_pass"]) - self._frame_limit = int(game_params["time_to_play"]) + self._good_food_count = game_params.good_food_count + self._bad_food_count = game_params.bad_food_count + self._score_to_pass = game_params.score_to_pass + self._frame_limit = game_params.time_to_play self.playground.center = (WIDTH / 2, HEIGHT / 2) # init game @@ -94,6 +96,7 @@ class EasyGame(PaiaGame): 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._create_foods(Fish, game_params.fish) self.frame_count = 0 self._frame_count_down = self._frame_limit @@ -112,7 +115,7 @@ class EasyGame(PaiaGame): self.ball.update(action) revise_ball(self.ball, self.playground) # update sprite - self.foods.update() + self.foods.update(playground=self.playground) # handle collision @@ -298,6 +301,9 @@ class EasyGame(PaiaGame): for i in range(count): # add food to group food = FOOD_TYPE(self.foods) - food.rect.centerx = random.randint(self.playground.left, self.playground.right) - food.rect.centery = random.randint(self.playground.top, self.playground.bottom) + food.set_center_x_and_y( + random.randint(self.playground.left, self.playground.right), + random.randint(self.playground.top, self.playground.bottom) + ) + pass diff --git a/src/game_object.py b/src/game_object.py index 22e2be3..31cb37b 100644 --- a/src/game_object.py +++ b/src/game_object.py @@ -1,5 +1,7 @@ import math +from typing import List +import pydantic import pygame.sprite from .env import BALL_COLOR, BALL_VEL, BALL_H, BALL_W, BALL_GROWTH_SCORE_STEP, BALL_GROWTH_SIZE_STEP, \ @@ -8,6 +10,15 @@ from .foods import Food from .sound_controller import SoundController from mlgame.view.view_model import create_rect_view_data +class LevelParams(pydantic.BaseModel): + playground_w:int=100 + playground_h:int=200 + score_to_pass:int=10 + time_to_play:int=300 + + good_food_count:List[int] =[] + bad_food_count:List[int] =[] + fish:int=0 class Ball(pygame.sprite.Sprite): def __init__(self):