はじめに
誤解の無いように最初に書いておくと、デスクトップとかウィンドウのキャプチャじゃないです。
tmlib.js で表示しているゲーム画面と言うか canvas のキャプチャ。
これがあるといろいろ便利に使える場合があるかと…
例えば、ゲームのセーブ時に画面を保存して、それをロードする時に表示してどんなセーブデータだったかわかりやすくする。
とかって、言うのはよくある。
そんな方法を考えてみた。
具体的に必要になったのは、結局また各種データのロード処理。
AssetManager って形でいろいろロードできるように、ロードしたものを管理できるようになってるのだけど、
Web上でRPGをやろうと思った場合、全部のデータを、最初にロードって言うのは、現実的では無いなぁ~と。
なので、必要になったら読み込むようにする。
ディスク読み込みじゃないけど、ネットワークからの読み込み処理。
tmlib.js にも LoadingScene クラスがあって、AssetManager の load をしてくれるけど、
見た感じ、事前に読み込むものがわかってる場合には、そのまま使える感じ。
tmlib-rpg では、どうしても、マップデータの json を読み込むと、それに関連して、中で使われている
イベントとかキャラクターとか、アイテムの画像とかデータとか、もういろいろ必要で、事前に読み込ませるのがつらい。
マップに表示するキャラクターは、マップデータの json を読むまでわからないとか云々…
(全部事前に用意するんだから、頑張ればできないことないけど…)
と、いうわけで、できるだけ直前まで読み込みを遅らせる。
イメージ的には以下のような感じ
displayEvent: ->
unless @image?
AssetManager.load(@event.image)
@image = AssetManager.get(@event.image)
drawImage @image
あくまでイメージです。
イベントを表示する場合に、その直前でロードして使う。
実際に、やってしまうと、非同期で読み込むので、イメージが表示できないです。
onload を使って表示処理自体を、ロード後にすることもできるけど、それ以降の処理を全部同期させると言うのは、現実的じゃないし、全部の箇所でそれをするのもいろいろ大変そう。
と、言うわけで、今処理しているシーンから、ロードシーンに移して、ロードしたら
また元のシーンの処理へ戻る。と言う感じの方法で対処することに。
この時、ロードシーンには、黒背景でロード用のアニメーションとかで表示するのもいいのだけど、
rpg のマップとかの場合は、少しグレイアウトして、マップを表示しつつ、その上にロードのアニメーションを表示したいかな~と
いうことで、このキャプチャをしたくなったのです。
ふ~。前置きながいながい。
ロードシーン
tmlib.js には、もともと、シーンを一時的に変える、push/pop でのスタック的なシーン切替があるんだけど、ロード中に、プレイヤーとか操作できたら困るなぁ~とか、NPCが勝手に動いてもな~とか…(裏に表示されるマップの処理的に)update とか draw の処理どうなっちゃうんだろう~?とか、思ったので…
普通に、シーンを置き換えて、ロードしたら置き換えなおす感じにしました。
これなら、tmlib.js 自体には手を入れなくてもできるし。
で、それとは別に、今表示している画面をキャプチャするメソッドを作って、ロードシーンには、キャプチャしたビットマップを渡してそれを背景として使うようにする。
機能的には2つ。キャプチャとロードシーンは、別々です。
こうやって分けておけば、好きなビットマップにしたり、特定のシーンでのキャプチャーを利用したりできるかな~と。
以下のような呼び出し方法になりました。
もうちょっとリファクタリングして、いろいろ整理したい部分が多いけれど…
# 現在のシーンをキャプチャー
rpg.system.captureScreenBitmap()
# アイテムをロード
rpg.system.db.item(['001','002'],(items)->
console.log items
)
rpg.system.db がDataBaseインスタンス
# アイテムデータ
item: (items,func) ->
assets = (@itemUrl(item) for item in items)
onload = () ->
items = []
for asset in assets
data = tm.asset.Manager.get(asset).data
data.item = asset
@items[data.item] = data
type = data.type ? 'Item'
items.push new rpg[type](data) if rpg[type]?
func(items)
@loadAssets assets, onload.bind @
# スクリーンビットマップ保存
captureScreenBitmap: () ->
@temp.screenBitmap = @app.canvas.getBitmap()
# Assetロード
loadAsset: (assets, callback=null) ->
@loadScene
scene: rpg.system.scene # 次に表示するシーンを、現在のシーンへ
assets: assets
callback: callback # ロードしたら呼ばれるコールバック関数
# シーンロード
loadScene: (args={}) ->
args = {
bitmap: @temp.screenBitmap # 表示用の bitmap に画面キャプチャを設定
}.$extend(@loadingSceneDefault).$extend(args)
rpg.system.app.replaceScene SceneLoading(args) # ロードシーンへ切り替え
SceneLoading では、bitmap を表示する。
オチ
と、いろいろ、こうやって作って動くようになったのだけど、最新の tmlib.js 実装(develop)では、pushScene を使ったときに画面をキャッシュしてくれるとか!
これでいいじゃ~ん。と言うことが、わかりました。
なので、最新版にバージョンアップして、この辺は、全部 tmlib.js まかせになる予定です^^