update all to 2.0.0
This commit is contained in:
parent
01cb8c4a3b
commit
d5a071ed32
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,24 @@
|
||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
|
class MLPlay:
|
||||||
|
def __init__(self, ai_name:str,*args, **kwargs):
|
||||||
|
print(f"Initial {__file__} script with ai_name:{ai_name}")
|
||||||
|
|
||||||
|
|
||||||
|
def update(self, scene_info: dict, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Generate the command according to the received scene information
|
||||||
|
"""
|
||||||
|
# print("AI received data from game :", json.dumps(scene_info))
|
||||||
|
# print(scene_info)
|
||||||
|
actions = ["UP", "DOWN", "LEFT", "RIGHT"]
|
||||||
|
|
||||||
|
return random.sample(actions, 1)
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""
|
||||||
|
Reset the status
|
||||||
|
"""
|
||||||
|
print("reset ml script")
|
||||||
|
pass
|
|
@ -0,0 +1,26 @@
|
||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
|
class MLPlay:
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
print("Initial ml script")
|
||||||
|
self.count=0
|
||||||
|
|
||||||
|
def update(self, scene_info: dict, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Generate the command according to the received scene information
|
||||||
|
"""
|
||||||
|
# print("AI received data from game :", json.dumps(scene_info))
|
||||||
|
# print(scene_info)
|
||||||
|
actions = ["UP", "DOWN", "LEFT", "RIGHT"]
|
||||||
|
self.count+=1
|
||||||
|
if self.count >100:
|
||||||
|
a = actions[100]
|
||||||
|
return random.sample(actions, 1)
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""
|
||||||
|
Reset the status
|
||||||
|
"""
|
||||||
|
print("reset ml script")
|
||||||
|
pass
|
|
@ -0,0 +1,22 @@
|
||||||
|
import random
|
||||||
|
|
||||||
|
class MLPlay:
|
||||||
|
def __init__(self, *args, **kwargs)
|
||||||
|
print("Initial ml script")
|
||||||
|
|
||||||
|
def update(self, scene_info: dict, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Generate the command according to the received scene information
|
||||||
|
"""
|
||||||
|
# print("AI received data from game :", json.dumps(scene_info))
|
||||||
|
# print(scene_info)
|
||||||
|
actions = ["UP", "DOWN", "LEFT", "RIGHT"]
|
||||||
|
|
||||||
|
return random.sample(actions, 1)
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""
|
||||||
|
Reset the status
|
||||||
|
"""
|
||||||
|
print("reset ml script")
|
||||||
|
pass
|
|
@ -0,0 +1,24 @@
|
||||||
|
import random
|
||||||
|
import aaa
|
||||||
|
|
||||||
|
|
||||||
|
class MLPlay:
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
print("Initial ml script")
|
||||||
|
|
||||||
|
def update(self, scene_info: dict, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Generate the command according to the received scene information
|
||||||
|
"""
|
||||||
|
# print("AI received data from game :", json.dumps(scene_info))
|
||||||
|
# print(scene_info)
|
||||||
|
actions = ["UP", "DOWN", "LEFT", "RIGHT"]
|
||||||
|
|
||||||
|
return random.sample(actions, 1)
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""
|
||||||
|
Reset the status
|
||||||
|
"""
|
||||||
|
print("reset ml script")
|
||||||
|
pass
|
|
@ -0,0 +1,36 @@
|
||||||
|
import pygame
|
||||||
|
|
||||||
|
|
||||||
|
class MLPlay:
|
||||||
|
def __init__(self, ai_name: str, *args, **kwargs):
|
||||||
|
self.ai_name = ai_name
|
||||||
|
print(f"Initial {__file__} script with ai_name:{ai_name}")
|
||||||
|
|
||||||
|
def update(self, scene_info: dict, keyboard: list = [], *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Generate the command according to the received scene information
|
||||||
|
"""
|
||||||
|
# print("AI received data from game :", json.dumps(scene_info))
|
||||||
|
# print(scene_info)
|
||||||
|
actions = []
|
||||||
|
|
||||||
|
if pygame.K_w in keyboard or pygame.K_UP in keyboard:
|
||||||
|
actions.append("UP")
|
||||||
|
elif pygame.K_s in keyboard or pygame.K_DOWN in keyboard:
|
||||||
|
actions.append("DOWN")
|
||||||
|
|
||||||
|
elif pygame.K_a in keyboard or pygame.K_LEFT in keyboard:
|
||||||
|
actions.append("LEFT")
|
||||||
|
elif pygame.K_d in keyboard or pygame.K_RIGHT in keyboard:
|
||||||
|
actions.append("RIGHT")
|
||||||
|
else:
|
||||||
|
actions.append("NONE")
|
||||||
|
|
||||||
|
return actions
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""
|
||||||
|
Reset the status
|
||||||
|
"""
|
||||||
|
print("reset ml script")
|
||||||
|
pass
|
Binary file not shown.
After Width: | Height: | Size: 1.6 MiB |
Binary file not shown.
After Width: | Height: | Size: 1018 KiB |
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"GAME_STATUS": [
|
||||||
|
["GAME_ALIVE", "alive", "存活"],
|
||||||
|
["GAME_PASS", "pass", "通關"],
|
||||||
|
["GAME_OVER", "over", "失敗"]
|
||||||
|
],
|
||||||
|
"SCENE_INFO": [
|
||||||
|
["scene_info['frame']", "# frame", "# 幀數"],
|
||||||
|
["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['foods']", "list of foods positions", "點點的位置清單"],
|
||||||
|
["scene_info", "dictionary of all information", "包含所有資訊的字典"]
|
||||||
|
],
|
||||||
|
"CONSTANT": [
|
||||||
|
[0, "left boundary", "左邊界"],
|
||||||
|
[800, "right boundary", "右邊界"],
|
||||||
|
[0, "top boundary", "上邊界"],
|
||||||
|
[600, "bottom boundary", "下邊界"],
|
||||||
|
[50, "ball width", "球身的寬度"],
|
||||||
|
[50, "ball height", "球身的高度"],
|
||||||
|
[8, "food width", "食物的寬度"],
|
||||||
|
[8, "food height", "食物的高度"]
|
||||||
|
],
|
||||||
|
"ACTION": [
|
||||||
|
["['UP']", "moving up", "向上移動"],
|
||||||
|
["['DOWN']", "moving down", "向下移動"],
|
||||||
|
["['LEFT']", "moving left", "向左移動"],
|
||||||
|
["['RIGHT']", "moving right", "向右移動"],
|
||||||
|
["['NONE']", "doing nothing", "不動作"]
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
import sys
|
||||||
|
from os import path
|
||||||
|
sys.path.append(path.dirname(__file__))
|
||||||
|
|
||||||
|
from mlgame.argument.tool import read_json_file, parse_config
|
||||||
|
from src.game import EasyGame
|
||||||
|
|
||||||
|
config_file = path.join(path.dirname(__file__), "game_config.json")
|
||||||
|
|
||||||
|
|
||||||
|
config_data = read_json_file(config_file)
|
||||||
|
GAME_VERSION = config_data["version"]
|
||||||
|
GAME_PARAMS = parse_config(config_data)
|
||||||
|
|
||||||
|
# will be equal to config. GAME_SETUP["ml_clients"][0]["name"]
|
||||||
|
|
||||||
|
GAME_SETUP = {
|
||||||
|
"game": EasyGame,
|
||||||
|
# "dynamic_ml_clients":True
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
{
|
||||||
|
"game_name": "easy_game",
|
||||||
|
"version": "2.0.0",
|
||||||
|
"url": "None",
|
||||||
|
"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": "total_point_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",
|
||||||
|
"verbose": "通關分數",
|
||||||
|
"type": "int",
|
||||||
|
"min": 1,
|
||||||
|
"max": 30,
|
||||||
|
"default": 10,
|
||||||
|
"help": "set the score to win this game "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "color",
|
||||||
|
"verbose": "矩形顏色",
|
||||||
|
"type": "str",
|
||||||
|
"choices": [
|
||||||
|
{
|
||||||
|
"verbose": "CYAN",
|
||||||
|
"value": "00BCD4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"verbose": "YELLOW",
|
||||||
|
"value": "FFEB3B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"verbose": "ORANGE",
|
||||||
|
"value": "FF9800"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"help": "set the color of rectangle",
|
||||||
|
"default": "00BCD4"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,192 @@
|
||||||
|
# Easy Game
|
||||||
|
這是一個簡單的遊戲,主要用來示範如何在PAIA 上發布一個遊戲
|
||||||
|

|
||||||
|
## Game Config
|
||||||
|
遊戲參數定義檔案需要使用json格式,且需要命名為`game_config.json`
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"game_name": "easy_game", // 遊戲的名稱
|
||||||
|
"version": "1.0.1", // 版本號
|
||||||
|
"url": "None", // github 專案連結
|
||||||
|
"game_params": [ // 遊戲參數陣列
|
||||||
|
{
|
||||||
|
"name": "time_to_play", // 遊戲參數的名字
|
||||||
|
"verbose": "遊戲總幀數", // 顯示文字
|
||||||
|
"type": "int", // 類型 分為 int str
|
||||||
|
"max": 2000, // int 可以設定 最大最小值
|
||||||
|
"min": 600,
|
||||||
|
"default": 600, // 遊戲參數的預設值
|
||||||
|
// 參數的輔助說明
|
||||||
|
"help": "set the limit of frame count , actually time will be revised according to your FPS .",
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "color",
|
||||||
|
"verbose": "矩形顏色",
|
||||||
|
"type": "str",
|
||||||
|
"choices": [
|
||||||
|
// 字串的選項需要有顯示文字(verbose) 與 實際值(value)
|
||||||
|
{
|
||||||
|
"verbose": "CYAN",
|
||||||
|
"value": "00BCD4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"verbose": "YELLOW",
|
||||||
|
"value": "FFEB3B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"verbose": "ORANGE",
|
||||||
|
"value": "FF9800"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"help": "set the color of rectangle",
|
||||||
|
"default": "FFEB3B"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
## Game Blockly
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"GAME_STATUS": [
|
||||||
|
// 遊戲狀態的參數
|
||||||
|
// ['python 變數名稱','display in English','中文的顯示文字']
|
||||||
|
["GAME_ALIVE", "alive", "存活"],
|
||||||
|
["GAME_PASS", "pass", "通關"],
|
||||||
|
["GAME_OVER", "over", "失敗"]
|
||||||
|
],
|
||||||
|
"SCENE_INFO": [
|
||||||
|
// 傳給MLPlay的資料內容
|
||||||
|
// ["python code", "english", "chinese"],
|
||||||
|
["scene_info['frame']", "# frame", "# 幀數"],
|
||||||
|
["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['foods']", "list of foods positions", "點點的位置清單"],
|
||||||
|
["scene_info", "dictionary of all information", "包含所有資訊的字典"]
|
||||||
|
],
|
||||||
|
"CONSTANT": [
|
||||||
|
// 提供給玩家的常數資訊
|
||||||
|
// ["value", "english", "chinese"],
|
||||||
|
[0, "left boundary", "左邊界"],
|
||||||
|
[800, "right boundary", "右邊界"],
|
||||||
|
[0, "top boundary", "上邊界"],
|
||||||
|
[600, "bottom boundary", "下邊界"],
|
||||||
|
[50, "ball width", "球身的寬度"],
|
||||||
|
[50, "ball height", "球身的高度"],
|
||||||
|
[8, "food width", "食物的寬度"],
|
||||||
|
[8, "food height", "食物的高度"]
|
||||||
|
],
|
||||||
|
"ACTION": [
|
||||||
|
// 讓玩家使用的遊戲指令
|
||||||
|
// ["python code", "english", "chinese"],
|
||||||
|
["UP", "moving up", "向上移動"],
|
||||||
|
["DOWN", "moving down", "向下移動"],
|
||||||
|
["LEFT", "moving left", "向左移動"],
|
||||||
|
["RIGHT", "moving right", "向右移動"],
|
||||||
|
["NONE", "doing nothing", "不動作"]
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
## Game interface
|
||||||
|
遊戲需要實作一個interface
|
||||||
|
```python
|
||||||
|
|
||||||
|
class PaiaGame(abc.ABC):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""
|
||||||
|
初始化資料
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def update(self, commands):
|
||||||
|
self.frame_count += 1
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def game_to_player_data(self) -> dict:
|
||||||
|
"""
|
||||||
|
send something to game AI
|
||||||
|
we could send different data to different ai
|
||||||
|
"""
|
||||||
|
to_players_data = {}
|
||||||
|
|
||||||
|
return to_players_data
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def reset(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_scene_init_data(self) -> dict:
|
||||||
|
"""
|
||||||
|
Get the initial scene and object information for drawing on the web
|
||||||
|
"""
|
||||||
|
# TODO add music or sound
|
||||||
|
scene_init_data = {"scene": self.scene.__dict__,
|
||||||
|
"assets": [
|
||||||
|
|
||||||
|
],
|
||||||
|
# "audios": {}
|
||||||
|
}
|
||||||
|
return scene_init_data
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_scene_progress_data(self) -> dict:
|
||||||
|
"""
|
||||||
|
Get the position of game objects for drawing on the web
|
||||||
|
"""
|
||||||
|
|
||||||
|
scene_progress = {
|
||||||
|
# background view data will be draw first
|
||||||
|
"background": [],
|
||||||
|
# game object view data will be draw on screen by order , and it could be shifted by WASD
|
||||||
|
"object_list": [],
|
||||||
|
"toggle": [],
|
||||||
|
"foreground": [],
|
||||||
|
# other information to display on web
|
||||||
|
"user_info": [],
|
||||||
|
# other information to display on web
|
||||||
|
"game_sys_info": {}
|
||||||
|
}
|
||||||
|
return scene_progress
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_game_result(self) -> dict:
|
||||||
|
"""
|
||||||
|
send game result
|
||||||
|
"""
|
||||||
|
return {"frame_used": self.frame_count,
|
||||||
|
"result": {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_keyboard_command(self) -> dict:
|
||||||
|
"""
|
||||||
|
Define how your game will run by your keyboard
|
||||||
|
"""
|
||||||
|
cmd_1p = []
|
||||||
|
|
||||||
|
ai_1p = self.ai_clients()[0]["name"]
|
||||||
|
return {ai_1p: cmd_1p}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def ai_clients() -> list:
|
||||||
|
"""
|
||||||
|
let MLGame know how to parse your ai,
|
||||||
|
you can also use this names to get different cmd and send different data to each ai client
|
||||||
|
"""
|
||||||
|
return [
|
||||||
|
{"name": "1P"}
|
||||||
|
]
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Flowchart
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
import pygame
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.append(r"../..")
|
||||||
|
from mlgame.view.view import PygameView
|
||||||
|
from mlgame.gamedev.generic import quit_or_esc
|
||||||
|
from src.game import EasyGame
|
||||||
|
|
||||||
|
FPS = 30
|
||||||
|
if __name__ == '__main__':
|
||||||
|
pygame.init()
|
||||||
|
game = EasyGame(time_to_play=1000, total_point_count=10, score=5, color="FF9800")
|
||||||
|
scene_init_info_dict = game.get_scene_init_data()
|
||||||
|
game_view = PygameView(scene_init_info_dict)
|
||||||
|
frame_count = 0
|
||||||
|
while game.is_running and not quit_or_esc():
|
||||||
|
pygame.time.Clock().tick_busy_loop(FPS)
|
||||||
|
commands = game.get_keyboard_command()
|
||||||
|
game.update(commands)
|
||||||
|
game_progress_data = game.get_scene_progress_data()
|
||||||
|
game_view.draw(game_progress_data)
|
||||||
|
frame_count += 1
|
||||||
|
# print(frame_count)
|
||||||
|
|
||||||
|
pygame.quit()
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,188 @@
|
||||||
|
import time
|
||||||
|
from os import path
|
||||||
|
|
||||||
|
import pygame
|
||||||
|
|
||||||
|
from mlgame.argument.model import AI_NAMES
|
||||||
|
from mlgame.gamedev.paia_game import PaiaGame, GameResultState, GameStatus
|
||||||
|
from mlgame.tests.test_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, \
|
||||||
|
create_scene_progress_data
|
||||||
|
from .game_object import Ball, Food
|
||||||
|
|
||||||
|
ASSET_PATH = path.join(path.dirname(__file__), "../asset")
|
||||||
|
|
||||||
|
|
||||||
|
class EasyGame(PaiaGame):
|
||||||
|
"""
|
||||||
|
This is a Interface of a game
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, time_to_play, total_point_count, score, color):
|
||||||
|
super().__init__()
|
||||||
|
self.game_result_state = GameResultState.FAIL
|
||||||
|
self.scene = Scene(width=800, height=600, color="#4FC3F7", bias_x=0, bias_y=0)
|
||||||
|
print(color)
|
||||||
|
self.ball = Ball("#" + color)
|
||||||
|
self.foods = pygame.sprite.Group()
|
||||||
|
self.score = 0
|
||||||
|
self.score_to_win = score
|
||||||
|
self._create_foods(total_point_count)
|
||||||
|
self._begin_time = time.time()
|
||||||
|
self._timer = 0
|
||||||
|
self.frame_count = 0
|
||||||
|
self.time_limit = time_to_play
|
||||||
|
|
||||||
|
def update(self, commands):
|
||||||
|
# handle command
|
||||||
|
ai_1p_cmd = commands[AI_NAMES[0]]
|
||||||
|
if ai_1p_cmd is not None:
|
||||||
|
action = ai_1p_cmd[0]
|
||||||
|
else:
|
||||||
|
action = "NONE"
|
||||||
|
# print(ai_1p_cmd)
|
||||||
|
self.ball.update(action)
|
||||||
|
|
||||||
|
# update sprite
|
||||||
|
self.foods.update()
|
||||||
|
|
||||||
|
# handle collision
|
||||||
|
hits = pygame.sprite.spritecollide(self.ball, self.foods, True, pygame.sprite.collide_rect_ratio(0.8))
|
||||||
|
if hits:
|
||||||
|
self.score += len(hits)
|
||||||
|
self._create_foods(len(hits))
|
||||||
|
self._timer = round(time.time() - self._begin_time, 3)
|
||||||
|
|
||||||
|
self.frame_count += 1
|
||||||
|
# self.draw()
|
||||||
|
|
||||||
|
if not self.is_running:
|
||||||
|
return "QUIT"
|
||||||
|
|
||||||
|
def game_to_player_data(self):
|
||||||
|
"""
|
||||||
|
send something to game AI
|
||||||
|
we could send different data to different ai
|
||||||
|
"""
|
||||||
|
to_players_data = {}
|
||||||
|
foods_data = []
|
||||||
|
for food in self.foods:
|
||||||
|
foods_data.append({"x": food.rect.x, "y": food.rect.y})
|
||||||
|
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,
|
||||||
|
"status": self.get_game_status()
|
||||||
|
}
|
||||||
|
|
||||||
|
to_players_data[AI_NAMES[0]] = data_to_1p
|
||||||
|
# should be equal to config. GAME_SETUP["ml_clients"][0]["name"]
|
||||||
|
|
||||||
|
return to_players_data
|
||||||
|
|
||||||
|
def get_game_status(self):
|
||||||
|
|
||||||
|
if self.is_running:
|
||||||
|
status = GameStatus.GAME_ALIVE
|
||||||
|
elif self.score > self.score_to_win:
|
||||||
|
status = GameStatus.GAME_PASS
|
||||||
|
else:
|
||||||
|
status = GameStatus.GAME_OVER
|
||||||
|
return status
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_running(self):
|
||||||
|
return self.frame_count < self.time_limit
|
||||||
|
|
||||||
|
def get_scene_init_data(self):
|
||||||
|
"""
|
||||||
|
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", 800, 600, bg_path, "url")
|
||||||
|
scene_init_data = {"scene": self.scene.__dict__,
|
||||||
|
"assets": [
|
||||||
|
background
|
||||||
|
],
|
||||||
|
# "audios": {}
|
||||||
|
}
|
||||||
|
return scene_init_data
|
||||||
|
|
||||||
|
@check_game_progress
|
||||||
|
def get_scene_progress_data(self):
|
||||||
|
"""
|
||||||
|
Get the position of game objects for drawing on the web
|
||||||
|
"""
|
||||||
|
foods_data = []
|
||||||
|
for food in self.foods:
|
||||||
|
foods_data.append(food.game_object_data)
|
||||||
|
game_obj_list = [self.ball.game_object_data]
|
||||||
|
game_obj_list.extend(foods_data)
|
||||||
|
backgrounds = [create_image_view_data("background", 0, 0, 800, 600)]
|
||||||
|
foregrounds = [create_text_view_data(f"Score = {str(self.score)}", 650, 50, "#FF0000", "24px Arial BOLD")]
|
||||||
|
toggle_objs = [create_text_view_data(f"Timer = {str(self._timer)} s", 650, 100, "#FFAA00", "24px Arial")]
|
||||||
|
scene_progress = create_scene_progress_data(frame=self.frame_count, background=backgrounds,
|
||||||
|
object_list=game_obj_list,
|
||||||
|
foreground=foregrounds, toggle=toggle_objs)
|
||||||
|
return scene_progress
|
||||||
|
|
||||||
|
@check_game_result
|
||||||
|
def get_game_result(self):
|
||||||
|
"""
|
||||||
|
send game result
|
||||||
|
"""
|
||||||
|
if self.get_game_status() == GameStatus.GAME_PASS:
|
||||||
|
self.game_result_state = GameResultState.FINISH
|
||||||
|
return {"frame_used": self.frame_count,
|
||||||
|
"state": self.game_result_state,
|
||||||
|
"attachment": [
|
||||||
|
{
|
||||||
|
"player": AI_NAMES[0],
|
||||||
|
"rank": 1,
|
||||||
|
"score": self.score
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_keyboard_command(self):
|
||||||
|
"""
|
||||||
|
Define how your game will run by your keyboard
|
||||||
|
"""
|
||||||
|
cmd_1p = []
|
||||||
|
key_pressed_list = pygame.key.get_pressed()
|
||||||
|
if key_pressed_list[pygame.K_UP]:
|
||||||
|
cmd_1p.append("UP")
|
||||||
|
elif key_pressed_list[pygame.K_DOWN]:
|
||||||
|
cmd_1p.append("DOWN")
|
||||||
|
elif key_pressed_list[pygame.K_LEFT]:
|
||||||
|
cmd_1p.append("LEFT")
|
||||||
|
elif key_pressed_list[pygame.K_RIGHT]:
|
||||||
|
cmd_1p.append("RIGHT")
|
||||||
|
else:
|
||||||
|
cmd_1p.append("NONE")
|
||||||
|
return {AI_NAMES[0]: cmd_1p}
|
||||||
|
|
||||||
|
def _create_foods(self, count: int = 5):
|
||||||
|
for i in range(count):
|
||||||
|
# add food to group
|
||||||
|
food = Food(self.foods)
|
||||||
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def ai_clients():
|
||||||
|
"""
|
||||||
|
let MLGame know how to parse your ai,
|
||||||
|
you can also use this names to get different cmd and send different data to each ai client
|
||||||
|
"""
|
||||||
|
return [
|
||||||
|
{"name": "1P",
|
||||||
|
|
||||||
|
},
|
||||||
|
]
|
|
@ -0,0 +1,63 @@
|
||||||
|
import random
|
||||||
|
|
||||||
|
import pygame.sprite
|
||||||
|
|
||||||
|
|
||||||
|
class Ball(pygame.sprite.Sprite):
|
||||||
|
def __init__(self, color="#FFEB3B"):
|
||||||
|
pygame.sprite.Sprite.__init__(self)
|
||||||
|
self.image = pygame.Surface([50, 50])
|
||||||
|
self.color = color
|
||||||
|
self.rect = self.image.get_rect()
|
||||||
|
self.rect.center = (400, 300)
|
||||||
|
|
||||||
|
def update(self, motion):
|
||||||
|
# for motion in motions:
|
||||||
|
if motion == "UP":
|
||||||
|
self.rect.centery -= 10.5
|
||||||
|
elif motion == "DOWN":
|
||||||
|
self.rect.centery += 10.5
|
||||||
|
elif motion == "LEFT":
|
||||||
|
self.rect.centerx -= 10.5
|
||||||
|
elif motion == "RIGHT":
|
||||||
|
self.rect.centerx += 10.5
|
||||||
|
|
||||||
|
@property
|
||||||
|
def game_object_data(self):
|
||||||
|
return {"type": "rect",
|
||||||
|
"name": "ball",
|
||||||
|
"x": self.rect.x,
|
||||||
|
"y": self.rect.y,
|
||||||
|
"angle": 0,
|
||||||
|
"width": self.rect.width,
|
||||||
|
"height": self.rect.height,
|
||||||
|
"color": self.color
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Food(pygame.sprite.Sprite):
|
||||||
|
def __init__(self, group):
|
||||||
|
pygame.sprite.Sprite.__init__(self, group)
|
||||||
|
self.image = pygame.Surface([8, 8])
|
||||||
|
self.color = "#E91E63"
|
||||||
|
self.rect = self.image.get_rect()
|
||||||
|
self.rect.centerx = random.randint(0, 800)
|
||||||
|
self.rect.centery = random.randint(0, 600)
|
||||||
|
self.angle = 0
|
||||||
|
|
||||||
|
def update(self) -> None:
|
||||||
|
self.angle += 10
|
||||||
|
if self.angle > 360:
|
||||||
|
self.angle -= 360
|
||||||
|
|
||||||
|
@property
|
||||||
|
def game_object_data(self):
|
||||||
|
return {"type": "rect",
|
||||||
|
"name": "ball",
|
||||||
|
"x": self.rect.x,
|
||||||
|
"y": self.rect.y,
|
||||||
|
"angle": 0,
|
||||||
|
"width": self.rect.width,
|
||||||
|
"height": self.rect.height,
|
||||||
|
"color": self.color
|
||||||
|
}
|
Loading…
Reference in New Issue