C語言模組

Description

要能在MLGame上支援C++的程式。

Acceptance check

  • C++打磚塊的範例程式
  • 使用說明文件

Diary or Report

C++ 打磚塊範例程式

前置作業

  1. 要先到 https://github.com/nlohmann/json/releases 的 Assets 下載 json.hpp
  2. 把 json.hpp 放到 MLGame/mlgame/crosslang/compile/cpp/include/ 目錄底下
  3. 將寫好的 c++ 版本範例程式 ml_play_template.cpp 放置到遊戲中的 ml 目錄底下 (舉例來說,MLGame/games/arkanoid/ml/ml_play_template.cpp )

json 資料型態

  • 從遊戲發送的 scene_info 通過 json.dumps() 轉換為 json 字串,發送回遊戲的 game 命令 通過 json.loads() 從 json 字串轉換為 python 物件。 客戶端 API 會將 json 字串轉換為可供腳本使用的對象,反之亦然。
  • json 使用範例

    以下是 scene_info 為 json string 的範例:

    {
        "status": "GAME_ALIVE",
        "ball": [[1, 2], [3, 4]]
    }

    在 c++ 端對應的 json 物件:

    json update(json scene_info)
    {
        cout << scene_info["status"] << endl;       // "GAME_ALIVE"
        cout << scene_info["ball"][0][0] << " "
            << scene_info["ball"][0][1] << endl;    // 1 2
    }

    json string 也可由 json 物件產生

    json j;
    
    j["direction"] = "LEFT";
    j["action"] = "SPEED_UP";
    j["data"] = {1, 2, 3};      // An array is stored as std::vector

    對應的 json string 為:

    {
        "direction": "LEFT",
        "action": "SPEED_UP",
        "data": [1, 2, 3]
    }

    如果遊戲 command 為 string 那就直接賦值:

    json j = "TURN_LEFT";

ml_play_template.cpp

  • Arkanoid

    #include <iostream>
    #include <ml_play.hpp>
    
    using namespace std;
    
    class MLPlay : public AbstractMLPlay
    {
    public:
        bool is_ball_served = false;
    
        MLPlay(json init_args)
        {
    
        }
    
        json update(json scene_info) override
        {
            json command;
    
            if (scene_info["status"] == "GAME_OVER" ||
                scene_info["status"] == "GAME_PASS") {
                command = "RESET";
                return command;
            }
    
            if (!this->is_ball_served) {
                command = "SERVE_TO_LEFT";
                this->is_ball_served = true;
            } else
                command = "MOVE_LEFT";
    
            return command;
        }
    
        void reset() override
        {
            this->is_ball_served = false;
        }
    };
  • Pingpong

    #include <iostream>
    #include <ml_play.hpp>
    
    using namespace std;
    
    class MLPlay : public AbstractMLPlay
    {
    public:
        bool is_ball_served = false;
        string side;
    
        MLPlay(json init_args)
        {
            this->side = init_args["args"][0];
        }
    
        json update(json scene_info) override
        {
            json command;
    
            if (scene_info["status"] != "GAME_ALIVE")
            {
                command = "RESET";
                return command;
            }
    
            if (!this->is_ball_served)
            {
                command = "SERVE_TO_LEFT";
                this->is_ball_served = true;
            }
            else
            {
                command = "MOVE_LEFT";
            }
    
            return command;
    
        }
    
        void reset() override
        {
            this->is_ball_served = false;
        }
    };
  • RacingCar

    #include <iostream>
    #include <ml_play.hpp>
    
    using namespace std;
    
    class MLPlay : public AbstractMLPlay
    {
    public:
        string player_num;
        json carPosition;
        json otherCarsPosition;
        json coinsPosition;
    
        MLPlay(json init_args)
        {
            string player = init_args["args"][0];
    
            if (player == "player1"){
                this->player_num = "0";
            }
            else if (player == "player2"){
                this->player_num = "1";
            }
            else if (player == "player3"){
                this->player_num = "2";
            }
            else if (player == "player4"){
                this->player_num = "3";
            }
        }
    
        json update(json scene_info) override
        {
            json command;
    
            if (scene_info["status"] == "RUNNING")
            {
                this->carPosition = scene_info["player_" + this->player_num + "_pos"];
            }
    
            otherCarsPosition = scene_info["cars_pos"];
    
            if (scene_info.contains("coin"))
            {
                this->coinsPosition = scene_info["coin"];
            } 
    
            command = "SPEED";
    
            return command;
    
        }
    
        void reset() override
        {
            cout << "reset ml script" << endl;
            return;
        }
    };
  • Maze_Car

    #include <iostream>
    #include <ml_play.hpp>
    
    using namespace std;
    
    class MLPlay : public AbstractMLPlay
    {
    public:
        json pwm;
        json control_list = {};
        float f_sensor;
        float r_sensor;
        float l_sensor;
    
        MLPlay(json init_args)
        {   
            pwm["left_PWM"] = 0;
            pwm["right_PWM"] = 0;
            control_list.push_back(pwm);
        }
    
        json update(json scene_info) override
        {
            f_sensor = scene_info["F_sensor"];
            l_sensor = scene_info["L_sensor"];
            r_sensor = scene_info["R_sensor"];
    
            int left_pwm = (int) control_list[0]["left_PWM"];
            int right_pwm = (int) control_list[0]["right_PWM"];
    
            control_list[0]["left_PWM"] = left_pwm + 50;
            control_list[0]["right_PWM"] = right_pwm + 50;
    
            return control_list;
        }
    
        void reset() override
        {
            cout << "reset ml script" << endl;
            return;
        }
    };

編譯方式

python3 MLGame.py -i ml_play_template.cpp arkanoid EASY 1

與 python 版本差不多,只是將 ml_play_template.py 置換為 ml_play_template.cpp。