記事一覧

Cocos2d解説(6) テクスチャアトラス作成ツールとの連携

■テクスチャアトラス作成ツールとの連携

テクスチャアトラスを駆使してアニメーションを実装する際には、アトラスの切り出し位置の管理が必要である。
各画像の配置が単純な場合は、切り出し位置を CGRectMake で直接指定すればよいので大した問題ではない。たとえば、横100px・縦150pxの絵が横に5枚並んだ .png ファイルから5枚のフレームを作成するには、

NSMutableArray* frames = [NSMutableArray initWithCapacity:5];
CCTexture* texture = [[CCTexture alloc] initWithImage:@"allFrames.png"];
for(int i=0; i<5; i++){
[frames addObject:[CCSpriteFrame frameWithTexture:texture
rect:CGRectMake(100*i, 0, 100, 150)]];
}

のように機械的に切り出し位置を指定すればよい。

しかし、もっと切り出し位置が複雑になると、その管理が大変になることがある。
そうした場合、「TexturePacker」と「Zwoptex」といったアトラス作成ツールを使うと、この切り出し情報をplistファイルとして書きだしてくれるので、個別指定する手間が省ける。

そんなわけでいくつかのサイトではこうしたツールを使うことを前提でcocos2dアニメーションの実装方法を紹介しているが、実際のところは、以下で述べるように話が相当ややこしくなるし、コード量もかえって多くなるので、アトラス構造の複雑さや容量の余裕次第では、上記の基本的な方法で実現できないか検討した方が良いかもしれない。

そのあたりのメリット・デメリットは後述するとして、ひとまず解説。

アトラス作成ツールが作ってくれるのは、CCSpriteFrameに相当する切り出し位置情報などのパラメータ。これを、xml (.plist)で書きだしてくれる。
この plist を読み込むことで各CCSpriteFrameに与えるべき情報=フレーム情報が生成される。

・・・となると、plist に書かれた情報から CCSpraiteFrame 作ってそれを NSArray に格納してくれるような関数があるのを期待するが、残念ながらそういうものは用意されていない。

plistファイルを読み込んだ際に行われるのは CCSpriteFrameCache にフレーム情報を登録することである。
CCSpriteFrameCache はどう使うかというと、まず

[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"frames.plist"];

としてフレーム情報を sharedSpriteFrameCache に読み込み、次にこの sharedSpriteFrameCache に対して

CCSpriteFrame* aFrame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"frameName"];

のようにしてフレーム情報を取得する。
このフレーム名はTexturePackerの場合

filenameN.ext
(filename:元の画像名 , N:番号 , ext:元の画像の拡張子)

となっている。例えば、元画像名 frame.png の 3 番目のフレーム名は
@"frame3.png"
である。
拡張子が付いてくるのでファイル名みたいに見えるが、単なる名前である。(当初自分はサンプルコードだけ追いかけて使い方を探っていたのでここがすごく混乱した)

さて、これがきわめて不毛なのだが、この sharedSpriteFrameCache から1つずつフレーム情報を引き出して
NSArrayに格納する作業が必要なのである。
たとえば5フレームある場合はこんな感じ。

NSMutableArray *animFrames = [NSMutableArray array];
for(int i = 1; i <= 5; ++i) {
[animFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
[NSString stringWithFormat:@"frame%d.png", i]]];
}

せっかく一括して読み込んだのだから、サクッとNSArrayまで作ってくれればいいと思うのだが・・・。
無いものは無いのでこのようにするしかない。
で、このようにして作った NSArray を使って

id anim = [CCAnimation animationWithFrames:animFrames];

とし、さらに CCAnimate を使ってアクションオブジェクトに変換した上でスプライトの runAction に指定する

CCAnimate* animAction = [CCAnimate actionWithAnimation:anim];
[sprite1 runAction:animAction];

と、やっとコマアニメーションが実行できる。


■どういう場合に使うべきか

以上のようにけっこうな手間がかかるので、単にコマアニメーションを1つ作るのにツール連携を利用するのは正直不毛だと思う。

一般的に考えて、ツール連携を使うメリットがあるのは次のような場合だろうか。

*大量の異なるスプライトを利用する必要があり、かつきちんと名前ベースでフレームを管理する必要がある
*一つのアトラスにサイズの違う多種類のキャラクターの複数コマのアニメーションが入っている等、切り出し情報の管理が複雑
*すでに上記の手順がメソッド化されている。もしくは、今回作っておくと今後繰り返し利用が見込める
*アニメーションとは関係なくとも、できるだけコンパクトに1つのアトラスに画像を詰め込みたい

ちなみに、zwoptexもTexturePackerも、画像を等間隔で並べる操作が簡単で、photoshopでグリッドを駆使したりしながら並べるよりかなり効率がいいので、冒頭の例のように機械的に数値指定で切り出す際も画像並べツールとして利用できる。