同様の記事はたくさんあるのだが、微妙に情報が古かったりして四苦八苦したので、自分なりに良いと思った方法を共有する。Windows向け。
方針
型の恩恵を受けるのがメイン。
ガッチリファイルを分けてwebpackでバンドルするような開発も可能ではあると思うが、個人的には1ファイル1プラグインの対応がわかりやすく、生成後ファイルも見づらくなくて良い……(と思っている。これは自分の開発が既存プラグインの改造がメインだからかもしれない)。
なので、プラグインの内容は1つのtsファイルで完結させ、それをコンパイルしたらjsファイルが出力されて、それがそのままプラグインとして使える、という状態を目指す。
導入
とりあえずnode.js を導入する。リンク先に飛んで、LTSと書いてあるバージョンのインストーラをDLし、ウイザードに従ってインストールすればよい。
また、今回はエディタとしてVSCodeを使う。別のエディタを使っている人は自分でなんとかなると思うので、適宜読み替えてほしい。DLしてインストールする。
初期設定
好きなフォルダ(デスクトップなど)に作業用のフォルダを作る。名前は何でもよい。
作ったら、VSCodeを開いて、ファイル→フォルダを開く で今作ったフォルダを開く。下の方にターミナルというのが出ていなければ、表示→ターミナル でターミナルを開き、下のコマンドを一行ずつ実行する。
npm init -y # typescriptを使うのに必要。初期設定を自動でやってくれる
npm i -D typescript # typescriptをインストールする。
npx tsc --init # typescriptのコンパイル用の設定ファイルを生成する
編集するソースを入れるフォルダsrc
を作り、ここに拡張子.ts
でプラグインファイルを作る。名前は好きなのにしてください。
また、.jsにコンパイルされたファイルが吐かれるフォルダdist
、後で使うフォルダ@types
を作る。ここまで終わると、フォルダの構成は以下のようになるはず。
ファイル→名前をつけてワークスペースの保存 でデスクトップ等に保存すると、.code-workspace
という、開くと一瞬でこの状態を復元してくれるファイルができる。便利。
package.jsonの設定
フォルダにpackage.jsonというのがあると思うので、それを開き、以下の行を追加する。
"scripts": {
+ "build": "tsc",
},
これでターミナルにnpm run build
と打つとtypescriptのコンパイルをしてくれる。が、いちいち打つのは面倒なので、VSCodeのGUIが便利。
サイドバーのメニュー的なところを右クリックすると、NPM スクリプトという項目が現れる。
これにチェックを入れるとこんな感じのメニューが現れる。
カーソルを合わせると▶ボタンが出現するので、それをクリックすればビルドが出来る。
自動でゲームに反映する設定
プラグインは.jsファイルでdistフォルダの中に生成されるが、これをゲームのプラグインフォルダにいちいちコピペするのは面倒なので、これもコマンドに含めてしまいたい。
まずはターミナルで
npm i -D cpx
を実行する。次にpackage.jsonに次の行を追加する。
"scripts": {
"build": "tsc",
+ "build2": "tsc && cpx dist/[ファイル名].js [ゲームのフォルダのパス]/js/plugins"
},
これで build2
を実行すればコンパイルと生成ファイルのゲームへの反映を両方やってくれる。build2はあんまりな名前なので、好きな名前にしてください。
tsconfigの設定
tsconfig.jsonというファイルをちょっと編集する。初期状態だとファイルのほぼすべてがコメントアウトされているので、必要なプロパティだけコメントアウトを解除する。
strict周りはわかる人は好みの設定にしてください。
"compilerOptions": {
"target": "es2018",
"module": "ESNext",
"outDir": "./dist",
"strictPropertyInitialization": false,
"strictBindCallApply": false,
}
- targetはES2018。これは、ソースが古い環境でも動くように、自動でコードを書き直してくれる機能。ツクールMVはes2019以上の新しい機能が使えないため、ES2018に書き直されるように設定する。これより古いぶんには問題がないが、生成後のソースが見づらいだけなのでおすすめできない。
- moduleはESNEXTがよいと思う。
export
関連の変なコードがくっついてこないため。 - outdirはコンパイルしたファイルをどこに出力するか。先ほど作ったdistフォルダを設定する。
-
strictPropertyInitialization
はクラスのコンストラクタで未定義を許容するオプション。ツクールMVのソースはclass
を用いて書かれてはいないため、typescriptにコンストラクタでのプロパティ未定義を怒られる事がある。それを黙らせる。typescriptの堅牢性を緩める行為なので、採用はお好みで。 -
strictBindCallApply
はFunction.call()
やFunction.apply()
にargumentsを使うためのオプション。typescriptのarguments
は型が緩いため、callやapplyで厳密に型チェックをさせると怒られる。それを黙らせる。typescriptの堅牢性を(ry
ツクールMVのコマンドの型定義
RPGツクールは基本的にグローバルにゲームに使用するいろんなものを生やしていて、それらの動作を上書きすることでプラグインを実現している。型定義については、素晴らしき先駆者様が公開してくださっているので、これを活用しよう。以上。
https://github.com/Narazaka/rpgmakermv_typescript_dts
……と言いたいところなのだが、///<reference>
の記述が必要だったり、定義が誤っていたときに修正できなくて面倒だったりと、ちょっと使いづらいので、カスタマイズする。
まずは上のリポジトリのとおりに次のコマンドを実行する。
npm install rpgmakermv_typescript_dts
次に@types
フォルダを作り、node_modules\rpgmakermv_typescript_dts\typings\rpgmakermv\rpgmakermv.d.ts
をコピーする。
そうしたらコピーしたファイルを開き、
- 2行目
/// <reference path="../lib/lib.dom.d.ts" />
は消去してよい。 - すべての
declare
を消去する。 - ファイル全体を
declare global{}
で囲う。 - ファイル末尾に
export {}
を記述する。
こうすることで快適に型が効くようになる。
型定義の書き換え
場合によっては型定義を書き換えなければならないこともある。この型定義だと$gameVariablesはnumberしか扱えないようになっているが、他の型の値を扱えるようにするにはrpgmaker.d.tsを次のように書き換える。
class Game_Variables {
constructor()
initialize(): void
clear(): void
- value(variableId: number): number
- setValue(variableId: number, value: number): number
+ value(variableId: number): unknown
+ setValue(variableId: number, value: any): number
onChange(): void
_data: number[]
}
unknown型の値をそのまま使おうとするとエラーになるので、使うときは次のようにして、型を絞り込んであげるとよい。
let someParam = $gameVariables.value(1) as string
まとめ
ここまでの設定ができれば、typescriptでプラグインを開発し、npmタスクランナーからbuild2
を行うことでプラグインがゲームに反映される、という流れが出来ているはず。良きツクールライフを!
豆知識
StorageManagerというデータを保存するクラス(環境に合わせてlocalStorageとファイル保存を使い分けてくれるっぽい)があるのだが、これがなんとJS側のStorageManagerと完全に名前が一緒で、サジェストをしてくれない。どうにかならんかなあ。