スプライトシートによるアニメーションの実装 [Edit]

こんにちは、ソニックムーブのみかちです。あっという間に8月です!花火の季節ですね!隅田川の花火大会は豪雨で中止になって残念でした・・・私は自宅警備隊でしたが、、さて、夜空が花火で彩られているそんな中、Herlockも打ち上げ準備です!毎回佳境といっておりますが、本当に佳境です!でっかく打ち上げたいと思いますので、みなさんご期待くださいっ

連載8回目の今回はスプライトシートによるアニメーションの実装についてご紹介させていただきます!Herlockではスプライトシートを利用して簡単にコマ送りアニメーションさせることが可能です。

スプライトシートとは

おそらく皆さんご存知のスプライトシートだと思われますが、一応ご説明をさせていただくと、、
スプライトシートとは、複数の画像を一枚の画像にまとめて、タイル状に配置したビットマップイメージファイルです。
アニメーション画像の管理がしやすい+ファイル容量を抑えるのにも効果的で、ゲームアプリなどのアニメーションが多いアプリ制作にはもってこいです。
FlashはCS6から、アニメーションを「スプライトシート」として書き出す機能が実装されています。

スプライトシートの書き出し

それでは実際にFlashのタイムラインアニメーションから スプライトシートを書き出してみます!

【スプライトシートの書き出し手順】
1.Flash上で任意のムービークリップを選び、右クリックして「スプライトシートを生成」メニューを選択します。

Herlock

2.データ形式は「JSON-Array」、画像形式は「PNG32bit」を選択して書き出します。

以上で書き出しは完了です!書き出したスプライトシートは下図となります。とっても簡単!CS6万歳!

Herlock

スプライトシートを利用したアニメーション

Herlockではこのスプライトシートを使ってアニメーションを作ることが簡単にできます。
スプライトシートによるアニメーションは下図のようにスプライトシートの画像を順々に表示していきます。アニメーションgif のようなコマアニメの要領ですね!

Herlock

アニメーションの実装について

スプライトシートによるコマアニメはBitmap.setClippingRectによって生成します。
setClippingRectの引数にはRectangleオブジェクトを渡すので、このRectangleを書き出したJSONから生成します。
Flashから書き出された1フレーム分のJSONデータは下記のようになります。

{
	"filename": "g0000",
	"frame": {"x":0,"y":0,"w":200,"h":143},
	"rotated": false,
	"trimmed": false,
	"spriteSourceSize": {"x":0,"y":0,"w":200,"h":143},
	"sourceSize": {"w":200,"h":143}
}

JSONを参考に下記の用なイメージで1フレーム分の描画矩形情報を生成します。

new Rectangle(frame.x, frame.y, frame.w, frame.h)

フレーム情報はJSONのframesに配列として格納されているので下記のようなコードで 全フレーム分の情報を抽出することが出来ます。
flashExportが作成したJSONデータです。

var frames = [];

for(var i = 0; i < flashExport.frames.length; i++) {
    var frame = flashExport.frames[i].frame;
    frames.push(new Rectangle(frame.x, frame.y, frame.w, frame.h));
}

※コード量を減らしたい場合は、事前にJSONを整形してframe情報以外を削除してもOKです。

アニメーションの実行はenterframeでsetClippingRectを呼び、上記で生成したRectangleを渡せばOKです。
それでは実際に動かしてみます!
スプライトシートを使用したアニメーション実装の全コードは下記となります。

//Flashから書き出したJSONを変数に代入します
var flashExport = {"frames": [
        {
            "filename": "g0000",
            "frame": {
                "x": 0,
                "y": 0,
                "w": 200,
                "h": 143
            },
            "rotated": false,
            "trimmed": false,
            "spriteSourceSize": {
                "x": 0,
                "y": 0,
                "w": 200,
                "h": 143
            },
            "sourceSize": {
                "w": 200,
                "h": 143
            }
        },
        //書き出したJSONを代入(今回は省略します)
    }
};

 /**
 * コマアニメ用のスプライトシート上の描画領域を
 * Rectangleの配列として定義します。
 */
