RPGツクールMVのプラグイン開発環境の作り方

海外で話題沸騰のRPGツクールMV([RPGMaker MV](http://store.steampowered.com/app/363890/?l=japanese))ですが、
まだ、日本語版は[ベータテスト中](http://www.spike-chunsoft.co.jp/event/detail/49)とのことです。
今回は、このRPGツクールMVのプラグイン開発環境の作り方を簡単に紹介したいと思います。

この[RPGツクールMV](https://tkool.jp/mv/)のすごい所は、なんといっても、
一回作ったら Windows, Mac, Android, iOS, Webのアプリとして
ゲームを出力する所もそうなのですが、
それよりも今回は、 Node.js で作られていることもあって、
プラグインが作りやすく、 ぶっちゃけなんでもできる！という所が本当にすごい所です。

[こんなゲーム](http://sifue.github.io/SIerQuest/)をすぐ作ってWeb公開することができます。

このRPGツクールは、 Node.jsの [nw.js](https://github.com/nwjs/nw.js) がベースとなっており、
描画エンジンは、[Pixi.js](http://www.pixijs.com/)、両方のAPIをある程度調べれば
普通のデスクトップアプリから、RPG以外のジャンルのゲーム、ネトゲまでも実装可能です。

ではプラグインの開発の仕方を説明してきます。

# 1. プラグインを適用するゲームを作る
今まで通りのRPGツクールの作り方でゲームを作っていきます。
ある程度欲しいプラグインを動作させる下地ができたら完了です。
ここでは簡単なマップだけ作成しました。


# 2. WebKitのディベロッパーツールの起動
ゲームを起動して、F8ボタンを押すことで、ディベロッパーツールを起動できます。
好きな所でブレークポイントを止めたり、プロファイルをしたり、
コンソールで対話的にプログラムでゲームを動かすことすらできます。

ディベロッパーツールは基本Chromeと同じことができますので、
使い方は、[Web開発でよく使う、特に使えるChromeデベロッパー・ツールの機能](http://www.buildinsider.net/web/chromedevtools/01)などが勉強になります。


# 3. 自分が作りたいプラグインのファイルを作る
お好みのエディタ(自分は Visual Studio Codeを利用）で、
次に自分の作りたいプラグインの雛形を作ります。ここでは、`WalkCount` という
名前の歩いた歩数を数えるプラグインを作成します。場所はゲームフォルダの`js\plugins`フォルダです。

```js:js\plugins\WalkCount.js
(function() {
	
})();
```

このようにひな形を用意して、プラグインを追加します。

```js:js\plugins.js
// Generated by RPG Maker.
// Do not edit this file directly.
var $plugins =
[
{"name":"WalkCount","status":true,"description":"","parameters":{}}
];
```

無論、GUIからプラグインをオンにすることもできます。
よくみたらコメントに直接編集するなと書いてありますねw

# 4. フックするポイントを探して実装する
何をしたいのかにもよりますが、ディベロッパーツールを起動して、
ProfileからCPUの動作を記録することで、どこが動いたのかを目星をつけることができます。

Profileタブを起動して、Startボタンを押し、フックしたい動作をした後に、
Stopで、プロファイル結果を見てみましょう。

どうやら、キャラクターが移動するときに呼ばれるのは、`Game_Player.prototype.executeMove`のようです。
それをフックするように実装してみます。

```js:js\plugins\WalkCount.js
(function() {
	var moveCount = 0;
	var _Game_Player_prototype_executeMove = Game_Player.prototype.executeMove;
	Game_Player.prototype.executeMove = function(direction) {
		_Game_Player_prototype_executeMove.call(this, direction);
		moveCount++;
		console.log("moveCount: " + moveCount);
	};
})();
```

これで動く度に、移動距離がカウントされ、開発ツールのConsoleにmoveCountを
コンソールに出力するようになりました。

なおこの書き方は、基本的に提供されているAPIをオーバーライドして
フックする基本的な書き方になります。
`Function.prototype.call()`を利用して、this というclass自体の
プロトタイプのインスタンスを渡して元の関数を実行します。

# 5. ゲームのオブジェクトを好きなように動かす
せっかくなので、10マス歩いたらメッセージを表示するようにしてみましょう。
このRPGツクールMVでは、シーンに紐づく全てのオブジェクトが SceneManager のプロパティから
辿れる他、$から始まるグローバル変数に様々なゲームオブジェクトが保存されています。

また$から始まるグローバル変数は特別で、ここに入っている情報を
描画するメインのループが回収して、様々な動作を行ってくれます。

ここでは、$gameMessage というグローバル変数のオブジェクトにメッセージを追加して
メッセージを表示させてみましょう。

```js:js\plugins\WalkCount.js
(function() {
	var moveCount = 0;
	var _Game_Player_prototype_executeMove = Game_Player.prototype.executeMove;
	Game_Player.prototype.executeMove = function(direction) {
		_Game_Player_prototype_executeMove.call(this, direction);
		moveCount++;
		console.log("moveCount: " + moveCount);
		if (moveCount == 10) {
			$gameMessage.add("I'm very tired...")
		}
	};
})();
```

これで、 10マス歩くと「I'm very tired...」と表示されるプラグインが完成しました。
とっても簡単です！

# 終わりに
基本的にプロジェクトのフォルダ内に全てのJSのソースコードがあり、
読むことで何をしているのかがわかるようになっています。

ヘルプにもいろいろ情報はありますが、
ソースコードを読んだ方がいろいろハックしやすそうです。

また、Node.js で動いているので、基本なんでも作れてしまうのですが、
日本語版がリリースされたあと、面白いプラグインがたくさん出てくれば良いなと思います。

また、[RPGツクールMVのAdventカレンダー](http://qiita.com/advent-calendar/2015/rmmv)もありますのでぜひぜひ参加してみましょう。

# おまけ: エントリーポイントとなるグローバルオブジェクト群
なんとかManagerと$付きのグローバル変数全部。
これ覚えておくと、いろんなことがやりやすいです。

```js
Utils
Graphics
Input
TouchInput
Html5Audio
JsonEx
DataManager
ConfigManager
StorageManager
ImageManager
AudioManager
SoundManager
TextManager
SceneManager
BattleManager
PluginManager
```

```js
var $dataActors       = null;
var $dataClasses      = null;
var $dataSkills       = null;
var $dataItems        = null;
var $dataWeapons      = null;
var $dataArmors       = null;
var $dataEnemies      = null;
var $dataTroops       = null;
var $dataStates       = null;
var $dataAnimations   = null;
var $dataTilesets     = null;
var $dataCommonEvents = null;
var $dataSystem       = null;
var $dataMapInfos     = null;
var $dataMap          = null;
var $gameTemp         = null;
var $gameSystem       = null;
var $gameScreen       = null;
var $gameTimer        = null;
var $gameMessage      = null;
var $gameSwitches     = null;
var $gameVariables    = null;
var $gameSelfSwitches = null;
var $gameActors       = null;
var $gameParty        = null;
var $gameTroop        = null;
var $gameMap          = null;
var $gamePlayer       = null;
var $testEvent        = null;
```