2017-06-15

[Flash] Starling MovieClip CS6 SpriteSheet

[Flash] Starlingの学習 MovieClipを表示する。Flash Pro CS6でSpriteSheetを作成

環境:

  • Starling 2.1
  • Adobe AIR SDK 22
  • FlashDevelop 5.2
  • Windows 7 64bit
  • Flash Pro CS6

[話者] StarlingのMovieClipについて、書籍『Introducing Starling』で学ぶぞ。

まずはFlash Pro CS6でSpriteSheetを作成する。 素材は https://kenney.nl/assets/platformer-characters-1 を使用した。ライセンスがCC0(Public Domain)なので助かる。

[合いの手] ふむふむ。

[話者] Flash Pro CS6で素材を読み込み、アニメーションを作成・確認した。 3つの画像を適当なタイミングで切り替えてるだけの、簡単なアニメーションだ。

fpsは60。ステージの大きさはキャラ画像1体の大きさが80x110pxなのでそれを横に並べて160x110px。2キャラ分のMovieClipを作成したぞ。

実Flash。操作不可。

[合いの手] この2キャラは別々のMovieClipなんだね。

[話者] Flash Pro CS6のLibrary Panelで、2つのMovieClipを選択して右クリック。[スプライトシートを生成]してStarling向けSpriteSheetを作るぞ。[フレームをスタック]をチェックすれば重複画像をまとめることができる。スタックというのは紙を重ねる(stack)みたいな意味だ。

SpriteSheetの中身はこんなだ。

spritesheet.png

spritesheet.xml

<?xml version="1.0" encoding="UTF-16"?>
<TextureAtlas imagePath="201706SpriteSheet.png">
    <!-- Created with Adobe Flash CS6 version 12.0.2.529 -->
    <!-- http://www.adobe.com/products/flash.html -->
    <SubTexture name="female0000" x="0" y="0" width="81" height="110"/>
    <SubTexture name="female0001" x="0" y="0" width="81" height="110"/>
    <SubTexture name="female0002" x="0" y="0" width="81" height="110"/>
    <SubTexture name="female0003" x="0" y="0" width="81" height="110"/>
    <SubTexture name="female0004" x="0" y="0" width="81" height="110"/>
    <SubTexture name="female0005" x="0" y="0" width="81" height="110"/>
    ...
    <SubTexture name="player0070" x="162" y="110" width="81" height="110"/>
    <SubTexture name="player0071" x="162" y="110" width="81" height="110"/>
    <SubTexture name="player0072" x="162" y="110" width="81" height="110"/>
    <SubTexture name="player0073" x="162" y="110" width="81" height="110"/>
</TextureAtlas>

それでは、これをStarlingで読み込んでアニメーションさせよう。

Main.as はこれまでと同じ。

package
{
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import starling.core.Starling;
    
    /**
     * ...
     * @author foo
     */
    [SWF(width="480",height="480",frameRate="60",backgroundColor="#002143")]
    public class Main extends Sprite 
    {
        private var stln:Starling;
        public static var frameRate:uint = 0;
        
        public function Main() 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onContext3dCreated);
            stln = new Starling(Game, stage);
            stln.showStats = true;
            stln.antiAliasing = 0;
            stln.start();
        }
        
        private function onContext3dCreated(e:Event):void 
        {
            stage.stage3Ds[0].removeEventListener(Event.CONTEXT3D_CREATE, onContext3dCreated);

            if (Starling.context.driverInfo.toLowerCase().indexOf("software") != -1) {
                // GPU disable
                Starling.current.nativeStage.frameRate = 30;
            } else {
                // GPU enable
            }
            frameRate = Starling.current.nativeStage.frameRate;
        }
    }
}

Game.as