var FRAMES = [];

//FlashのJSONを上記フレーム定義に変換します
for(var i = 0; i < flashExport.frames.length; i++) {
    var frame = flashExport.frames[i].frame;
    FRAMES.push(new Rectangle(frame.x, frame.y, frame.w, frame.h));
}

//Mixinの実装
var mixin = function( target, imports ) {
    for ( var method in imports ) {
        target[method] = imports[method];
    }
};

//アニメーション生成用のSpriteオブジェクトを生成します
var SpriteAnimationFactory = {

    create: function( bmd, frames ) {
        //表示コンテナ
        var sprite = new Sprite();
        //methodsの定義内容をmixin
        mixin(sprite, this.methods);
        //表示用Bitmap
        sprite.bitmap = sprite.addChild( new Bitmap(bmd, false, false, frames[0]) );
        //Frame
        sprite.frames = frames;
        //現在のFrameIndex
        sprite.frameIndex = 0;
        return sprite;
    },

    //アニメーションの表示コンテナに実装するメソッド
    methods: {
        //アニメーションの再生
        play: function() {
            var self = this;
            this.update = function() {
                self.renderFrame(self.frameIndex++);
                if(self.frameIndex >= self.frames.length) {
                    self.frameIndex = 0;
                }
            };
            this.addEventListener("enterFrame", this.update);
        },
        //アニメーションの停止
        stop: function() {
            this.removeEventListener("enterFrame", this.update);
        },
        //フレームを表示
        renderFrame: function(frameIndex) {
            var frame = this.frames[frameIndex];
            this.bitmap.setClippingRect(frame);
        },
        //フレームのリセット
        reset: function() {
            this.renderFrame(0);
            this.frameIndex = 0;
        }
    }
};

//==============================================
// 実行処理
//==============================================
var stage = new Stage( 320, 480 );
addLayer( new Layer( stage ) );

//背景を敷き詰めます
var bg = stage.addChild( new Bitmap( new BitmapData( 1, 1, true, 0xff00ffff ) ) );
bg.width = stage.stageWidth;
bg.height = stage.stageHeight;

//画像を読み込みます
var image = new Image( "assets/images/sheet.png" );

image.onload = function() {

    //アニメーション表示コンテナを生成してstageに追加
    var cat = SpriteAnimationFactory.create( new BitmapData( image ), FRAMES);
    stage.addChild( cat );

    //再生
    cat.play();
};

実行結果が下図となります。
ねこ好き弊社のぷにぷに毛玉ねこがびっくりしているアニメーションが表示できました!カワイイ!

Herlock

このようにとても簡単にFlashのタイムラインアニメーションからアニメーションを作成することができました。Flashでつくったアニメーションがそのまま表示されるのはやっぱり楽しいですね!

さて、今回でF-site様でのHerlockのご紹介も最後となります。
6月末から8回にわたって、Herlockの基本的な概念から、サンプルアプリを使用したアプリ実装のご説明、ライブラリの使い方などいろいろとご紹介させていただきました。すこしでも皆さんに興味を持って頂けたのであれば嬉しいです!

Herlockのクローズドベータ版のリリースは8月中旬を予定しております!
順調にいけばもう少しで実際に触って頂けると思いますので今しばらくお待ちいただければとっ。
もし、まだ事前登録をお済でない方はこの機会にぜひ!事前登録はコチラから簡単にできますのでよろしくお願いします。

まだまだHerlockは機能が盛りだくさんです!すべてご紹介はできませんでしたので、ぜひAPI Documentも公開中ですので、興味を持たれた方は覗いてみてください。こそっと機能がふえていたりするので、そこも要チェックです!

また、FacebookやTwitterでも開発状況や新しい情報を配信しておりますのでこちらもチェックしてみてください!たまに私も現れることがあると思いますので、飽きずにお付き合いくださいw
FB:https://www.facebook.com/herlock.do
Twitter:@herlock_do


最後になりましたが、今回この連載を引き受けてくださったF-site様、ご対応いただいたスタッフの方々にこの場を借りてお礼申し上げます!ありがとうございました!

その他の記事