Spriteは少ないほうが良い
よくゲームエンジンのパフォーマンス比較でスプライトを増やしてFPSを計測していることからも分かるように、スプライトが増えればその分計算が増えるのでパフォーマンスは落ちる。つまり、古い端末でも十分滑らかに動くことを意図するならスプライト数は減らすに限る。特にWebブラウザ上で動くことを想定しているcocos2d-jsでは重要になる。
cc.RenderTexture
例えばアクションゲームの背景がオブジェクトの組み合わせで表現されるとき、ステージごとに背景を替えたい場合、パフォーマンス的には予め合成された画像を持っておくのが有利だが、容量的には不利だ。
これを解決する一つの方法が、RenderTexture
である。
cc.RenderTexture()
cc.RenderTexture is a generic rendering target. To render things into it,
simply construct a render target, call begin on it, call visit on any cocos
scenes or objects to render them, and call end. For convenience, render texture
adds a sprite as it's display child with the results, so you can simply add
the render texture to your scene and treat it like any other CocosNode.
There are also functions for saving the render texture to disk in PNG or JPG format.
cc.RenderTexture | JsDoc Reference
ざっくり言えばスプライトを組み合わせた大きな画像を内部的に作ってしまうようなもの。
使い方
- cc.RenderTextureをサイズ指定して作成
- これからRenderTextureに焼き付ける事を
begin
で宣言する - 焼き付けたいSpriteを配置する
- Spriteのメソッド
retain
を呼んで焼きこむSpriteであることを宣言する - Spriteのメソッド
visit
を呼んで焼き付ける - Spriteのメソッド
release
を呼んで解放する - 3から6を焼き付けたいSpriteの分だけ繰り返す
- RenderTextureへの焼き付けが終わった事を
end
で宣言する
retainとかreleaseとかはC++版のcocos2dやってないとわかりづらいと思う。
var rt = cc.RenderTexture.create(320,240);
rt.begin();
var sprite;
for(var i=0;i<10;i++){
sprite = cc.Sprite.create('res/object-'+i+'.png');
sprite.retain();
sprite.setPosition(0,i*sprite.width);
sprite.visit();
sprite.release();
}
rt.end();
var rtSprite = cc.Sprite.createWithTexture(rt.sprite.texture); // 別にそのままrt使っても良いが
だいたいこんな感じになる。が、これだと上手く動かない時がある。というかモダンな環境では多分上手く動かない。スプライトが逆さまに移っているし、順序もおかしい筈。
WebGLだと上下が逆さま
これはccConfig
で設定したrenderMode
が2、または0でWebGLが有効な場合に起こる。どうしてかというと、CANVASテクスチャはDOMと同じく左上が基点なのだが、WebGLでは上下反転しているからだ。だから、どちらにも対応しようとした場合はrenderMode
がCANVASなのかWebGLなのかで処理を分けなければならない。
WebGL/Canvas両対応版
var rt = cc.RenderTexture.create(320,240);
rt.begin();
var sprite;
for(var i=0;i<10;i++){
sprite = cc.Sprite.create('res/object-'+i+'.png');
sprite.retain();
if (cc._renderType === cc._RENDER_TYPE_WEBGL) { // renderTypeで処理を分ける
sprite.setScale(1,-1); // 上下反転
sprite.setPosition(0,rt.height - i*sprite.width); // 上下逆から配置
}else if(cc._renderType === cc._RENDER_TYPE_CANVAS){
sprite.setPosition(0,i*sprite.width);
}
sprite.visit();
sprite.release();
}
rt.end();
var rtSprite = cc.Sprite.createWithTexture(rt.sprite.texture); // 別にそのままrt使っても良いが