読者です 読者をやめる 読者になる 読者になる

夏までにiPhone アプリつくってみっか!

趣味でiPhone/Androidアプリを開発し、日々勉強した事を書いています。オープンワールド系レースゲームをUnityで開発中です。

【cocos2d】テクスチャアトラスを使ってみる

cocos2d

今回は、CCSpriteBatchNodeを使わずに実装した前回の弾を放射状に撃つプログラムをCCSpriteBatchNodeを使って実装してみたいとおもいます。が、その前に考えなくてはならない事があります。
キャラクターが発射する弾のサイズはキャラクターより小さい方が良いと考え、このプログラムでは異なるサイズのスプライトを使っているのですが、異なるテクスチャーを持つスプライトをバッチノードにaddChildしようとするとプログラムがクラッシュします。今回はテクスチャ自体は同じなのでscaleプロパティを使って弾のサイズを縮小すれば良いのですが、最終的にはキャラクターと弾はデザインを変えなくてはいけないので、今からそれに備えておきます。
それにはテクスチャアトラスを使用する必要があります。
テクスチャアトラス(あるいはスプライトシート)は複数のテクスチャ画像を1つのテクスチャ画像ファイルにまとめたものです。テクスチャアトラスに含まれる個々の画像の元のファイル名やテクスチャアトラスのどこに配置されているかが記載された.plistの拡張子を持つ同名のファイルと1セットで使用されます。
テクスチャアトラスを使う事で見た目の異なるオブジェクトをCCSpriteBatchNodeにaddChildできるだけでなく、RAMの使用量を節約することができます。通常テクスチャは任意のサイズで作成しますが、iPhone内部では幅、高さが2の乗数の大きさのサイズに自動的に変換されてしまいます。元のテクスチャのサイズが全て2の乗数x2の乗数のサイズであれば無駄はできませんが、そうでない場合は変換で増えた領域は無駄になってしまいます。2の乗数サイズのテクスチャアトラスの中に様々なサイズの画像をできるだけ隙間なくびっしりと敷き詰めることでRAMの無駄な使用量を最小限にする事ができます。
テクスチャアトラスとそれに対応する.plistファイルを人力で作成する事は不可能ではありませんが、自動でやってくれる便利なツールがいくつか出ています、今回はLearn Cocos2d 2: Game Development for Iosで紹介されていたTexturePackerというツールをつかってテクスチャアトラスを作ってみました。有料アプリケーションですが、機能が制限された状態であれば無料で使用できます。今回は7日間の試用版状態で使ってみました。
例によってcocos2dのアイコンですが、大小の他に敵キャラ用に色を変えたアイコンを用意しました。これがTexturePackerで作成したテクスチャアトラスの画像です。
f:id:takujidev:20130410210652p:plain
背景が透明なので見えませんが、結構無駄なスペースがあります。
f:id:takujidev:20130410211114p:plain
背景に色を付けてみました。黒い部分が無駄な領域です。大きい方の2つのアイコンがもう少し小さければテクスチャアトラスの縦サイズが半分になりましたがまあ良いでしょう。本来であればこういう空きスペースに他のテクスチャを詰め込むと無駄を節約できるのです。
TexturePackerを初めて使ってみたのですが、3ステップで完了し、特別な設定はする必要はありませんでした。TexturePackerの画面はこんな感じです。
f:id:takujidev:20130410213144p:plain

そして、.pngファイルとともに生成される.plistファイルの中身はこんな感じになっています。
f:id:takujidev:20130410213535p:plain
元のファイル名の情報や座標の情報が含まれているのがわかると思います。
で、これらのファイルをcocos2dで使うには、まずシングルトンインスタンスのCCSpriteFrameCacheに.plistファイルを読み込みます。これにより、.png拡張子のテクスチャファイルも読み込まれます。そして、読み込まれたテクスチャアトラスのデータはCCSpriteFrameのインスタンスとして生成されます。

[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"icon-atlas.plist"];

あとは、例えばCCSpriteの画像として使いたければ、

CCSprite* sprite = [CCSprite spriteWithSpriteFrameName:@"Icon-72.png"];

などとやれば元のファイル名でアクセスできます。このようにして同じテクスチャアトラスのスプライトフレームから作ったCCSpriteのインスタンスは同じCCSpriteBatchNodeにaddChildできます。

スプライトフレームのインスタンスとして取り出すときはこのようにします。

CCSpriteFrame* frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"Icon-Small.png"];

次回は今回作成したテクスチャアトラスを活用して全てのスプライトをバッチノードに登録してみたいと思います。また、スプライトバッチノードは今後様々なクラスからアクセスする事になると思いますので、シングルトンとして実装したいと思います。