Constructは簡単にゲームをセーブする方法を提供しています。プレーヤーはゲームデータをセーブすることで、次にプレイするときに最後の状態から始めることができます。レベルやステージがたくさんある長編ゲームなどでは特に重要でしょう。もちろんWebStorageを利用して、ごく簡単な”最後のレベルをセーブする”等の保存はできますが、全てのオブジェクトの最後の状態を保存するのは難しいといえます。システムオブジェクト[2]のSaveとLoadアクションはまさにこのためにあり、最小限の労力で高機能なデータセーブ機能を実装することが可能です。
基本的なデータセーブのサポート
ゲームにセーブ機能を加えるもっとも簡単な方法は、特定のキーが押された時にSaveもしくはLoadアクションを実行することです。
ここではわかりやすく説明するためにデスクトップゲームを使用します。モバイルゲームの場合は当然画面のどこかにタッチできるボタンを設置することになるでしょう。
データはブラウザによってディスクに保存されます。このためプレイヤーは一旦コンピューターもしくはデバイスをオフにし、翌日戻ってきたとしてもデータをゲームに問題なくロードすることができます。ただしデータはブラウザ毎に保存されるので注意が必要です。例えばFirefoxとChromeはそれぞれ別々にデータをセーブしますから、Chromeを使ってセーブして次にFirefoxに切り替えたとしてもデータはうまくロードしません。
ゲームのデータはブラウザのキャッシュには保存されません。ブラウザのキャッシュは極めて短期的なもので、ページやイメージを何度もダウンロードしなくて済むようにブラウザが保存しますが定期的にクリアされることがあります。幸運にもゲームのデータはキャッシュには保存されません。より永続的な保存領域であるWebStorageもしくはIndexedDBに保存されますからユーザーがブラウザのキャッシュをクリアしても影響はありません。
保存スロットについて
ユーザーが複数のデータを保存できることが好ましい場合があります。このために保存スロットがあります。スロットはファイルのように別々にデータを保存します。あらかじめ用意した複数のスロットをユーザーに提示したり、名前をつけて保存できるようにさせたりもできます。
多くのブラウザは1つのwebページが利用できるストレージに制限を設けています。ほとんどのゲームでは問題にはならないでしょうが、もし保存スロットを多く利用する場合には問題になる可能性もあります。上限を定めたスロットを提供することによって問題を回避するのが最も好ましいでしょう。後ほど詳しく解説しますがNo Saveを使うことによってデータをできるだけ小さくするやり方もあります。
完了を示すトリガー
保存には時間がかかる場合がありますが、その間もゲームは実行しつづけています。保存が完了したら、システムはOn save completeトリガーを呼び出します。同様に、読み込みも時間が掛かる場合があります。この際はOn load complete が呼び出されます。Saveアクション呼び出し後で、なおかつOn save completeトリガー以前に起こった変更も、保存されることに気を付けましょう。
まだ何も保存されていないスロットからロードしようとすると、On load failedトリガーが発生します。単にユーザーがゲームを始める目的で保存スロットを選んだのであれば、この場合は新しいゲームを開始するだけでよいでしょう。
'No Save' 動作
No Save動作をもつオブジェクトは何も保存されず、ロードする時も影響を受けることはありません。No Save動作は、風景や背景などの静的オブジェクトに追加することをお勧めします。Tickの度に自動的に更新されるような、例えばHUDやテキストオブジェクト、などにも使えます。これはゲームに影響を与えることはありませんが、不要な情報を省略するので、保存データをより小さくし、保存と読み込みを高速にします。(またこれはcontinuous preview[5]が正しく動作するために必要です)
データが保存された後のプロジェクトの変更
セーブデータは、プロジェクトの内容の変化に対して堅牢であるべきです。変数、動作、およびその他のオブジェクトが、追加、削除、もしくはその順序の変更をされたとしても、以前に保存されたデータの読み込みは成功するべきです。ただし何か新しいものを追加した場合は、そのためのデータは保存されていないので、ロードするときには無視されます。逆にプロジェクトから何かを削除した場合は、データを再度読み込むことができなくなりますから注意してください。個々のインスタンスを削除してもセーブデータに影響を与えませんが、レイアウトまたはレイヤーを全体として削除した場合はセーブデータから再度読み込むことはできなくなります。
上級者向けトピック
ここまでの内容を利用して、ほとんどのゲームにセーブデータ機能を簡単に追加することができます。ただし上級者中は、セーブデータ・システムについてさらに詳細に説明している、以下のトピックを読み進めると良いでしょう。
使用スロットの追跡
システムの保存/読み込み操作は、どのスロットに保存されているかを示してはくれません。これを追跡するための最良の方法は自分で WebStorage オブジェクトにいくつかの余分なメタ・データを格納するやり方です。たとえば、スロットを保存するたびに、どのスロットに保存されたかが分かるようなキーを WebStorage に一緒に記述する方法があります。プレイヤーの名前やゲームの小さなスクリーン・ショットなどのようなメタデータを、データURIとして追加することも出来ます。そうすることで、WebStorageがどのスロットにデータを保存したか分かるようになります。また、メタ・データのキーを書き換えたり削除することで簡単にリセットやデータのクリヤーを実装することができます。
何が保存され、何が保存されないか
インスタンス変数、グローバル変数とローカル変数、動作のプロパティ、効果、粒子、現在再生中のオーディオなど - を含むゲームの完全な状態が保存されます。しかし、いくつかの例外がありますが、どれも驚くべきことではない、そう願います。次のものが保存されず、ロードするときにも影響を受けません。
- 入力の状態 (マウスの位置、すなわちまたはプレーヤーを持っていたかどうかのキーに触れる)
- AJAX 要求
- WebSocket 接続
- XML オブジェクト
- ユーザーのメディア、ビデオまたはオーディオのフィード
- Facebook のログイン
- WebStorage の状態
- CocoonJS/Windows 8 の状態
- 任意のプラットフォーム上の任意のアプリ内購入に関する情報
- 'No Save' 指定されたもの
JSONデータを直接使用する
On save completeおよびOn load completeトリガーの発生時に、システムの SaveStateJSON 表現を用いてセーブデータのためのすべてをJSON書式で得ることができます。これらのトリガーの発生時以外の際に SaveStateJSON を用いても空の文字列しか得ることができないことに注意しましょう。この二つのトリガー発生時が、データに直接アクセスする唯一の機会です。
あなた自身のサーバーがある場合は、ゲームのJSONデータを、AJAXオブジェクトを利用してサーバーへ送信し、サーバーのデータベースに格納することで、セーブデータを共有することが可能です。また Windows 8 や Clay.io など、ログインしているユーザーのデータを格納する機能を提供しているプラットフォームを利用すれば、ユーザーがどこでログインしてもデータを共有できるようになります。つまりユーザーがどこに行ってもセーブデータにアクセスできるようになるわけです。
一旦 JSON 文字列を取得すれば、Load from JSON システム・アクションを用いてゲームを読み込むことができます。
バージョン管理
大抵の場合、プロジェクトを変更しても、古いセーブデータは問題なく読み込まれます。しかしユーザーによってはプロジェクトのバージョンとセーブデータがどこから来ているかを正確に追跡したいかもしれません。これにはグローバル変数を使用して行う方法があります。例えば、Versionと名付けた変数を用意し、値を1として初期化します。後に、あなたのゲームの新しいバージョンを発行する時に、その変数の初期値を2などの新しい数字に変更します。そして、On load completeトリガーのタイミングでグローバル変数に値が読み込まれます。この値はSaveアクションが実行された時点でのバージョンの値です。これは、ゲームに多くの新しいオブジェクトを追加したプロジェクトなどで、古いセーブデータを読み込むときに、それら新しいオブジェクトを破壊したり非表示にしたりする際の確認に役に立ちます。