diff --git a/README.md b/README.md index 8f962db..1635685 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ![easy_game](https://img.shields.io/github/v/tag/PAIA-Playful-AI-Arena/easy_game) [![Python 3.9](https://img.shields.io/badge/python-3.9-blue.svg)](https://www.python.org/downloads/release/python-390/) -[![MLGame](https://img.shields.io/badge/MLGame->9.5.3-.svg)](https://github.com/PAIA-Playful-AI-Arena/MLGame) +[![MLGame](https://img.shields.io/badge/MLGame->10.3.2-.svg)](https://github.com/PAIA-Playful-AI-Arena/MLGame) [![pygame](https://img.shields.io/badge/pygame-2.0.1-.svg)](https://github.com/pygame/pygame/releases/tag/2.0.1) @@ -22,20 +22,11 @@ ```python # main.py game = EasyGame( - time_to_play, score_to_pass, - green_food_count, red_food_count, - playground_size: list, - level: int = -1, + level: int = 1, level_file: str = None, sound: str = "off") ``` - -- `time_to_play`:遊戲執行的終止時間,單位是 frame,也就是遊戲內部更新畫面的次數,每更新一次 frame +1 -- `green_food_count`:遊戲中綠色食物的數量。 -- `red_food_count`:遊戲中紅色食物的數量。 -- `score_to_pass`:遊戲通關的點數,要超過這個分數才算過關。 -- `playground_size`:可移動區域的大小。 使用逗號將數字隔開 `width,height` `100,200` -- `level`: 選定內建關卡,請注意,使用此設定將會覆蓋掉上述其他關卡參數設定,預設為 -1 不選擇任何關卡。 +- `level`: 選定內建關卡,預設為 1 選擇第一關。 - `level_file`: 使用外部檔案作為關卡,請注意,使用此設定將會覆蓋掉關卡編號,並且不會自動進入下一關。 - `sound`: 音效。 @@ -83,10 +74,10 @@ python -m mlgame -i ./ml/ml_play_template.py ./ --time_to_play 1200 --green_food import random class MLPlay: - def __init__(self): + def __init__(self,ai_name,*args, **kwargs): print("Initial ml script") - def update(self, scene_info: dict): + def update(self, scene_info: dict,,*args, **kwargs): # print("AI received data from game :", scene_info) @@ -114,12 +105,16 @@ class MLPlay: "foods": [ { "x": 656, - "y": 210 + "y": 210, + "type": "GOOD_1", + "score": 1 }, ..., { "x": 371, - "y": 217 + "y": 217, + "type": "BAD_1", + "score": -1 } ], @@ -131,8 +126,10 @@ class MLPlay: - `frame`:遊戲畫面更新的編號 - `ball_x`:主角方塊的X座標,表示方塊的左邊座標值。 - `ball_y`:主角方塊的Y座標,表示方塊的上方座標值。 -- `foods`:食物的清單,清單內每一個物件都是一個食物的左上方座標值 +- `foods`:食物的清單,清單內每一個物件都是一個食物的左上方座標值,也會提供此食物是什麼類型和分數多少。 + - `type` 食物類型: `GOOD_1`, `GOOD_2`, `GOOD_3`, `BAD_1`, `BAD_2`, `BAD_3` - `score`:目前得到的分數 +- `score_to_pass`:通關分數 - `status`: 目前遊戲的狀態 - `GAME_ALIVE`:遊戲進行中 - `GAME_PASS`:遊戲通關 diff --git a/blockly.json b/blockly.json index 922740c..0435f5a 100644 --- a/blockly.json +++ b/blockly.json @@ -11,8 +11,9 @@ ["scene_info['status']", "game status", "遊戲狀態"], ["scene_info['ball_x']", "x coordinate of ball", "球的 x 座標"], ["scene_info['ball_y']", "y coordinate of ball", "球的 y 座標"], - ["scene_info['score']", "x coordinate of platform", "平台的 x 座標"], + ["scene_info['score']", "score", "目前的分數"], ["scene_info['foods']", "list of foods positions", "點點的位置清單"], + ["scene_info['score_to_pass']", "the score for next level", "通關分數"], ["scene_info", "dictionary of all information", "包含所有資訊的字典"] ], "CONSTANT": [ @@ -22,8 +23,9 @@ [600, "bottom boundary", "下邊界"], [30, "ball width", "球身的寬度"], [30, "ball height", "球身的高度"], - [8, "food width", "食物的寬度"], - [8, "food height", "食物的高度"] + [8, "food lv1 size", "等級一食物的寬高度"], + [12, "food lv2 size", "等級二食物的高度"], + [16, "food lv3 size", "等級三食物的高度"] ], "ACTION": [ ["['UP']", "moving up", "向上移動"], diff --git a/game_config.json b/game_config.json index 3bcc2d2..6ed2edf 100644 --- a/game_config.json +++ b/game_config.json @@ -1,6 +1,6 @@ { "game_name": "easy_game", - "version": "2.2.1-beta", + "version": "2.3.1-alpha", "url": "https://github.com/PAIA-Playful-AI-Arena/easy_game", "description": "這是一個吃東西小遊戲,除了讓你熟習所有基本操作,也是 PAIA 的遊戲教學範例", "logo": [ @@ -12,77 +12,14 @@ "max": 1 }, "game_params": [ - { - "name": "time_to_play", - "verbose": "遊戲總幀數", - "type": "int", - "max": 2000, - "min": 600, - "default": 600, - "help": "set the limit of frame count , actually time will be revised according to your FPS ." - }, - { - "name": "green_food_count", - "verbose": "綠色食物數量", - "type": "int", - "choices": [ - 5, - 10, - 15, - 20, - 25, - 30, - 35, - 40, - 45, - 50 - ], - "help": "set the total number of points", - "default": 10 - }, - { - "name": "red_food_count", - "verbose": "紅色食物數量", - "type": "int", - "choices": [ - 5, - 10, - 15, - 20, - 25, - 30, - 35, - 40, - 45, - 50 - ], - "help": "set the total number of points", - "default": 10 - }, - { - "name": "score_to_pass", - "verbose": "通關分數", - "type": "int", - "min": 1, - "max": 30, - "default": 10, - "help": "set the score to win this game " - }, - { - "name": "playground_size", - "verbose": "場地尺寸", - "type": "list", - "default": "400,400", - "help": "set the size of playground " - }, { "name": "level", "verbose": "內建關卡編號", "type": "int", "min": -1, - "max": 5, - "default": "-1", - "help": "選定內建關卡,請注意,使用此設定將會覆蓋掉其他關卡設定,預設為 -1 不選擇任何關卡。" + "max": 100, + "default": 1, + "help": "選定內建關卡,預設為 1 選擇第一關。" }, { "name": "level_file", "verbose": "匯入關卡檔案", diff --git a/levels/001.json b/levels/001.json index a948b2c..2a5c36c 100644 --- a/levels/001.json +++ b/levels/001.json @@ -5,6 +5,6 @@ 200 ], "score_to_pass": 10, - "green_food_count": 3, - "black_food_count": 0 + "green_food_count": [3,0,0], + "black_food_count": [0,0,0] } \ No newline at end of file diff --git a/levels/002.json b/levels/002.json index bb34c84..1d7ad96 100644 --- a/levels/002.json +++ b/levels/002.json @@ -5,6 +5,6 @@ 200 ], "score_to_pass": 15, - "green_food_count": 5, - "black_food_count": 0 + "green_food_count": [5,0,0], + "black_food_count": [0,0,0] } \ No newline at end of file diff --git a/levels/003.json b/levels/003.json index af6dd30..1e7af2e 100644 --- a/levels/003.json +++ b/levels/003.json @@ -5,6 +5,6 @@ 300 ], "score_to_pass": 15, - "green_food_count": 10, - "black_food_count": 0 + "green_food_count": [6,0,0], + "black_food_count": [2,0,0] } \ No newline at end of file diff --git a/levels/004.json b/levels/004.json index 34d2278..61f4ddd 100644 --- a/levels/004.json +++ b/levels/004.json @@ -5,6 +5,6 @@ 300 ], "score_to_pass": 15, - "green_food_count": 7, - "black_food_count": 3 + "green_food_count": [8,0,0], + "black_food_count": [4,0,0] } \ No newline at end of file diff --git a/levels/005.json b/levels/005.json index cee2f71..09e99fc 100644 --- a/levels/005.json +++ b/levels/005.json @@ -5,6 +5,6 @@ 300 ], "score_to_pass": 15, - "green_food_count": 7, - "black_food_count": 7 + "green_food_count": [8,3,0], + "black_food_count": [4,0,0] } \ No newline at end of file diff --git a/levels/006.json b/levels/006.json index ef06d11..bac42f3 100644 --- a/levels/006.json +++ b/levels/006.json @@ -5,6 +5,6 @@ 400 ], "score_to_pass": 15, - "green_food_count": 7, - "black_food_count": 10 + "green_food_count": [8,4,0], + "black_food_count": [5,2,0] } \ No newline at end of file diff --git a/levels/007.json b/levels/007.json index 49c8e26..84ee5bf 100644 --- a/levels/007.json +++ b/levels/007.json @@ -5,6 +5,6 @@ 400 ], "score_to_pass": 20, - "green_food_count": 7, - "black_food_count": 13 + "green_food_count": [8,4,2], + "black_food_count": [4,4,0] } \ No newline at end of file diff --git a/levels/008.json b/levels/008.json index 61a8a29..c94adc3 100644 --- a/levels/008.json +++ b/levels/008.json @@ -5,6 +5,6 @@ 500 ], "score_to_pass": 20, - "green_food_count": 10, - "black_food_count": 15 + "green_food_count": [6,4,2], + "black_food_count": [6,4,2] } \ No newline at end of file diff --git a/levels/009.json b/levels/009.json index bda3f34..9ee974f 100644 --- a/levels/009.json +++ b/levels/009.json @@ -5,6 +5,6 @@ 500 ], "score_to_pass": 25, - "green_food_count": 15, - "black_food_count": 30 + "green_food_count": [10,5,3], + "black_food_count": [12,7,4] } \ No newline at end of file diff --git a/levels/010.json b/levels/010.json index 845f344..d7450e3 100644 --- a/levels/010.json +++ b/levels/010.json @@ -5,6 +5,6 @@ 600 ], "score_to_pass": 25, - "green_food_count": 20, - "black_food_count": 40 + "green_food_count": [12,8,4], + "black_food_count": [25,10,5] } \ No newline at end of file diff --git a/levels/template.json b/levels/template.json index 3d76644..3b9a69a 100644 --- a/levels/template.json +++ b/levels/template.json @@ -1,7 +1,11 @@ { - "time_to_play": 1200, + "time_to_play": 300, "playground_size": [ - 500, + 100, 200 - ] + ], + "score_to_pass": 10, + "green_food_count": [3,0,0], + "black_food_count": [0,0,0] + } \ No newline at end of file diff --git a/src/env.py b/src/env.py index 82de125..82274ce 100644 --- a/src/env.py +++ b/src/env.py @@ -17,10 +17,24 @@ BALL_W = 30 # food class FoodTypeEnum(StringEnum): - GREEN = auto() - RED = auto() -FOOD_COLOR_MAP = {FoodTypeEnum.GREEN: "#009688", - FoodTypeEnum.RED: "#FF1744"} + GOOD_1 = auto() + GOOD_2 = auto() + GOOD_3 = auto() + BAD_1 = auto() + BAD_2 = auto() + BAD_3 = auto() + +FOOD_COLOR_MAP = { + FoodTypeEnum.GOOD_1: "#009688", + FoodTypeEnum.GOOD_2: "#009688", + FoodTypeEnum.GOOD_3: "#009688", + FoodTypeEnum.BAD_1: "#FF1744", + FoodTypeEnum.BAD_2: "#FF1744", + FoodTypeEnum.BAD_3: "#FF1744" +} +FOOD_LV1_SIZE = 8 +FOOD_LV2_SIZE = 12 +FOOD_LV3_SIZE = 16 # path of assets ASSET_PATH = path.join(path.dirname(__file__), "..", "asset") diff --git a/src/foods.py b/src/foods.py new file mode 100644 index 0000000..3833d8c --- /dev/null +++ b/src/foods.py @@ -0,0 +1,92 @@ +import pygame.sprite + +from games.easy_game.src.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 + + +class Food(pygame.sprite.Sprite): + def __init__(self, group): + pygame.sprite.Sprite.__init__(self, group) + self.image = pygame.Surface([8, 8]) + self.type = None + self.score = 0 + self.color = None + + self.rect = self.image.get_rect() + self.angle = 0 + + def update(self) -> None: + pass + + @property + def game_object_data(self): + return create_rect_view_data( + "food", + self.rect.x, + self.rect.y, + self.rect.width, + self.rect.height, + self.color + ) + + +class GoodFoodLv1(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() +class GoodFoodLv2(Food): + def __init__(self, group): + super().__init__(group) + + self.image = pygame.Surface([FOOD_LV2_SIZE, FOOD_LV2_SIZE]) + self.type = FoodTypeEnum.GOOD_2 + self.color = FOOD_COLOR_MAP[self.type] + self.score = 2 + self.rect = self.image.get_rect() + +class GoodFoodLv3(Food): + def __init__(self, group): + super().__init__(group) + + self.image = pygame.Surface([FOOD_LV3_SIZE, FOOD_LV3_SIZE]) + self.type = FoodTypeEnum.GOOD_3 + self.color = FOOD_COLOR_MAP[self.type] + self.score = 4 + self.rect = self.image.get_rect() + + + + +class BadFoodLv1(Food): + def __init__(self, group): + super().__init__(group) + self.image = pygame.Surface([FOOD_LV1_SIZE, FOOD_LV1_SIZE]) + self.type = FoodTypeEnum.BAD_1 + self.color = FOOD_COLOR_MAP[self.type] + self.score = -1 + self.rect = self.image.get_rect() + self.angle = 0 + +class BadFoodLv2(Food): + def __init__(self, group): + super().__init__(group) + + self.image = pygame.Surface([FOOD_LV2_SIZE, FOOD_LV2_SIZE]) + self.type = FoodTypeEnum.BAD_2 + self.color = FOOD_COLOR_MAP[self.type] + self.score = -2 + self.rect = self.image.get_rect() + +class BadFoodLv3(Food): + def __init__(self, group): + super().__init__(group) + + self.image = pygame.Surface([FOOD_LV3_SIZE, FOOD_LV3_SIZE]) + self.type = FoodTypeEnum.BAD_3 + self.color = FOOD_COLOR_MAP[self.type] + self.score = -4 + self.rect = self.image.get_rect() diff --git a/src/game.py b/src/game.py index 3b916df..9f063ef 100644 --- a/src/game.py +++ b/src/game.py @@ -9,65 +9,62 @@ 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 .env import * -from .env import FoodTypeEnum -from .game_object import Ball, Food +from .foods import * +from .game_object import Ball from .sound_controller import SoundController +def revise_ball(ball: Ball, playground: pygame.Rect): + ball_rect = copy.deepcopy(ball.rect) + if ball_rect.left < playground.left: + ball_rect.left = playground.left + elif ball_rect.right > playground.right: + ball_rect.right = playground.right + + if ball_rect.top < playground.top: + ball_rect.top = playground.top + elif ball_rect.bottom > playground.bottom: + ball_rect.bottom = playground.bottom + ball.rect = ball_rect + pass + + class EasyGame(PaiaGame): """ This is a Interface of a game """ def __init__( - self, time_to_play, score_to_pass, green_food_count, red_food_count, - playground_size: list, - level: int = -1, + self, + level: int = 1, level_file: str = None, sound: str = "off", *args, **kwargs): super().__init__(user_num=1) - + # TODO reduce game config and use level file self.game_result_state = GameResultState.FAIL self.scene = Scene(width=WIDTH, height=HEIGHT, color=BG_COLOR, bias_x=0, bias_y=0) self._level = level self._level_file = level_file - if self._level_file is not None or level == "": - # set by injected file - self.set_game_params_by_file(self._level_file) - pass - elif self._level != -1: - # set by level number - self.set_game_params_by_level(self._level) - pass - else: - # set by game params - self._playground_w = int(playground_size[0]) - self._playground_h = int(playground_size[1]) - self.playground = pygame.Rect( - 0, 0, - self._playground_w, - self._playground_h - ) - self._green_food_count = green_food_count - self._red_food_count = red_food_count - self._score_to_pass = score_to_pass - self._frame_limit = time_to_play - 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): + if path.isfile(self._level_file) or self._level_file == "": + # 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.set_game_params_by_file(level_file_path) + self._init_game_by_file(level_file_path) - def set_game_params_by_file(self, level_file_path: str): + def _init_game_by_file(self, level_file_path: str): try: with open(level_file_path) as f: game_params = json.load(f) - self._set_game_params(game_params) except: # If the file doesn't exist, use default parameters print("此關卡檔案不存在,遊戲將會會自動使用第一關檔案 001.json。") @@ -75,32 +72,40 @@ class EasyGame(PaiaGame): with open(os.path.join(LEVEL_PATH, "001.json")) as f: game_params = json.load(f) self._level = 1 - self._level_file=None - self._set_game_params(game_params) + self._level_file = None + 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 + ) + self._green_food_count = game_params["green_food_count"] + self._red_food_count = game_params["black_food_count"] + self._score_to_pass = int(game_params["score_to_pass"]) + self._frame_limit = int(game_params["time_to_play"]) + self.playground.center = (WIDTH / 2, HEIGHT / 2) + + # init game + self.ball = Ball() + self.foods.empty() + self.score = 0 + + # todo validate food count + self._create_foods(GoodFoodLv1, self._green_food_count[0]) + self._create_foods(GoodFoodLv2, self._green_food_count[1]) + self._create_foods(GoodFoodLv3, self._green_food_count[2]) + self._create_foods(BadFoodLv1, self._red_food_count[0]) + self._create_foods(BadFoodLv2, self._red_food_count[1]) + self._create_foods(BadFoodLv3, self._red_food_count[2]) + + self.frame_count = 0 + self._frame_count_down = self._frame_limit + self.sound_controller.play_music() - def _set_game_params(self, 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 - ) - self._green_food_count = int(game_params["green_food_count"]) - self._red_food_count = int(game_params["black_food_count"]) - self._score_to_pass = int(game_params["score_to_pass"]) - 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() - self.score = 0 - self._create_foods(self._green_food_count, FoodTypeEnum.GREEN) - 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,24 +116,13 @@ class EasyGame(PaiaGame): action = "NONE" self.ball.update(action) - self.revise_ball(self.ball, self.playground) + revise_ball(self.ball, self.playground) # update sprite self.foods.update() # 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._check_foods_collision() # self._timer = round(time.time() - self._begin_time, 3) self.frame_count += 1 @@ -138,6 +132,17 @@ class EasyGame(PaiaGame): if not self.is_running: return "RESET" + def _check_foods_collision(self): + hits = pygame.sprite.spritecollide(self.ball, self.foods, True) + if hits: + for food in hits: + self.score += food.score + self._create_foods(food.__class__, 1) + if isinstance(food, (GoodFoodLv1,GoodFoodLv2,GoodFoodLv3,)): + self.sound_controller.play_eating_good() + elif isinstance(food, (BadFoodLv1,BadFoodLv2,BadFoodLv3,)): + self.sound_controller.play_eating_bad() + def get_data_from_game_to_player(self): """ send something to game AI @@ -146,13 +151,16 @@ class EasyGame(PaiaGame): to_players_data = {} foods_data = [] for food in self.foods: - foods_data.append({"x": food.rect.x, "y": food.rect.y}) + # TODO add good food and bad food + + foods_data.append({"x": food.rect.x, "y": food.rect.y, "type": food.type, "score": food.score}) data_to_1p = { "frame": self.frame_count, "ball_x": self.ball.rect.centerx, "ball_y": self.ball.rect.centery, "foods": foods_data, "score": self.score, + "score_to_pass":self._score_to_pass, "status": self.get_game_status() } @@ -181,9 +189,9 @@ class EasyGame(PaiaGame): elif self.is_passed and self._level != -1: # win and use level will enter next level self._level += 1 - self.set_game_params_by_level(self._level) + self._init_game_by_level(self._level) - self.init_game() + self._init_game() pass @@ -199,7 +207,6 @@ class EasyGame(PaiaGame): """ Get the initial scene and object information for drawing on the web """ - # TODO add music or sound # bg_path = path.join(ASSET_PATH, "img/background.jpg") # background = create_asset_init_data( # "background", WIDTH, HEIGHT, bg_path, @@ -280,25 +287,10 @@ class EasyGame(PaiaGame): cmd_1p.append("NONE") return {get_ai_name(0): cmd_1p} - def _create_foods(self, count: int = 5, type: FoodTypeEnum = FoodTypeEnum.GREEN): + def _create_foods(self, FOOD_TYPE, count: int = 5): for i in range(count): # add food to group - food = Food(self.foods, type) - + 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) pass - - def revise_ball(self, ball: Ball, playground: pygame.Rect): - ball_rect = copy.deepcopy(ball.rect) - if ball_rect.left < playground.left: - ball_rect.left = playground.left - elif ball_rect.right > playground.right: - ball_rect.right = playground.right - - if ball_rect.top < playground.top: - ball_rect.top = playground.top - elif ball_rect.bottom > playground.bottom: - ball_rect.bottom = playground.bottom - ball.rect = ball_rect - pass diff --git a/src/game_object.py b/src/game_object.py index e7c316a..bf0e9c9 100644 --- a/src/game_object.py +++ b/src/game_object.py @@ -1,6 +1,7 @@ import pygame.sprite -from games.easy_game.src.env import FoodTypeEnum, FOOD_COLOR_MAP, BALL_COLOR, BALL_VEL, BALL_H, BALL_W +from games.easy_game.src.env import BALL_COLOR, BALL_VEL, BALL_H, BALL_W +from games.easy_game.src.foods import Food from mlgame.view.view_model import create_rect_view_data @@ -44,26 +45,3 @@ class Ball(pygame.sprite.Sprite): ) -class Food(pygame.sprite.Sprite): - def __init__(self, group, type: FoodTypeEnum): - pygame.sprite.Sprite.__init__(self, group) - self.image = pygame.Surface([8, 8]) - self.type = type - self.color = FOOD_COLOR_MAP[type] - - self.rect = self.image.get_rect() - self.angle = 0 - - def update(self) -> None: - pass - - @property - def game_object_data(self): - return create_rect_view_data( - "food", - self.rect.x, - self.rect.y, - self.rect.width, - self.rect.height, - self.color - )