新規ゲームへの対応手順
はじめに
新規ゲームに対応するためには、ゲーム固有の実装である alfort フォルダ内のソースコードを適切に書き換える必要があります。
そのための準備として、以下のことを行ってください。
- ダウンロードした Playable! ライブラリの中にある playable-item-collectorフォルダを丸ごとコピーし、playable-item-collector-{新規ゲーム名}にリネームします。
- playable-item-collector-{新規ゲーム名}/Python内の- alfortフォルダを- {新規ゲーム名}にリネームします。
- playable-item-collector-{新規ゲーム名}/Python内の各ファイルで- from alfort import XXXXや- from alfort.XXXX import YYYYとなっている部分を 全て- from {新規ゲーム名} import XXXXや- from {新規ゲーム名}.XXXX import YYYYに置換します。
以降で具体的に行うコードの書き換えについて説明します。
ゲーム操作用クラスの実装
Item Collector がゲームを起動し、操作可能にするには、最初に以下のクラスを実装する必要があります。
- ゲーム環境を制御するクラス
- ゲームからの受信データを処理・格納するクラス
- プログラム側からゲームを操作するためのパッド入力を定義するクラス
このうち、2, 3 のクラスに関しては Map Scanner で実装したクラスと全く同一のものになります。 詳細はこちらを参照してください。
以下、「1. ゲーム環境を制御するクラス」のみ解説します。
ゲーム環境を制御するクラス
Item Collector との連携をつかさどるクラスとして base/base_wrapper.py の UE4Wrapper クラスがあります。
個々のゲームに合わせた処理ができるよう、{新規ゲームの名称}/custom_wrapper.py にある UE4Wrapper の継承クラス ItemCollectorEnvWrapper において、以下の関数を適切に変更してください。
- reset(): リセット処理。ゲームを再度起動し、接続を行う
- open(): ゲームの起動を行う
- step(): パッド入力をして、ゲームからの返答を待つ (ゲーム側の処理を 1 フレーム進める)
- step_first():- step()の特殊対応版
アイテム回収時の準備処理の実装
回収テスト時に Item Collector がゲームを操作する処理は、基本的に base/base_thread_main.py の BaseComThreadMain クラスに実装されています。
BaseComThreadMain クラスの実装を確認することで、ゲームを操作してアイテム回収を行う処理の流れを理解できます。
BaseComThreadMain クラスは以下の流れでアイテム回収を開始します。
- (回収テストモードで) ゲームを起動する
- title_menu_setting()を実行して、タイトル画面からゲームプレイ画面に遷移する
- set_debug_function()を実行して、テスト前に必要な設定を行う
- アイテム回収を開始する
- 通常移動での回収に失敗した際は、switch_debug_move()を実行してデバッグ移動モードに切り替える
各ゲームでアイテムを回収を行うには、ゲームごとに以下の処理を実装する必要があります。
- ゲームプレイ画面までの遷移処理
- アイテム回収前の設定処理
- その他の定型処理 (Order)
上記それぞれの処理は、Map Scanner で実装したクラスとほぼ同一のものになります
(ただし、「アイテム回収前の設定処理」は「スキャン前の設定処理」に相当します)。
関数 title_menu_setting() と set_debug_function() の 1 行目、および返り値が少し異なることに注意してください。
詳細はこちらを参照してください。
結果確認時の準備処理の実装
結果確認時に Item Collector がゲームを操作する処理は、基本的に base/base_thread_replay.py の BaseComThreadReplay クラスに実装されています。
このクラスには、経路探索結果に基づき、現在のプレイヤー座標から GUI 上で指定した座標までの移動行うための処理が定義されています。
BaseComThreadReplay クラスは以下の流れで経路探索に基づく移動モードを有効化します。
- (結果確認モードで) ゲームを起動する
- title_menu_setting()を実行して、タイトル画面からゲームプレイ画面に遷移する
- set_debug_function()を実行して、経路探索に基づく移動モードを有効化する前に必要な設定を行う
「アイテム回収時の準備処理の実装」と同じく、ゲームごとに以下の処理を実装する必要があります。
- ゲームプレイ画面までの遷移処理
- アイテム回収前の設定処理
- その他の定型処理 (Order)
ですが、関数 title_menu_setting() と set_debug_function() の 1 行目が少し異なる部分を除いて、「アイテム回収時の準備処理の実装」と全く同じものを使用できます。
キャラクター制御を行う処理の実装
Item Collector のエージェントは、基本的に経路探索で得られたルートに従って移動します。 適切な経路が見つからなかった場合や、探索で得られた経路での移動に複数回失敗した場合は、 自由移動モードに切り替えた上で、直接アイテムの座標まで向かいます。
こうしたキャラクター制御を行うには {新規ゲームの名称}/custom_agents.py > CustomAgent クラスの下記関数を適切に実装する必要があります。
- path_move(): 経路探索で得られたルートに従って通常移動を行うための処理です。
- collect_item(): アイテムの座標に到着した後の回収動作を行うための処理です。
- debug_move_mode(): デバッグカメラモード (自由移動モード) を使った移動を行うための処理です。
実装後は、探索で得られた経路をプレイヤーが上手く移動できているかを確認してください。 移動に失敗するのであれば、コード内のコメントを参考にしながら、自動操作のルールを適切に変更してください。 新しい動作 (例: 中に入っているアイテムを回収するために木箱を攻撃して破壊する) を追加したいのであれば、ステートマシンの構成も変更する必要があります。
各種データファイルの準備
探索データの準備
Map Scanner のソースディレクトリ内にある Python/map_data 以下の各ディレクトリ内に graph_data.bin が存在することを確認した上で、
map_data ディレクトリ全体を Item Collector のソースディレクトリ内にある Python 以下に配置してください。
Map Scanner によるマップスキャンが完了していない場合、Python/map_data ディレクトリは存在しません。
また、map_scanner_searcher.py による事前経路探索が行われていない場合、graph_data.bing は存在しません。
こちらを参照し、先に Map Scanner 側での作業を完了させてください。
ゲーム内マップ画像の用意
実行結果を可視化するためにツール内で表示するゲーム内マップ画像を用意します。用意できたら Python/pic/ 以下に配置してください。
また、画像のファイル名は {マップのコード名}.{適切な拡張子} としてください。
このコード名は Map Scanner で決定したものと同じものを用いてください。
アイテム情報ファイルの作成
こちら を参考に、
テストを行いたいマップ単位で「そのマップ中に存在する全アイテムの情報」を列挙したファイル {マップ ID}_item_list.json を用意します。
このファイルは下記のフォーマットに従う形で作成してください。
{
  "Level": "PL_010VIL", // レベル名
  "TreasureList": [
    // アイテム種別: 宝箱 の全リスト
    {
      "Location": { "X": 14375, "Y": 5335, "Z": -114.37490081787109 },
      "ItemID": "it_firewood_01"
    },
    {
      "Location": {
        "X": 13990.0009765625,
        "Y": 5415,
        "Z": -114.37490081787109
      },
      "ItemID": "it_rune_02"
    }
  ],
  "XXXXList": [
    // アイテム種別: XXXX の全リスト (ゲームに該当するものがあれば)
    // (省略)
  ]
}
ファイルが作成できたら Python/map_data/{マップ ID} 以下に配置してください。
パラメータ設定ファイルの修正
Python/map_data/_map_list.yaml に必要なパラメータを追記します。
以下の手順をテスト対象となるマップ毎に行ってください。
- ツール上のマップ画像にテスト結果をプロットするために、ゲーム内の座標とプロット先の座標を対応させる必要があります。このための 1 次変換係数を map_param_calc.py を用いて計算してください。使い方はリンク先を参照してください。
- 上記リンクにあるように計算結果がコンソール出力されるので、plot_coefficientとplot_biasの値を以下に示すフォーマットに従って追加してください。
- 特定のセーブデータのロードするだけで指定したマップへ移動できるようにします。ゲームのセーブ機能を利用し、プレイヤーがそのマップに存在する状態のセーブデータを作成してください。
- savedataのフィールドに、上記で作成したセーブデータのファイル名 (拡張子なし) を記載してください。
- Nameのフィールドに、マップのゲーム内名称を記載してください。
修正後の _map_list.yaml が以下のようになっていることを確認してください。
map_params:
  { マップID_1 }:
    name: { マップ名称_1 } # 変更する内容
    save_data: { セーブデータ名 (拡張子なし) } # 変更する内容
    x:
      end: 24000
      start: 1000
    Y:
      end: 20000
      start: -10000
    Z:
      end: 6000
      start: -2000
    plot: # 変更する内容
      coef_x: { plot_coefficient の 1 つ目の値 } # 変更する内容
      coef_y: { plot_coefficient の 2 つ目の値 } # 変更する内容
      bias_x: { plot_bias の 1 つ目の値 } # 変更する内容
      bias_y: { plot_bias の 2 つ目の値 } # 変更する内容
  { マップID_2 }: (略)
_map_list.yaml は Map Scanner と共通の設定ファイルです。
詳しい仕様については こちら を参照してください。
item_collector.py の修正
item_collector.py は実行結果を可視化するための GUI を構築するコードです。
利用にあたり、以下の変数を修正する必要があります。
- class GUI- ITEM_TYPE_TABLE: 回収したいアイテムの種類を全て登録してください。 形式は- "アイテムのコード名": ["アイテムのゲーム内名称", 可視化に用いるプロット点の色]です。 可視化に用いるプロット点の色は- (R, G, B, アルファ値)の形式で指定する必要があります。- class GUI上部の定数定義を参考にしてください。