Merge branch 'release/2.2.0-beta'
This commit is contained in:
commit
7a4cc1d638
17
README.md
17
README.md
|
@ -21,13 +21,17 @@
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# main.py
|
# main.py
|
||||||
game = EasyGame(time_to_play=1000, total_point_count=10, score=5, color="FF9800")
|
game = EasyGame(
|
||||||
|
time_to_play, score_to_pass, green_food_count, red_food_count,
|
||||||
|
playground_size: list,level: int = -1)
|
||||||
```
|
```
|
||||||
|
|
||||||
- `time_to_play`:遊戲執行的終止時間,單位是 frame,也就是遊戲內部更新畫面的次數,每更新一次 frame +1
|
- `time_to_play`:遊戲執行的終止時間,單位是 frame,也就是遊戲內部更新畫面的次數,每更新一次 frame +1
|
||||||
- `total_point_count`:遊戲中食物出現的最大數量。
|
- `green_food_count`:遊戲中綠色食物的數量。
|
||||||
- `score`:遊戲通關的點數,要超過這個分數才算過關。
|
- `red_food_count`:遊戲中紅色食物的數量。
|
||||||
- `color`:主角方塊的顏色,使用16進位顏色表示法
|
- `score_to_pass`:遊戲通關的點數,要超過這個分數才算過關。
|
||||||
|
- `playground_size`:可移動區域的大小。 使用逗號將數字隔開 `width,height` `100,200`
|
||||||
|
- `level`: 選定內建關卡,請注意,使用此設定將會覆蓋掉其他設定,預設為 -1 不選擇任何關卡。
|
||||||
|
|
||||||
## 玩法
|
## 玩法
|
||||||
|
|
||||||
|
@ -53,7 +57,7 @@ game = EasyGame(time_to_play=1000, total_point_count=10, score=5, color="FF9800"
|
||||||
|
|
||||||
2. 座標系統
|
2. 座標系統
|
||||||
- 螢幕大小 800 x 600
|
- 螢幕大小 800 x 600
|
||||||
- 主角方塊 50 x 50
|
- 主角方塊 30 x 30
|
||||||
- 食物方塊 8 x 8
|
- 食物方塊 8 x 8
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -64,7 +68,7 @@ game = EasyGame(time_to_play=1000, total_point_count=10, score=5, color="FF9800"
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 在easy game中,打開終端機
|
# 在easy game中,打開終端機
|
||||||
python -m mlgame -i ./ml/ml_play_template.py ./ --time_to_play 1200 --total_point_count 15 --score 10 --color FF9800
|
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
|
||||||
```
|
```
|
||||||
|
|
||||||
## AI範例
|
## AI範例
|
||||||
|
@ -163,5 +167,6 @@ class MLPlay:
|
||||||
- `player`:玩家編號
|
- `player`:玩家編號
|
||||||
- `score`:吃到的食物總數
|
- `score`:吃到的食物總數
|
||||||
- `rank`:排名
|
- `rank`:排名
|
||||||
|
- `passed`:是否通關
|
||||||
|
|
||||||
---
|
---
|
|
@ -20,8 +20,8 @@
|
||||||
[800, "right boundary", "右邊界"],
|
[800, "right boundary", "右邊界"],
|
||||||
[0, "top boundary", "上邊界"],
|
[0, "top boundary", "上邊界"],
|
||||||
[600, "bottom boundary", "下邊界"],
|
[600, "bottom boundary", "下邊界"],
|
||||||
[50, "ball width", "球身的寬度"],
|
[30, "ball width", "球身的寬度"],
|
||||||
[50, "ball height", "球身的高度"],
|
[30, "ball height", "球身的高度"],
|
||||||
[8, "food width", "食物的寬度"],
|
[8, "food width", "食物的寬度"],
|
||||||
[8, "food height", "食物的高度"]
|
[8, "food height", "食物的高度"]
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"game_name": "easy_game",
|
"game_name": "easy_game",
|
||||||
"version": "2.1.0",
|
"version": "2.2.0-beta",
|
||||||
"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": [
|
||||||
|
@ -8,7 +8,8 @@
|
||||||
"https://raw.githubusercontent.com/PAIA-Playful-AI-Arena/Paia-Desktop/master/media/easygame.svg"
|
"https://raw.githubusercontent.com/PAIA-Playful-AI-Arena/Paia-Desktop/master/media/easygame.svg"
|
||||||
],
|
],
|
||||||
"user_num": {
|
"user_num": {
|
||||||
"min": 1,"max": 1
|
"min": 1,
|
||||||
|
"max": 1
|
||||||
},
|
},
|
||||||
"game_params": [
|
"game_params": [
|
||||||
{
|
{
|
||||||
|
@ -21,15 +22,45 @@
|
||||||
"help": "set the limit of frame count , actually time will be revised according to your FPS ."
|
"help": "set the limit of frame count , actually time will be revised according to your FPS ."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "total_point_count",
|
"name": "green_food_count",
|
||||||
"verbose": "總食物數量",
|
"verbose": "綠色食物數量",
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"choices":[ 5 ,10 ,15,20,25,30,35,40,45,50],
|
"choices": [
|
||||||
|
5,
|
||||||
|
10,
|
||||||
|
15,
|
||||||
|
20,
|
||||||
|
25,
|
||||||
|
30,
|
||||||
|
35,
|
||||||
|
40,
|
||||||
|
45,
|
||||||
|
50
|
||||||
|
],
|
||||||
"help": "set the total number of points",
|
"help": "set the total number of points",
|
||||||
"default": 10
|
"default": 10
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "score",
|
"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": "通關分數",
|
"verbose": "通關分數",
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"min": 1,
|
"min": 1,
|
||||||
|
@ -38,25 +69,20 @@
|
||||||
"help": "set the score to win this game "
|
"help": "set the score to win this game "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "color",
|
"name": "playground_size",
|
||||||
"verbose": "矩形顏色",
|
"verbose": "場地尺寸",
|
||||||
"type": "str",
|
"type": "list",
|
||||||
"choices": [
|
"default": "400,400",
|
||||||
{
|
"help": "set the size of playground "
|
||||||
"verbose": "CYAN",
|
},
|
||||||
"value": "00BCD4"
|
{
|
||||||
},
|
"name": "level",
|
||||||
{
|
"verbose": "內建關卡編號",
|
||||||
"verbose": "YELLOW",
|
"type": "int",
|
||||||
"value": "FFEB3B"
|
"min": -1,
|
||||||
},
|
"max": 5,
|
||||||
{
|
"default": "-1",
|
||||||
"verbose": "ORANGE",
|
"help": "選定內建關卡,請注意,使用此設定將會覆蓋掉其他設定,預設為 -1 不選擇任何關卡。"
|
||||||
"value": "FF9800"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"help": "set the color of rectangle",
|
|
||||||
"default": "00BCD4"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"time_to_play": 300,
|
||||||
|
"playground_size": [
|
||||||
|
100,
|
||||||
|
200
|
||||||
|
],
|
||||||
|
"score_to_pass": 10,
|
||||||
|
"green_food_count": 3,
|
||||||
|
"black_food_count": 0
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"time_to_play": 300,
|
||||||
|
"playground_size": [
|
||||||
|
200,
|
||||||
|
200
|
||||||
|
],
|
||||||
|
"score_to_pass": 15,
|
||||||
|
"green_food_count": 5,
|
||||||
|
"black_food_count": 0
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"time_to_play": 500,
|
||||||
|
"playground_size": [
|
||||||
|
300,
|
||||||
|
300
|
||||||
|
],
|
||||||
|
"score_to_pass": 15,
|
||||||
|
"green_food_count": 10,
|
||||||
|
"black_food_count": 0
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"time_to_play": 600,
|
||||||
|
"playground_size": [
|
||||||
|
300,
|
||||||
|
300
|
||||||
|
],
|
||||||
|
"score_to_pass": 15,
|
||||||
|
"green_food_count": 7,
|
||||||
|
"black_food_count": 3
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"time_to_play": 800,
|
||||||
|
"playground_size": [
|
||||||
|
300,
|
||||||
|
300
|
||||||
|
],
|
||||||
|
"score_to_pass": 15,
|
||||||
|
"green_food_count": 7,
|
||||||
|
"black_food_count": 7
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"time_to_play": 1000,
|
||||||
|
"playground_size": [
|
||||||
|
400,
|
||||||
|
400
|
||||||
|
],
|
||||||
|
"score_to_pass": 15,
|
||||||
|
"green_food_count": 7,
|
||||||
|
"black_food_count": 10
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"time_to_play": 1000,
|
||||||
|
"playground_size": [
|
||||||
|
400,
|
||||||
|
400
|
||||||
|
],
|
||||||
|
"score_to_pass": 20,
|
||||||
|
"green_food_count": 7,
|
||||||
|
"black_food_count": 13
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"time_to_play": 1200,
|
||||||
|
"playground_size": [
|
||||||
|
500,
|
||||||
|
500
|
||||||
|
],
|
||||||
|
"score_to_pass": 20,
|
||||||
|
"green_food_count": 10,
|
||||||
|
"black_food_count": 15
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"time_to_play": 1200,
|
||||||
|
"playground_size": [
|
||||||
|
600,
|
||||||
|
500
|
||||||
|
],
|
||||||
|
"score_to_pass": 25,
|
||||||
|
"green_food_count": 15,
|
||||||
|
"black_food_count": 30
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"time_to_play": 1200,
|
||||||
|
"playground_size": [
|
||||||
|
700,
|
||||||
|
600
|
||||||
|
],
|
||||||
|
"score_to_pass": 25,
|
||||||
|
"green_food_count": 20,
|
||||||
|
"black_food_count": 40
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"time_to_play": 1200,
|
||||||
|
"playground_size": [
|
||||||
|
500,
|
||||||
|
200
|
||||||
|
],
|
||||||
|
"score_to_pass": 20,
|
||||||
|
"green_food_count": 3,
|
||||||
|
"black_food_count": 1
|
||||||
|
}
|
|
@ -1 +1 @@
|
||||||
mlgame>=9.5.1.7b0
|
mlgame>=10.3.1
|
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
from enum import auto
|
||||||
|
from mlgame.utils.enum import StringEnum
|
||||||
|
class FoodTypeEnum(StringEnum):
|
||||||
|
GREEN = auto()
|
||||||
|
RED = auto()
|
170
src/game.py
170
src/game.py
|
@ -1,4 +1,6 @@
|
||||||
import time
|
import copy
|
||||||
|
import json
|
||||||
|
import os.path
|
||||||
from os import path
|
from os import path
|
||||||
|
|
||||||
import pygame
|
import pygame
|
||||||
|
@ -6,11 +8,17 @@ import pygame
|
||||||
from mlgame.game.paia_game import PaiaGame, GameResultState, GameStatus
|
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 create_text_view_data, create_asset_init_data, create_image_view_data, Scene, \
|
from mlgame.view.view_model import *
|
||||||
create_scene_progress_data
|
from .enums import FoodTypeEnum
|
||||||
from .game_object import Ball, Food
|
from .game_object import Ball, Food
|
||||||
|
|
||||||
|
BG_COLOR = "#111111"
|
||||||
|
PG_COLOR = "#B3E5FC"
|
||||||
|
|
||||||
|
WIDTH = 800
|
||||||
|
HEIGHT = 600
|
||||||
ASSET_PATH = path.join(path.dirname(__file__), "../asset")
|
ASSET_PATH = path.join(path.dirname(__file__), "../asset")
|
||||||
|
LEVEL_PATH = path.join(path.dirname(__file__), "../levels")
|
||||||
|
|
||||||
|
|
||||||
class EasyGame(PaiaGame):
|
class EasyGame(PaiaGame):
|
||||||
|
@ -18,20 +26,74 @@ class EasyGame(PaiaGame):
|
||||||
This is a Interface of a game
|
This is a Interface of a game
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, time_to_play, total_point_count, score, color, *args, **kwargs):
|
def __init__(
|
||||||
|
self, time_to_play, score_to_pass, green_food_count, red_food_count,
|
||||||
|
playground_size: list,
|
||||||
|
level: int = -1,
|
||||||
|
# level_file,
|
||||||
|
*args, **kwargs):
|
||||||
super().__init__(user_num=1)
|
super().__init__(user_num=1)
|
||||||
|
|
||||||
self.game_result_state = GameResultState.FAIL
|
self.game_result_state = GameResultState.FAIL
|
||||||
self.scene = Scene(width=800, height=600, color="#4FC3F7", bias_x=0, bias_y=0)
|
self.scene = Scene(width=WIDTH, height=HEIGHT, color=BG_COLOR, bias_x=0, bias_y=0)
|
||||||
print(color)
|
self._level = level
|
||||||
self.ball = Ball("#" + color)
|
if level != -1:
|
||||||
|
|
||||||
|
self.set_game_params_by_level(level)
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
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.foods = pygame.sprite.Group()
|
||||||
|
self.init_game()
|
||||||
|
|
||||||
|
def set_game_params_by_level(self, level):
|
||||||
|
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:
|
||||||
|
game_params = json.load(f)
|
||||||
|
else:
|
||||||
|
# If the file doesn't exist, use default parameters
|
||||||
|
|
||||||
|
with open(os.path.join(LEVEL_PATH, "001.json")) as f:
|
||||||
|
game_params = json.load(f)
|
||||||
|
self._level=1
|
||||||
|
|
||||||
|
|
||||||
|
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.score = 0
|
||||||
self.score_to_win = score
|
self._create_foods(self._green_food_count, FoodTypeEnum.GREEN)
|
||||||
self._create_foods(total_point_count)
|
self._create_foods(self._red_food_count, FoodTypeEnum.RED)
|
||||||
self._begin_time = time.time()
|
|
||||||
self._timer = 0
|
|
||||||
self.frame_count = 0
|
self.frame_count = 0
|
||||||
self.time_limit = time_to_play
|
self._frame_count_down = self._frame_limit
|
||||||
|
|
||||||
def update(self, commands):
|
def update(self, commands):
|
||||||
# handle command
|
# handle command
|
||||||
|
@ -40,24 +102,31 @@ class EasyGame(PaiaGame):
|
||||||
action = ai_1p_cmd[0]
|
action = ai_1p_cmd[0]
|
||||||
else:
|
else:
|
||||||
action = "NONE"
|
action = "NONE"
|
||||||
# print(ai_1p_cmd)
|
|
||||||
self.ball.update(action)
|
|
||||||
|
|
||||||
|
self.ball.update(action)
|
||||||
|
self.revise_ball(self.ball, self.playground)
|
||||||
# update sprite
|
# update sprite
|
||||||
self.foods.update()
|
self.foods.update()
|
||||||
|
|
||||||
# handle collision
|
# handle collision
|
||||||
hits = pygame.sprite.spritecollide(self.ball, self.foods, True, pygame.sprite.collide_rect_ratio(0.8))
|
hits = pygame.sprite.spritecollide(self.ball, self.foods, True)
|
||||||
if hits:
|
if hits:
|
||||||
self.score += len(hits)
|
for food in hits:
|
||||||
self._create_foods(len(hits))
|
if food.type == FoodTypeEnum.GREEN:
|
||||||
self._timer = round(time.time() - self._begin_time, 3)
|
self.score += 1
|
||||||
|
self._create_foods(1, FoodTypeEnum.GREEN)
|
||||||
|
|
||||||
|
elif food.type == FoodTypeEnum.RED:
|
||||||
|
self._create_foods(1, FoodTypeEnum.RED)
|
||||||
|
self.score -= 1
|
||||||
|
# self._timer = round(time.time() - self._begin_time, 3)
|
||||||
|
|
||||||
self.frame_count += 1
|
self.frame_count += 1
|
||||||
|
self._frame_count_down = self._frame_limit - self.frame_count
|
||||||
# self.draw()
|
# self.draw()
|
||||||
|
|
||||||
if not self.is_running:
|
if not self.is_running:
|
||||||
return "QUIT"
|
return "RESET"
|
||||||
|
|
||||||
def get_data_from_game_to_player(self):
|
def get_data_from_game_to_player(self):
|
||||||
"""
|
"""
|
||||||
|
@ -86,31 +155,38 @@ class EasyGame(PaiaGame):
|
||||||
|
|
||||||
if self.is_running:
|
if self.is_running:
|
||||||
status = GameStatus.GAME_ALIVE
|
status = GameStatus.GAME_ALIVE
|
||||||
elif self.score > self.score_to_win:
|
elif self.score > self._score_to_pass:
|
||||||
status = GameStatus.GAME_PASS
|
status = GameStatus.GAME_PASS
|
||||||
else:
|
else:
|
||||||
status = GameStatus.GAME_OVER
|
status = GameStatus.GAME_OVER
|
||||||
return status
|
return status
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
|
if self.score > self._score_to_pass 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()
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_running(self):
|
def is_running(self):
|
||||||
return self.frame_count < self.time_limit
|
return self.frame_count < self._frame_limit
|
||||||
|
|
||||||
def get_scene_init_data(self):
|
def get_scene_init_data(self):
|
||||||
"""
|
"""
|
||||||
Get the initial scene and object information for drawing on the web
|
Get the initial scene and object information for drawing on the web
|
||||||
"""
|
"""
|
||||||
# TODO add music or sound
|
# TODO add music or sound
|
||||||
bg_path = path.join(ASSET_PATH, "img/background.jpg")
|
# bg_path = path.join(ASSET_PATH, "img/background.jpg")
|
||||||
background = create_asset_init_data(
|
# background = create_asset_init_data(
|
||||||
"background", 800, 600, bg_path,
|
# "background", WIDTH, HEIGHT, bg_path,
|
||||||
github_raw_url="https://raw.githubusercontent.com/PAIA-Playful-AI-Arena/easy_game/main/asset/img/background.jpg")
|
# github_raw_url="https://raw.githubusercontent.com/PAIA-Playful-AI-Arena/easy_game/main/asset/img/background.jpg")
|
||||||
scene_init_data = {"scene": self.scene.__dict__,
|
scene_init_data = {"scene": self.scene.__dict__,
|
||||||
"assets": [
|
"assets": [
|
||||||
background
|
# background
|
||||||
],
|
],
|
||||||
# "audios": {}
|
# "audios": {}
|
||||||
}
|
}
|
||||||
|
@ -126,9 +202,21 @@ class EasyGame(PaiaGame):
|
||||||
foods_data.append(food.game_object_data)
|
foods_data.append(food.game_object_data)
|
||||||
game_obj_list = [self.ball.game_object_data]
|
game_obj_list = [self.ball.game_object_data]
|
||||||
game_obj_list.extend(foods_data)
|
game_obj_list.extend(foods_data)
|
||||||
backgrounds = [create_image_view_data("background", 0, 0, 800, 600)]
|
backgrounds = [
|
||||||
foregrounds = [create_text_view_data(f"Score = {str(self.score)}", 650, 50, "#FF0000", "24px Arial BOLD")]
|
# create_image_view_data("background", 0, 0, WIDTH, HEIGHT),
|
||||||
toggle_objs = [create_text_view_data(f"Timer = {str(self._timer)} s", 650, 100, "#FFAA00", "24px Arial")]
|
create_rect_view_data(
|
||||||
|
"playground", self.playground.x, self.playground.y,
|
||||||
|
self.playground.w, self.playground.h, PG_COLOR)
|
||||||
|
]
|
||||||
|
foregrounds = [
|
||||||
|
|
||||||
|
]
|
||||||
|
toggle_objs = [
|
||||||
|
create_text_view_data(f"Score:{self.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" Time:{self._frame_count_down:04d}", 600, 150, "#FF5722", "24px Arial BOLD"),
|
||||||
|
|
||||||
|
]
|
||||||
scene_progress = create_scene_progress_data(frame=self.frame_count, background=backgrounds,
|
scene_progress = create_scene_progress_data(frame=self.frame_count, background=backgrounds,
|
||||||
object_list=game_obj_list,
|
object_list=game_obj_list,
|
||||||
foreground=foregrounds, toggle=toggle_objs)
|
foreground=foregrounds, toggle=toggle_objs)
|
||||||
|
@ -147,7 +235,8 @@ class EasyGame(PaiaGame):
|
||||||
{
|
{
|
||||||
"player": get_ai_name(0),
|
"player": get_ai_name(0),
|
||||||
"rank": 1,
|
"rank": 1,
|
||||||
"score": self.score
|
"score": self.score,
|
||||||
|
"passed": self.score > self._score_to_pass
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -171,8 +260,25 @@ class EasyGame(PaiaGame):
|
||||||
cmd_1p.append("NONE")
|
cmd_1p.append("NONE")
|
||||||
return {get_ai_name(0): cmd_1p}
|
return {get_ai_name(0): cmd_1p}
|
||||||
|
|
||||||
def _create_foods(self, count: int = 5):
|
def _create_foods(self, count: int = 5, type: FoodTypeEnum = FoodTypeEnum.GREEN):
|
||||||
for i in range(count):
|
for i in range(count):
|
||||||
# add food to group
|
# add food to group
|
||||||
food = Food(self.foods)
|
food = Food(self.foods, type)
|
||||||
|
|
||||||
|
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
|
pass
|
||||||
|
|
|
@ -1,25 +1,28 @@
|
||||||
import random
|
|
||||||
|
|
||||||
import pygame.sprite
|
import pygame.sprite
|
||||||
|
|
||||||
|
from games.easy_game.src.enums import FoodTypeEnum
|
||||||
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_VEL = 10.5
|
||||||
|
|
||||||
BALL_H = 50
|
BALL_H = 30
|
||||||
|
|
||||||
BALL_W = 50
|
BALL_W = 30
|
||||||
|
|
||||||
|
|
||||||
class Ball(pygame.sprite.Sprite):
|
class Ball(pygame.sprite.Sprite):
|
||||||
def __init__(self, color="#FFEB3B"):
|
def __init__(self):
|
||||||
pygame.sprite.Sprite.__init__(self)
|
pygame.sprite.Sprite.__init__(self)
|
||||||
self.origin_image = pygame.Surface([BALL_W, BALL_H])
|
self.origin_image = pygame.Surface([BALL_W, BALL_H])
|
||||||
self.image = self.origin_image
|
self.image = self.origin_image
|
||||||
self.color = 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)
|
||||||
|
|
||||||
|
|
||||||
def update(self, motion):
|
def update(self, motion):
|
||||||
# for motion in motions:
|
# for motion in motions:
|
||||||
if motion == "UP":
|
if motion == "UP":
|
||||||
|
@ -51,28 +54,25 @@ class Ball(pygame.sprite.Sprite):
|
||||||
|
|
||||||
|
|
||||||
class Food(pygame.sprite.Sprite):
|
class Food(pygame.sprite.Sprite):
|
||||||
def __init__(self, group):
|
def __init__(self, group, type: FoodTypeEnum):
|
||||||
pygame.sprite.Sprite.__init__(self, group)
|
pygame.sprite.Sprite.__init__(self, group)
|
||||||
self.image = pygame.Surface([8, 8])
|
self.image = pygame.Surface([8, 8])
|
||||||
self.color = "#E91E63"
|
self.type = type
|
||||||
|
self.color = FOOD_COLOR_MAP[type]
|
||||||
|
|
||||||
self.rect = self.image.get_rect()
|
self.rect = self.image.get_rect()
|
||||||
self.rect.centerx = random.randint(0, 800)
|
|
||||||
self.rect.centery = random.randint(0, 600)
|
|
||||||
self.angle = 0
|
self.angle = 0
|
||||||
|
|
||||||
def update(self) -> None:
|
def update(self) -> None:
|
||||||
self.angle += 10
|
pass
|
||||||
if self.angle > 360:
|
|
||||||
self.angle -= 360
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def game_object_data(self):
|
def game_object_data(self):
|
||||||
return {"type": "rect",
|
return create_rect_view_data(
|
||||||
"name": "ball",
|
"food",
|
||||||
"x": self.rect.x,
|
self.rect.x,
|
||||||
"y": self.rect.y,
|
self.rect.y,
|
||||||
"angle": 0,
|
self.rect.width,
|
||||||
"width": self.rect.width,
|
self.rect.height,
|
||||||
"height": self.rect.height,
|
self.color
|
||||||
"color": self.color
|
)
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue