cheka.jp 超不定期で更新する写真達。お口直しにどうぞ。

Herlockで作るiOSアプリ(もちろんAndroidも!) – スプライトシート編 –

この記事はHerlockシリーズの続きです。

スプライトシートを利用して見た目を調整します。
基本的な仕様はHerlockで作るiOSアプリ(もちろんAndroidも!) – タッチイベント編 –と一緒です。

準備

スプライトシートの作成を参考に作成して下さい。
今回準備したスプライトシートはこちらです。

Spritesheet
{"frames": [
    {
    	"filename": "1",
    	"frame": {"x":0,"y":0,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": false,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
    	"sourceSize": {"w":100,"h":100}
    }
    ,{
    	"filename": "2",
    	"frame": {"x":100,"y":0,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": false,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
    	"sourceSize": {"w":100,"h":100}
    }
    ,{
    	"filename": "3",
    	"frame": {"x":200,"y":0,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": false,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
    	"sourceSize": {"w":100,"h":100}
    }
    ,{
    	"filename": "4",
    	"frame": {"x":300,"y":0,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": false,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
    	"sourceSize": {"w":100,"h":100}
    }
    ,{
    	"filename": "5",
    	"frame": {"x":400,"y":0,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": false,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
    	"sourceSize": {"w":100,"h":100}
    }
    ,{
    	"filename": "6",
    	"frame": {"x":0,"y":100,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": false,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
    	"sourceSize": {"w":100,"h":100}
    }
    ,{
    	"filename": "7",
    	"frame": {"x":100,"y":100,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": false,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
    	"sourceSize": {"w":100,"h":100}
    }
    ,{
    	"filename": "8",
    	"frame": {"x":200,"y":100,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": false,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
    	"sourceSize": {"w":100,"h":100}
    }
    ,{
    	"filename": "9",
    	"frame": {"x":300,"y":100,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": false,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
    	"sourceSize": {"w":100,"h":100}
    }
    ,{
    	"filename": "10",
    	"frame": {"x":400,"y":100,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": false,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
    	"sourceSize": {"w":100,"h":100}
    }
    ,{
    	"filename": "drag1",
    	"frame": {"x":0,"y":200,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": true,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":101},
    	"sourceSize": {"w":100,"h":101}
    }
    ,{
    	"filename": "drag2",
    	"frame": {"x":100,"y":200,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": true,
    	"spriteSourceSize": {"x":0,"y":1,"w":100,"h":101},
    	"sourceSize": {"w":100,"h":101}
    }
    ,{
    	"filename": "drag3",
    	"frame": {"x":200,"y":200,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": true,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":101},
    	"sourceSize": {"w":100,"h":101}
    }
    ,{
    	"filename": "drag4",
    	"frame": {"x":300,"y":200,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": true,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":101},
    	"sourceSize": {"w":100,"h":101}
    }
    ,{
    	"filename": "drag5",
    	"frame": {"x":400,"y":200,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": true,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":101},
    	"sourceSize": {"w":100,"h":101}
    }
    ,{
    	"filename": "drag6",
    	"frame": {"x":0,"y":300,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": true,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":101},
    	"sourceSize": {"w":100,"h":101}
    }
    ,{
    	"filename": "drag7",
    	"frame": {"x":100,"y":300,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": true,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":101},
    	"sourceSize": {"w":100,"h":101}
    }
    ,{
    	"filename": "drag8",
    	"frame": {"x":200,"y":300,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": true,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":101},
    	"sourceSize": {"w":100,"h":101}
    }
    ,{
    	"filename": "drag9",
    	"frame": {"x":300,"y":300,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": true,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":101},
    	"sourceSize": {"w":100,"h":101}
    }
    ,{
    	"filename": "drag10",
    	"frame": {"x":400,"y":300,"w":100,"h":100},
    	"rotated": false,
    	"trimmed": true,
    	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":101},
    	"sourceSize": {"w":100,"h":101}
    }],
    "meta": {
    	"app": "Adobe Flash Professional",
    	"version": "13.1.0.226",
    	"image": "spritesheet.png",
    	"format": "RGBA8888",
    	"size": {"w":512,"h":512},
    	"scale": "1"
    }
};

スプライトシート用のロジックを追加

spritesheet.pngから指定の範囲を切り出して新規にBitmapを作成し、spriteに追加します。
管理用にscene/gamesprite.jsを作成して下さい。

/* ゲームのロジック */
define( ['config'], function ( config ) {
    //Flashから書き出したJSONを変数に代入します
    var flashExport = {"frames": [
        {
        	"filename": "1",
        	"frame": {"x":0,"y":0,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": false,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
        	"sourceSize": {"w":100,"h":100}
        }
        ,{
        	"filename": "2",
        	"frame": {"x":100,"y":0,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": false,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
        	"sourceSize": {"w":100,"h":100}
        }
        ,{
        	"filename": "3",
        	"frame": {"x":200,"y":0,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": false,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
        	"sourceSize": {"w":100,"h":100}
        }
        ,{
        	"filename": "4",
        	"frame": {"x":300,"y":0,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": false,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
        	"sourceSize": {"w":100,"h":100}
        }
        ,{
        	"filename": "5",
        	"frame": {"x":400,"y":0,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": false,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
        	"sourceSize": {"w":100,"h":100}
        }
        ,{
        	"filename": "6",
        	"frame": {"x":0,"y":100,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": false,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
        	"sourceSize": {"w":100,"h":100}
        }
        ,{
        	"filename": "7",
        	"frame": {"x":100,"y":100,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": false,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
        	"sourceSize": {"w":100,"h":100}
        }
        ,{
        	"filename": "8",
        	"frame": {"x":200,"y":100,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": false,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
        	"sourceSize": {"w":100,"h":100}
        }
        ,{
        	"filename": "9",
        	"frame": {"x":300,"y":100,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": false,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
        	"sourceSize": {"w":100,"h":100}
        }
        ,{
        	"filename": "10",
        	"frame": {"x":400,"y":100,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": false,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":100},
        	"sourceSize": {"w":100,"h":100}
        }
        ,{
        	"filename": "drag1",
        	"frame": {"x":0,"y":200,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": true,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":101},
        	"sourceSize": {"w":100,"h":101}
        }
        ,{
        	"filename": "drag2",
        	"frame": {"x":100,"y":200,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": true,
        	"spriteSourceSize": {"x":0,"y":1,"w":100,"h":101},
        	"sourceSize": {"w":100,"h":101}
        }
        ,{
        	"filename": "drag3",
        	"frame": {"x":200,"y":200,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": true,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":101},
        	"sourceSize": {"w":100,"h":101}
        }
        ,{
        	"filename": "drag4",
        	"frame": {"x":300,"y":200,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": true,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":101},
        	"sourceSize": {"w":100,"h":101}
        }
        ,{
        	"filename": "drag5",
        	"frame": {"x":400,"y":200,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": true,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":101},
        	"sourceSize": {"w":100,"h":101}
        }
        ,{
        	"filename": "drag6",
        	"frame": {"x":0,"y":300,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": true,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":101},
        	"sourceSize": {"w":100,"h":101}
        }
        ,{
        	"filename": "drag7",
        	"frame": {"x":100,"y":300,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": true,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":101},
        	"sourceSize": {"w":100,"h":101}
        }
        ,{
        	"filename": "drag8",
        	"frame": {"x":200,"y":300,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": true,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":101},
        	"sourceSize": {"w":100,"h":101}
        }
        ,{
        	"filename": "drag9",
        	"frame": {"x":300,"y":300,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": true,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":101},
        	"sourceSize": {"w":100,"h":101}
        }
        ,{
        	"filename": "drag10",
        	"frame": {"x":400,"y":300,"w":100,"h":100},
        	"rotated": false,
        	"trimmed": true,
        	"spriteSourceSize": {"x":0,"y":0,"w":100,"h":101},
        	"sourceSize": {"w":100,"h":101}
        }],
        "meta": {
        	"app": "Adobe Flash Professional",
        	"version": "13.1.0.226",
        	"image": "spritesheet.png",
        	"format": "RGBA8888",
        	"size": {"w":512,"h":512},
        	"scale": "1"
        }
    };
    //Flashのjsonを上記フレーム定義に変換
    var SpriteSheet = [];
    for(var i = 0; i < flashExport.frames.length; i++) {
        var frame = flashExport.frames[i].frame;
        SpriteSheet[flashExport.frames[i].filename] = (new Rectangle(frame.x, frame.y, frame.w, frame.h));
    }

    var spriteSheetImage = new Image( "assets/images/spritesheet.png" );
    spriteSheetImage.onload = function() {
//        console.log("spriteLoad!");
    };
    //外部へ公開するAPI
    return {
        getSprite : function(name){
            name = name.toString();
            var sprite;
            if(SpriteSheet[name]){
                sprite = new Sprite(100,100);
                sprite.addChild( new Bitmap(new BitmapData( spriteSheetImage ), false, false, SpriteSheet[name]) );
                sprite.name = name;
            }
            return sprite;
        }
    }
});

ゲームロジックの修正

スプライトを利用するようにゲームロジックを修正します。
ドラッグ可能なspriteを入替えるロジックも追加しておきます。

/* ゲームのロジック */
define( ['config','scene/gamesprite'], function ( config ,spriteSheet) {
    //生成するオブジェクト数
    var maxCount = 5;
    //外部へ公開するAPI
    return {
        //ランダムの数字作成
        createNumber : function(){
          return parseInt(1+(Math.random()*8));
        },
        //新しい数字を追加する
        addNewNumber : function(list){
            var range = list.length;
            list = list.slice(1,range);
            list[range-1] = this.createNumber();
            return list;
        },
        //数字のリストを生成する
        createNumberList : function(){
            var list = [];
            for(var i=0;i<maxCount;i++){
                list[i] = this.createNumber();
            }
            return list;
        },
        //Spriteを準備する
        createSprite : function(id,number){
            var name = (id===0) ? "drag" + number : number;
            return _stage.addChild( spriteSheet.getSprite(name) );
        },
        //新しいSpriteを追加する
        addNewSprite : function(spriteList,numberList){
            //最後の行を追加する
            var range = numberList.length;
            _stage.removeChild(spriteList[0]);
            spriteList = spriteList.slice(1,range);
            spriteList[range-1] = this.createSprite(range,numberList[range-1]);
            //最初の行をドラッグ可能なspriteへ変換する
            spriteList[0] = this.createSprite(0,spriteList[0].name);
            return spriteList;
        },
        //spriteの初期化
        initializeSprite : function(list){
            var numberSprite = [];
            for(var i=0;i<list.length;i++){
                numberSprite[i] = this.createSprite(i,list[i]);
            }
            return numberSprite;
        },
        //並び替え
        showList : function(list){
            var adjust = 0;
            _.each(list,function(obj){
                obj.x = 30 + ( adjust * 120);
                obj.y = 100;
                adjust++;
            });
        },
        //タッチ移動
        touchMove : function(event,numberSprite){
            if(100<event.localY){
                numberSprite[0].x = event.localX - numberSprite[0].width/2;
                numberSprite[0].y = event.localY - numberSprite[0].height/2;
            }
        },
        //タッチ終了
        touchEnd : function(event,number,numberSprite){
            return {
                number : this.addNewNumber(number),
                numberSprite : this.addNewSprite(numberSprite,number)
            }
        },
        includeObject : function(x,y,obj){
            var _x = [obj.x,obj.x+obj.width];
            var _y = [obj.y,obj.y+obj.height];
            return (_x[0]<=x && x<=_x[1] && _y[0]<=y && y<=_y[1]) ? false : true;
        }
    }
});

ゲームロコントローラーの修正

主要なロジックをgamelogic.jsに移譲するように修正致しました。

/* 画面遷移の管理 */
define( ['config','scene/gamelogic'], function ( config,logic ) {
    //画面オブジェクト
    var _sprite_image_bg, _sprite_button;
    var _loaded = false;
    var _waitNumber;
    //Gameページの追加
    var Page = function (path){
        //親の呼び出し
        Scene.call(this,path);
        //コンテキストの準備
        var self = this;
        //数字配列
        this.touched = true;
        this.number = logic.createNumberList();
        this.numberSprite = [];
        //Topイベント
        this.goToTop = function(){
            //ゲーム画面の描画
            Scene.goto("/");
        }
        //タッチ開始
        this.touchMove = this.touchBegin = function(event){
            //ホームボタンが押されていかチェックする
            self.touched = logic.includeObject(event.localX,event.localY,_sprite_button);
            //ホームボタン以外の時
            if(self.touched){
                logic.touchMove(event,self.numberSprite);
            }
        }
        //タッチ移動終了
        this.touchEnd = function(event){
            //ホームボタン以外の時
            if(self.touched){
                var res = logic.touchEnd(event,self.number,self.numberSprite);
                self.number = res.number;
                self.numberSprite = res.numberSprite;
                //再表示
                logic.showList(self.numberSprite);
            }
        }
        //tweemjsを進めるためのイベント
        this.tweenTick = function(){
            createjs.Tween.tick(1000/60);
        }
        //画面オブジェクトの追加
        this.addChildren = function(){
            //背景画像の描画
            _stage.addChild( _sprite_image_bg );
            //ボタンの描画
            _stage.addChild( _sprite_button );
            _sprite_button.addEventListener( "touchTap",this.goToTop, false );
            //ボタンのアニメーション
            var startY = config.height*(-1);
            var oldY = _sprite_button.y;
            _sprite_button.y = startY + oldY;
            createjs.Tween.get(_sprite_button,{loop:false}).to({y:oldY},1000, createjs.Ease.backin);
            //背景のアニメーション
            _sprite_image_bg.y = startY;
            createjs.Tween.get(_sprite_image_bg,{loop:false}).to({y:0},1000, createjs.Ease.backin).call(function(){
                //ステージにゲームオブジェクトを準備
                self.numberSprite = logic.initializeSprite(self.number);
                logic.showList(self.numberSprite);
                //タッチイベント
                self.touched = true;
                _stage.addEventListener("touchBegin",self.touchBegin,false);
                _stage.addEventListener("touchMove",self.touchMove);
                _stage.addEventListener("touchEnd",self.touchEnd);
            });
            _stage.addEventListener("enterFrame",this.tweenTick)
        }
    };
    Page.prototype = new Scene();
    //準備処理
	var deferred = Deferred();
    //読込処理
    Page.prototype.onEnter = function () {
        if(_loaded) return true;
        //ボタンの準備
        var image_button = new Image(config.button + "top.png");
        image_button.onload = function() {
            _sprite_button = new Sprite(170,90);
            _sprite_button.x = 117;
            _sprite_button.y = 500;
            _sprite_button.addChild( new Bitmap( new BitmapData( image_button ) ) );
            //背景画像の描画
            var image_bg = new Image(config.background.game);
            image_bg.onload = function(){
                //背景画像の準備
                _sprite_image_bg = new Bitmap( new BitmapData( image_bg ) );
                //onShowの呼び出し
                deferred.call();
                _loaded = true;
            };
        }
    };
    //表示処理
    Page.prototype.onShow = function () {
        //コンテキスト
        var self = this;
        if(!_loaded){
            deferred.next( function () {
                //背景画像の描画
                self.addChildren();
            });
        }else{
            this.addChildren();
        }
    };
    //非表示処理
    Page.prototype.onHide = function () {
        _stage.removeAllEventListeners();
        _sprite_button.removeEventListener( "touchTap", this.goToTop );
        _stage.removeChild(_sprite_button);
        _stage.removeChild(_sprite_image_bg);
        _.each(this.numberSprite,function(obj){
            obj = _stage.getChildByName(obj.name);
            _stage.removeChild(obj);
        });
    };
    //シーンの追加
    Scene.mapping({
        "/game": Page
    });
});

ロジックの整理も含まれていますが、スプライトシートが簡単に利用できるのが分かると思います。
画像をロードするとコールバックが発生するので、積極的に使いたい機能ですね!

Add a Comment

メールアドレスが公開されることはありません。

Get Adobe Flash player