RPGツクールMV　コミュニティ版コアスクリプト解説

RPGツクールMVのコアスクリプトとは、ゲームの本体にあたるスクリプトのことを指します。ゲームエディタ（マップを作ったりするソフト）は含まれません。現在、RPGツクールMVの[コミュニティ版コアスクリプト](https://github.com/rpgtkoolmv/corescript)が開発されています。オープンソースですので、英語を使えれば誰でも開発に参加できます。（日本語で不具合報告したい場合はRPGアツマール運営のTwitter(nico_indiesgame)へどーぞ）

この記事ではリリースノートの短い文章では説明しきれない事柄や新機能を１００％活用する方法などの耳寄り情報をちょこちょこ書いていこうかと思います。

# 本家「RPGツクールMV」との関係

コミュニティ版は、オープンソースプロジェクトとしてRPGツクールMVのコアスクリプトをより良くする（例：バグ取り、ブラウザの変化に対応、高速化など）ために開発しています。ある程度開発が進むと、[RPGアツマールお知らせブログ](http://blog.nicovideo.jp/atsumaru/atsumaru-corescript.html)からコミュニティ版がリリースされます（これが「アツマール版」と呼ばれることもある理由です）。そしてコミュニティ版で開発されたコードは最終的に本家「RPGツクールMV」に反映されることを目指していますので、コミュニティ版を本家の「先行版」と捉えることもできます。

コミュニティ版はご自由にご自分のゲームに使って頂けますので、本家に反映されるのを待たずとも遠慮なくご利用下さい！！また、コミュニティ版を使った際に発生した問題点などはじゃんじゃん報告してもらえると、より完成度が高まります！

## 本家版への取り込み実績

コミュニティ版のバージョン1.2cが本家版のバージョン1.5.0として取り込まれました！！

現在のコミュニティ版最新バージョンは1.2cですので、本家1.5.0以上のスクリプトをコミュニティ版にアップデートするメリットは特にありません。

# 1.1

1.1と、そこで新たに発生した不具合を修正した1.1bがあります。基本的にはそれぞれのリリースノート（[1.1](http://blog.nicovideo.jp/atsumaru/download/community-11.html)、[1.1b](http://blog.nicovideo.jp/atsumaru/download/community-11b.html)）に書いてありますので、それと合わせてお読み下さい。

## プリロード

ゲーム中で使われる画像を先読みするプリロードシステムが導入されました。それぞれのマップイベント、コモンイベント、バトルイベントの開始時にそのページのイベントコマンドを解析し、「ピクチャーの表示」などの画像を用いるコマンドがあった場合、先に画像の読み込みを開始します。（実装箇所は`Game_Interpreter.requestImages`）

```:会話イベント
◆文章：なし, ウィンドウ, 下
：　　：こちらの文章を表示している間に、
：　　：裏でbig_pictureとHit1とDarkness4を読み込んでるよ！
◆ピクチャの表示：#1, big_picture, 左上 (48,0), (100%,100%), 255, 通常
◆アニメーションの表示：プレイヤー, 打撃/物理（←内部でHit1とDarkness4を使用）
```

一方で、プリロードはあくまでイベントの開始時に、そのページに限ってのみ行われます。（ただし「コモンイベントの呼び出し」についてだけは気を利かせて呼び出し先もプリロードします）従って、以下のように真っ先に大きな画像を表示するパターンでは結局間に合わない可能性が高いです。

```:会話イベント２
◆ピクチャの表示：#1, big_picture, 左上 (48,0), (100%,100%), 255, 通常
◆文章：なし, ウィンドウ, 下
：　　：上の絵の読み込みは間に合わない可能性が高いね＞＜
```

### プリロードシステムを活用する

既に実装をご覧になった方なら気づいたかもしれませんが、これらのプリロードシステムは`ImageManager.requestXxxxx`の形でプラグインやスクリプトなどから簡単に実行できます。例えば先程のようにイベントの先頭に大きな絵の表示がある場合で、演出の都合上どうしても遅れずに表示したい場合には以下のように別のイベントからスクリプト経由でプリロードを呼び出してしまいましょう。

```:別のイベント
◆スクリプト：ImageManager.requestPicture('big_picture');
```

言うまでもなく、この「別のイベント」は「会話イベント２」よりも先に実行されている必要があります。会話イベント２が町の人などの場合、マップに入った辺りで自動実行しておくのが良いでしょう。

---

また、プラグインを使ってプリロード機能を拡張するという活用法もあります。現在の機能ではあくまで各種のイベントコマンドに対してしかプリロードしません。例えば戦闘中の通常攻撃、スキル使用のアニメーションなどはプリロードの対象外というわけです。これは、使うかどうかもわからない画像を大量に先読みしてユーザーの通信回線に過度な負担をかけられないという倫理的な判断です。

しかしながら、実際に遊んでみるとわかりますがアニメーションを初めて表示する際は結構読み込みで待たされます。テンポ感を重視する人にとってはこれは致命的でしょう。そこで戦闘開始時にアクターの持っている通常攻撃とスキルを検索して、それをプリロード（`ImageManager.requestAnimation`を使用）するプラグインを作ればこの「待ち」を改善することができます。

ツクールのコアそのものにプリロード機能が備わったことで、それぞれのゲームの画像先読み需要に柔軟に応えられるようになったことは大きな変更点だと思います。ガンガン利用していきましょう！

## メモリ管理

ツクールMVにメモリの管理機構を導入しました。今までは画像を一度メモリに読み込むと永遠に溜め込むシステムになっていたため、特にメモリの上限が低いモバイルデバイスで長時間プレイしているとメモリが満杯になって落ちてしまうことがありました。

そこであらかじめ画像溜め込みの上限値を`ImageCache.limit`に定め、それを超える量の画像が読み込まれたときは古いものから順に管理機構から追い出すようにしました。デフォルトの上限値は相当余裕を見て低めに設定されているので、例えばPC向けゲームならパフォーマンス重視でこの上限値を引き上げても良いかもしれません。

**※設定値の目安については[画像キャッシュ上限値](#画像キャッシュ上限値)の項目をご覧ください**

## WebGL化

モバイルデバイスでのツクールの動作をWebGLモードに変更しました。PixiにはcanvasモードとWebGLモードがあり、基本的にはWebGLの方が高速かつ高品質な描写が出来るのですが、今まではモバイルデバイスに対してcanvasモードを強制してきました。

その理由は、前節のメモリ溜め込み問題です。実は、canvasモードは多くの点で性能が低いですがメモリ管理にしてはむしろ賢く、メモリが溢れにくいという利点があったようです。（詳しくは[liplyさんの記事](http://qiita.com/liply/items/f98807edb62f2d178669)をどうぞ）

今までは「メモリ溜め込み問題」を「モバイルデバイスでcanvasモード強制」によって概ね押さえ込んでいたわけです。ですが、前節のメモリ管理機構のおかげでもうその必要が無くなりました。（というか、高速なWebGLを使いたくてメモリ管理を導入したというのが正しいです）

WebGL化により、特にAndroid端末で大幅な動作の高速化が期待されます。

### WebGL統一

**※統一などと言っていましたが、1.2でcanvasとWebGLを自動判別するモードに戻しました。詳しくは[レンダリングモードの自動選択](#レンダリングモードの自動選択)の項目をご覧ください**

早くなります、だけでは何なのでここで耳寄り情報を。今までもPC向けには既にWebGLモードで起動されていましたが、今回モバイルデバイスでもWebGL化されました。…つまり、ツクールの動作がほぼ（←※追記予定）**WebGLで統一された**ことになります。

これが何を意味するかというと、**WebGLを用いた演出が解禁される**ということです。もちろんツクールにその手の演出はありませんが、プラグインでそのような演出を加えることは可能です。そして実際、そのようなプラグインはいくつか存在しました。（例：水中のように画面を歪ませる、戦闘開始時に画面を割るなど）

この手の画面演出系のプラグインはゲームの雰囲気を一挙に変える大変かっこいいものなのですが、WebGLの機能を使っているためWebGLモードでしか動かない、というものが多くありました。そして今まではモバイルのツクールがcanvasモード強制だったので「スマホ向けを考えると実質このプラグインは使えない…」という悲しみを背負っていました＞＜

しかし今ではモバイルもWebGLですので、この手のかっこいい演出系プラグインが復活することができます！またプラグインの作り手としてもWebGLを用いた新たなプラグインを作って遠慮なく公開することができます。よって、これからツクールゲームの演出は一段とレベルアップしていくのではないでしょうか！楽しみです！！

## フォントの読み込み改善

低速回線下でしばしば報告されていたFont load errorを改善しました。具体的にはフォント読み込み待ちを20秒から60秒に伸ばし、さらにCSS font loadingに対応しているブラウザではフォントがロード出来るまで無限に待ちます。ついでに[Chromeでフォントが混ざる問題](http://ch.nicovideo.jp/indies-game/blomaga/ar1181695)を解消するという一石二鳥。

## 「ムービーの再生」改善

全Android端末で動画が再生できない問題を修正しました（！！）。モバイルデバイスでは動画を再生する時にタッチ操作で始めないと行けない、というルールがあるのですが、これへの対策コードがiOS用のは書かれてるのにAndroid用のは全く書かれてなかった…これでもう「スマホで動画流れない」とかコメントされまくってわざわざ動画ありルートとなしルートを別に用意する日々からはおさらばです！

なお、「ムービーの再生」コマンドが終わるまで次のイベントコマンドに進行しないように統一しました。今まではデバイスによってその辺の挙動が違ってたのです、なんてこったい＞＜

## 不具合修正

「ピクチャの消去」時にまれにエラーが出るバグや、iOS8で全くゲームが動作しなくなっていた不具合（！？）など数々の問題を修正しています。ブラウザのバージョンアップにより不具合が増えることもありえますので、1.2以降も不具合対応は優先的に行います。

## 内部構造解説

この節では今回特に大きな改変であるプリロードとメモリ管理の内部構造を解説してみます。コアスクリプトそのものに興味が無ければ読まなくても大丈夫です。（需要があるか怪しいので最後に回しました）

### プリロード構造

**RequestQueue**

`ImageManager.requestXxxxx`でプリロードを予約しますが、これは一度`RequestQueue`に貯められ、一件ずつ順番にプリロードを実行していく仕組みになっています。なぜか？プリロードはあくまでゲームを快適にする要素であって、あくまで最重要は`ImageManager.loadXxxxx`で**必要な時に**読み込まれる画像です。従ってプリロードは同時に一件までに絞って通信回線を温存しているのです。

### メモリ管理構造

**ImageCache**

画像のキャッシュ（溜め込み）機構の本体がこの`ImageCache`です。先に述べたように`ImageCache.limit`で定義された上限値までは画像をそのまま溜め込み、上限値を超えだすと古いものから順にメモリから排除していきます。ただし、下で説明する**リザーブされた**画像は排除されません。

他に、プリロードされてるだけの画像は**まだ必要な時でない**ので真っ先に排除されます。「いや、排除されたらプリロードした意味ないじゃん！」…大丈夫です。ブラウザが賢くその画像を保存しておいてくれます。あくまでプリロードの目的は「インターネットから画像をダウンロードしておくこと」です。メモリに展開しておくことではありません。

**ImageManager.reserveXxxxx**

このメソッドでは単に画像を読み込むだけでなくそれをキャッシュに**リザーブ**しておくことができます。リザーブされた画像は排除の対象外となります。キャッシュに残し続けることが前提となるシステム系の画像（とdrawFace,drawCharacterの対象画像)などで用いています。乱用は上限値圧迫の元なので基本的にツクラーの皆さんが使うのは避けたほうが良いでしょう。なおリザーブにはreservationIdが必要で、対応するreleaseReservationによりリザーブを解除することができます。

# 1.2

1.2と、そこで新たに発生した不具合を修正した1.2b、また修正しつつ便利なプラグインを追加した1.2cがあります。基本的にはそれぞれのリリースノート（[1.2](http://blog.nicovideo.jp/atsumaru/download/community-12.html)、[1.2b](http://blog.nicovideo.jp/atsumaru/download/community-12b.html)、[1.2c](http://blog.nicovideo.jp/atsumaru/download/community-12c.html)）に書いてありますので、それと合わせてお読み下さい。

## 読み込みリトライ機能

リトライの対象となるのは画像、音声、動画、マップデータ(Map001.jsonとか)です。これらの読み込みに失敗した時は、まず数回、時間を空けて「自動読み込みリトライ」が行われます。その数回のリトライがすべて失敗した場合、ローディングエラー（ファイル名とリトライボタン付き）を画面に表示します。

このローディングエラーは通常のものと違い、真ん中のリトライボタンを押す（または決定キーを押す）ことによって手動で再読み込みが可能です。これに成功すると、なんとゲームに復帰することができるのです！今までのツクールMVでは「え？一つ読み込みミスった？…エラーです、ゲーム終了！セーブしてなかったら…最初からッ！」みたいな硬派すぎる仕様でした。なので移動中にスマホで遊ぶ時は電波が途切れないように大変気を使いましたが、これからは安心して遊べますね！

なお、コアスクリプトはファイルが本当に存在しないかどうかを判別できないので、ファイルが全く存在しない場合でもリトライボタンは常に表示されます。例えばテストプレイでリトライボタンが出た場合、ネット回線は関係ないわけですから、単なる画像指定のミスであると思われます。この点はご注意下さい…！

## レンダリングモードの自動選択

canvasモードとWebGLモードの選択を、「WebGLが使える場合のみWebGLモード、そうでなければcanvasモードとする」自動選択(auto)モードにしました。これは、MVの動作対象であるAndroid4.4系列の一部端末の中にWebGLモードに対応していない機種が存在することがわかったためです。

さて、autoモードに戻るということは今までと同じ状態に戻るのでしょうか。…いいえ、それは違います。autoモードに戻してもなお「モバイルデバイスでのcanvasモード強制を解除した」という1.1の変更は残っています。多くのAndroid端末はWebGLモードによる高速化の恩恵を受けられますし、WebGLを用いた演出を見られる端末も大幅に増えています。

WebGL限定のプラグインを使うなどで特定のモードでの動作が必要な場合は、後述のベーシックプラグインでレンダリングモードを固定するのも一つの手だと思います。

## マスターボリュームAPI

`AudioManager.masterVolume`に数値（最小値:0,最大値:1,初期値:1） を代入することで、すべてのBGM,BGS,ME,SE,ムービーの音量を一括で変更できるようになりました。マスターボリュームの名の通り、個別の音量やオプションの音量などがすべて計算された後で最後にマスターボリュームの値が音量に掛け算されます。

とはいえ、この機能はコアスクリプト内では最大値の1に固定されており、事実上使用されていません。じゃあこの機能は何だ、ということですが実はこれはゲーム投稿サイトのように、ツクールゲーム音量を一括で管理したい人に向けたメタ的な機能なのです。…そういうことですので特に狙いが無いならいじらずに放っておくことをおすすめします。

## ベーシックプラグイン

Community_Basic.jsは、1.2cで追加されたパラメーター設定用のプラグインです（本家ver1.5.0にも同封されました）。画像キャッシュ上限値や画面サイズ、レンダリングモードや常時ダッシュの初期値を設定できる便利なやつです。

### 画像キャッシュ上限値

画像キャッシュ上限値は、デフォルトでは`10`となっております（単位はMPixel）。RPGツクールMVは色んな環境で動作することが考えられますので、動作対象範囲内で最もメモリのないモバイルデバイスで十分余裕がある最低限の値に設定されています。

しかし、画像キャッシュというのはメモリに画像を展開しておけるわけですから、上限値が高いほど高速にゲームを動作できることは間違いありません。[武藤さんの記事](http://wargame.jp/wgbl/%E3%82%B2%E3%83%BC%E3%83%A0%E8%A3%BD%E4%BD%9C/rpg%E3%83%84%E3%82%AF%E3%83%BC%E3%83%ABmv%E3%81%AE%E8%BB%BD%E9%87%8F%E5%8C%96%E5%AF%BE%E7%AD%96%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/)ではＰＣ向けのゲームを作成する時の上限値として`30`という値が設定されています。スマホでプレイしてもらうことを考えない場合、この値が一つの目安になると思います！

極論ですが、高速動作を最優先して画像をすべてメモリに溜め込む場合は`Infinity`（無限大）という値を設定することもできます。もちろんこの場合は、メモリ管理機能の導入以前と同様に「いつゲームが落ちるかわからない」という危険な状態であることは忘れないでください！

## 不具合修正

今回もたくさん修正されました（詳しくはリリースノートを参照）。特にAndroidのChromeでゲームを遊んでいる時にスワイプしてもページがスクロールしていかないようになったのが大きいと思います！

## 内部構造解説

### 画像メモリ節約

リリースノート上での説明は地味ですが、メモリ節約と高速動作に大きな影響を与えたのが1.2の「画像メモリ量節約」です。

**Bitmap**

Bitmapの内部構造は1.1でメモリ管理とプリロードの実現のため一度大きく変わっています。1.2では、さらにメモリを節約するため必要にならない限りは内部でcanvasを持たないように変更しました。今まではImageインスタンス（this._image）へ画像を読み込むとその後にcanvas（this._context）へもれなく書き出していたため、事実上メモリを２倍圧迫している状態でした。

しかし、実際のところ色替えや切り出しなどの機能が必要無い限り、canvasへの書き出しは必要ありません。また、ピクチャーや遠景などのメモリを圧迫する大きい絵ではそういった機能を用いないので、これらをcanvasへ書き出さないことでメモリを大幅に節約できたのです。

### リトライ構造

**ResourceHandler**

`ResourceHandler.createLoader`というメソッドに再読み込み用のretryMethodと読み込み完全失敗用のresignMethodを投げると特殊な「リトライメソッド」が生成されて帰ってきますので、これをリトライの対象となるデータのonerrorなどのエラーハンドラに設定すると「リトライ化」できます。

これは、失敗してから３回の「自動リトライ」（リトライまでの間隔はそれぞれ0.5秒、1秒、3秒）を行い、３回とも失敗したらローディングエラーとリトライボタンを画面に表示し、待機します。リトライボタンが押されると`ResourceHandler.retry()`が起動し、再び読み込みが開始されます。この時、リトライ回数はリセットされていますのでもし失敗したら再び３回の自動リトライを挟んでから、ローディングエラーとなります。

# 1.3

開発中です。あなたもぜひ参加してください！