package 
{
    import flash.display.Bitmap;
    import starling.animation.Juggler;
    import starling.core.Starling;
    import starling.display.MovieClip;
    import starling.display.Sprite;
    import starling.events.Event;
    import starling.events.Touch;
    import starling.events.TouchEvent;
    import starling.events.TouchPhase;
    import starling.textures.Texture;
    import starling.textures.TextureAtlas;
    
    /**
     * ...
     * @author foo
     */
    public class Game extends Sprite 
    {
        private var jgr:Juggler;

        [Embed(source = "../bin/201706SpriteSheet.png")]
        private static var SpriteSheet:Class;

        [Embed(source = "../bin/201706SpriteSheet.xml", mimeType="application/octet-stream")]
        private static var SpriteSheetXML:Class;
        private var mve1:MovieClip;
        private var mve2:MovieClip;

        public function Game() 
        {
            if (stage) init()
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            addEventListener(Event.ENTER_FRAME, onGetGpuStyle);
        }
        
        private function onGetGpuStyle(e:Event):void  
        {
            if (Main.frameRate <= 0) return;
            removeEventListener(Event.ENTER_FRAME, onGetGpuStyle);
            
            addItem();
        }
        
        private function addItem():void 
        {
            var btmp:Bitmap = new SpriteSheet();
            var txtr:Texture = Texture.fromBitmap(btmp);
            
            var xm:XML = XML(new SpriteSheetXML());
            var txAtls:TextureAtlas = new TextureAtlas(txtr, xm);
            
            var mve1frames:Vector.<Texture> = txAtls.getTextures('player');
            //trace(mve1frames.length);
            mve1 = new MovieClip(mve1frames, 60);
            mve1.x = stage.stageWidth / 4 * 1;
            mve1.y = stage.stageHeight / 4 * 1;
            addChild(mve1);
            mve1.addEventListener(TouchEvent.TOUCH, onTouchMC);
            
            var mve2frames:Vector.<Texture> = txAtls.getTextures('female');
            mve2 = new MovieClip(mve2frames, 60);
            mve2.x = mve1.x;
            mve2.y = stage.stageHeight / 4 * 2;
            mve2.scaleX = -1;
            addChild(mve2);
            mve2.addEventListener(TouchEvent.TOUCH, onTouchMC);
            
            jgr = Starling.juggler;
            jgr.add(mve1);
            jgr.add(mve2);
        }
        
        private function onTouchMC(e:TouchEvent):void 
        {
            var tch:Touch = e.getTouch(stage);
            if ( ! tch) return;
            var ph:String = getTouchPhase(tch);
            if (tch.phase == TouchPhase.ENDED) {
                //trace(e.currentTarget);
                var tapobj:MovieClip = e.currentTarget as MovieClip;
                if (tapobj.isPlaying) {
                    tapobj.pause();
                } else {
                    tapobj.play();
                }
            }
        }

        private function getTouchPhase(tch:Touch):String
        {
            var ph:String = '';
            if (tch.phase == TouchPhase.BEGAN) {
                ph = 'BEGAN';
            } else if (tch.phase == TouchPhase.ENDED) {
                ph = 'ENDED';
            } else if (tch.phase == TouchPhase.HOVER) {
                ph = 'HOVER';
            } else if (tch.phase == TouchPhase.MOVED) {
                ph = 'MOVED';
            } else if (tch.phase == TouchPhase.STATIONARY) {
                ph = 'STATIONARY';
            }
            return ph;
        }
    }
}

実Flash。操作可。キャラをクリックで、アニメーション一時停止・再開

[合いの手] https://helpx.adobe.com/jp/animate/using/create-sprite-sheet.html の文書を読むと、スプライトシートとは別にテクスチャアトラスというのがあるみたいだよ。違いは?

[話者] Adobe Animate CC2017では[スプライトシートを生成]とは別に[テクスチャアトラスを生成]というのがメニューにあるようだな。

Adobe Flash Pro CS6では[スプライトシートを生成]しかないからなー。しかし以下のAdobeの人の記事を読むと‥‥

テクスチャアトラスは複数のスプライトシートを 1 つのファイルにまとめたものです。

引用元: http://cuaoar.jp/2011/12/movieclip-starling.html

Flash Professional CS6 から、スプライトシートを生成する機能が追加されました。 ... また、複数のシンボルを選択してからこの機能を使うことで、テクスチャアトラスを生成することもできます。

引用元: http://cuaoar.jp/2012/05/flash-pro-cs6-starling.html

複数のSymbolを選択して生成したものはテクスチャアトラスになってるらしいぞ。 今回は2つのMovieClipを選択して生成したから、作ったのはスプライトシートというよりテクスチャアトラスだったようだ。

[合いの手] ソースにある Starling.juggler は何だろう?

[話者] これにaddしないとanimationしてくれない。

0 件のコメント:

コメントを投稿

人気記事