■画像ファイルとテクスチャ
テクスチャを使用する際には、使用するたびに画像をファイルから読み出すのではなく、まずメモリ上にビットマップとして展開して、それを読み出して使用することになる。
なので、画像を指して "テクスチャ" と言った場合には このメモリ上のビットマップを指している。
前回の記事で示した方法でスプライトを作る場合、内部的には画像を元にテクスチャをメモリ上に作成→そのテクスチャを指定してスプライト作成という処理が行われている。つまり、ごく大雑把にはこのような内容である。
CCTexture2d* texture = [[CCTexture2d alloc] initWithImage:@"texture.png"];
sprite1 = [CCSprite spriteWithTexture:texture rect:rect1];
■テクスチャキャッシュ
spriteWithFile: を使った場合の挙動は、単なるテクスチャ作成に加えてテクスチャキャッシュ(CCTextureCache)への登録という処理も含まれるので、
CCTexture2d* texture = [[CCTextureCache sharedTextureCache] addImage:@"texture.png"];
sprite1 = [CCSprite spriteWithTexture:texture rect:rect1];
とするとより近い挙動となる。
テクスチャキャッシュは、メモリ上にあるテクスチャへのポインタをまとめて持ってくれている仕組み。アプリの起動中ずっとインスタンスが存在しているので、アプリ内のどこからでも参照することが出来る(いわゆるシングルトン)。
なので、違うシーンで同じテクスチャを使いたい場合など、一度テクスチャを作ってテクスチャキャッシュに登録すれば、簡単に使い回しができる。
上記の addImage: はテクスチャの作成とキャッシュへの登録を同時に行ってくれるメソッドということになる。
便利ではあるが、不要なテクスチャの掃除などは自動では行ってくれないので、メモリが厳しい場合は適宜
[[CCTextureCache sharedTextureCache] removeUnusedTextures];
などとして使わなくなったテクスチャを破棄する必要がある。
あまり使い回しをしない場合(シーンが変わると使うテクスチャもほとんど入れ替わる場合など)は、むしろ自前でテクスチャをalloc/releaseした方がメモリの管理としては合理的かもしれない。
その場合都度画像読み込みのオーバーヘッドがかかるのがデメリットである。
公式ドキュメントなどでは基本的にテクスチャキャッシュの利用が
推奨されてはいるが、それはそれとしてあくまでバランスを考えて選ぶことが必要、と思っておいた方がいいだろう。
なお、他にも initWithImage 系の初期化メソッドは自動的にキャッシュを利用するので、テクスチャの生成・破棄を自分でやりたい場合には留意しておきたい。
■テクスチャアトラスについて
ゲームキャラのコマアニメーションのように小さい画像がたくさん必要な場合、一つの画像ファイルに複数の絵を押し込めて
使用時に切り出すという方法がよく用いられる。
これは、描画パフォーマンス上の利点があるほか、画像ファイル数が異様に増加してしまって面倒なことになるのを避けることができる。
この複数の絵が入った画像をテクスチャアトラス(以下アトラス)と呼ぶ。
CCSpriteはアトラスの使用を前提としているため、必ずテクスチャの切り出し情報も保持している。
アトラスから切り出してスプライトを作る場合はこんな感じ。
//画像の左上から 100px×100px部分を切り出してスプライトを作成
CGRect rect1 = CGRectMake(0, 0, 100, 100);
CCSprite* aSprite = [CCSprite spriteWithFile:@"texture.png" rect:rect1];
前回の最も単純な例では rect:を指定しなかったが、この場合画像の大きさがそのまま切り出し範囲となる。