ラベル StarlingFramework の投稿を表示しています。 すべての投稿を表示
ラベル StarlingFramework の投稿を表示しています。 すべての投稿を表示

2014年8月7日木曜日

Adobe AIR 15 Beta スプライトパフォーマンス検証

Adobe LabsでAIR15Betaが公開されました。
(リンク先へ)

1年程前に150個のスプライトアニメーションをNexus7(2012)で
表示するテストを行いました。


fpsは43程度でていました。

AIR15Beta + TEGRANOTE 7 + StarlingFramework 1.5.1を使用して同じ条件で
表示するテストを行いました。

fpsは60ほぼをキープしていました。ハードウェア性能の進化とAIRの進化には
まだまだ期待できると思います。

AIR15ではOpenGL ES3.0に対応するという事でさらに高速なグラフィックを表現する事にも期待できます。

追記

iPodTouch(第5世代) iOS7で上記と同じ条件で動作させてみました。
fpsは30を下回りました。モードはipa-app-store(アプリをリリースする状態)で
パッケージを行っています。






2013年6月29日土曜日

Magic&Dungeon リリース

Google Playでシンプルなアクションゲームをリリースしました。

開発環境
Adobe AIR 3.6
Starling Framework 1.3
Feathers 1.0

Get it on Google Play

2013年6月18日火曜日

Flash Pro CCとFlash Builderを連携する

今回はFlash Pro CCFlash Builderの連携を行い
Starling Frameworkを使用して
Air for iOSデバッグを行うという記事を書きました。

Flash Pro CCとFlashBuilderを連携する 1
今回の記事の概要とStarlingFrameworkの設定 (リンク先へ)

Flash Pro CCとFlashBuilderを連携する 2
Air for iOSの設定とサンプルソースコードを記載(リンク先へ)

Flash Pro CCとFlashBuilderを連携する 3
iOS端末によるデバッグ (リンク先へ)

Flash Pro CCとFlashBuilderを連携する 3

Flash Pro CCファイルメニューからAIR 3.6 for iOS 設定を選択します
・レンダリングモード ダイレクト
・解像度 高

一般からデプロイに移ります
iOS証明書プロビジョニングファイルの設定を行います

これでパブリッシュまでの準備が整いました。

次にiOS端末USBケーブルMacに接続し
実際にデバッグしてみます。
今回のテストはiOS 6.1.2を使用しています

Flash Pro CCデバッグメニュームービーをデバッグより
USB 経由でデバイスを選択して、接続した端末を設定します




デバッグメニューリモートデバッグセッションを開始を選択します

iOS端末TestiOSのアプリがインストールされるので、アプリを起動します




Flash Builderで設定したブレークポイントFlash Pro CCに反映されます

Flash Builderで設定したブレークポイント



デバッグ時にはFlash Pro CCの同じ場所で止まります



外部ライブラリファイルもFlash Builderで設定を行えば、Flash Pro CCに反映されます
Starling.as

Flash Pro CCとFlashBuilderを連携する 2

Flash Pro CCを起動し、AIR for iOSを選択します

ActionScript オプションより、クラスエディターFlash Builderに設定します

Flash Builderで設定したStarling Frameworkをリンクします
Flash Pro CCのファイルメニューActionScript 設定ソースパスを開きます
+ボタンを押した後、フォルダボタンを押します

Starling Frameworkソースフォルダを設定します

TestiOSクラスを作成します

TestiOSクラスを作成すると、Flash BuilderFlash Professional プロジェクト
作成するダイアログを表示しますので、作成を行います

TestiOSFlash Professional プロジェクトが作成されました

Flash Builder側からFlashパブリッシュやデバッグを呼び出す事ができます。

TestiOS.asMain.asを作成します
TestiOS.as
package
{
 import flash.display.Sprite;
 import flash.display.StageAlign;
 import flash.display.StageScaleMode;
 import flash.events.Event;
 import flash.geom.Rectangle;

 import starling.core.Starling;
 import starling.utils.HAlign;
 import starling.utils.RectangleUtil;
 import starling.utils.VAlign;

 [SWF(width="640",height="960",frameRate="60",backgroundColor="#0")]
 public class TestiOS extends Sprite
 {
  public static const STAGE_WIDTH:uint = 640;
  public static const STAGE_HEIGHT:uint = 960;

  private var viewport:Rectangle;

  public function TestiOS()
  {
   super();

   stage.align = StageAlign.TOP_LEFT;
   stage.scaleMode = StageScaleMode.NO_SCALE;

   addEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
  }

  protected function addedToStageHandler(event:flash.events.Event):void
  {
   removeEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);

   viewport = RectangleUtil.fit(
    new Rectangle(0,0,stage.stageWidth,stage.stageHeight), 
    new Rectangle(0,0,stage.fullScreenWidth,stage.fullScreenHeight),
    starling.utils.ScaleMode.SHOW_ALL);

   Starling.handleLostContext = true;
   Starling.multitouchEnabled = true;

   var st:Starling = new Starling(Main, stage, viewport);
   st.stage.stageWidth  = STAGE_WIDTH;
   st.stage.stageHeight = STAGE_HEIGHT;
   st.start();
   st.showStatsAt(HAlign.RIGHT,VAlign.BOTTOM,1);
  }

 }
}
Main.as
package
{
 import starling.display.Quad;
 import starling.display.Sprite;
 import starling.events.Event;
 import starling.utils.Color;

 public class Main extends Sprite
 {
  public function Main()
  {
   super();
   addEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
  }

  private function addedToStageHandler(event:Event):void
  {
   removeEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);

   var quad:Quad = new Quad(100,100,Color.BLUE);
   quad.x = (stage.stageWidth >> 1) - (quad.width >> 1);
   quad.y = (stage.stageHeight >> 1) - (quad.height >> 1);
   addChild(quad);
  }
 }
}

Flash Pro CCとFlashBuilderを連携する 1

今回は主にこの3つを行いました。
・Flash Pro CCFlash Builderを連携します。
StarlingFrameworkの簡単なサンプルアプリの作成
Flash Pro CCからブレークポイントを利用したデバッグ

開発環境
Mac OS X 10.7.5
Flash Professional CC Ver 13.0.0.759
Flash Builder 4.6
Adobe AIR 3.6
Starling Framework 1.3















Starling Frameworkを使用しますので
Flash BuilderにFlex ライブラリプロジェクトとして作成します
FlashBuilder-StarlingFrameworkをSWC化 (リンク先へ)


2013年3月29日金曜日

Starling ATFファイルの使用

SpriteSheetをATF形式で試してみました。
詳しくはATF SDKの公開(リンク先へ)をご覧下さい。

利点

  • テクスチャの保持に必要なメモリ料が少ない
  • テクスチャのアップロードが短時間で済む
  • 描画が早くなる
  • という事ですが、Starling1.3で試した結果以下のようになりました。

    Sprite Animation Sample

    150個のスプライトをアニメーションさせながら、移動をさせています。
    pngスプライトデータ 約43fps
    atfフォーマット 約35fps

    Starlingコンテンツの描画領域とassetsの管理 まとめ

    1.Starlingコンテンツの描画領域とassetsの管理(リンク先へ)

    2.Starlingコンテンツの描画領域とassetsの管理 実装編(リンク先へ)

    3.Starlingコンテンツの描画領域とassetsの管理 解説(リンク先へ)

    Starlingコンテンツの描画領域とassetsの管理 解説編

    描画領域の処理
    ScreenMultiResolution.as
    var showType:int = 0;
    
    if(showType == 0)
    {
    showAll();
    } else if(showType == 1) {
    showCenter();
    } else {
    return;
    }
    
    変数showTypeの0で画面全体を表示し、1で画面の中央に表示に切り替えます。
    ScreenMultiResolution.as
      private function showCenter():void
      {
       viewport = RectangleUtil.fit(
        new Rectangle(0, 0, stage.stageWidth,stage.stageHeight), 
        new Rectangle((stage.stageWidth >> 1) - (STAGE_WIDTH >> 1),
        (stage.stageHeight >> 1) - (STAGE_HEIGHT >> 1),
        STAGE_WIDTH,
        STAGE_HEIGHT),
        starling.utils.ScaleMode.SHOW_ALL);
      }
    
      private function showAll():void
      {
       viewport = RectangleUtil.fit(
        new Rectangle(0,0,stage.stageWidth,stage.stageHeight), 
        new Rectangle(0,0,stage.fullScreenWidth,stage.fullScreenHeight),
        starling.utils.ScaleMode.SHOW_ALL);
      }
    
    RectangleUtil.fit()メソッドは、第1引数の矩形領域を第2引数の矩形領域に、縦横比は変えずに納めるためのRectangleオブジェクトを返します。
    第3引数には、ScaleModeクラスの定数で伸縮モードが渡せます。 

    詳しくは
    Starlingフレームワーク1.3の新しい機能(リンク先へ)
    Multi-Resolution Development(リンク先へ)
    をご覧下さい。

    assetsの管理
    Main.as
      private function addAssets(data:Object):void
      {
       var sheetPngName:String = "sheetPng";
       var sheetXmlName:String = "sheetXml";
       var scaleFactorName:String = "scaleFactor";
       var contentScaleFactor:int;
       var sScale:String;
    
       if(Starling.contentScaleFactor >= 1 && Starling.contentScaleFactor < 3)
       {
        contentScaleFactor = int(Starling.contentScaleFactor);
        sScale = "x"+contentScaleFactor.toString();
    
        assetManager = new AssetManager(contentScaleFactor);
        assetManager.verbose = true;
        assetManager.enqueue(data[sScale][sheetPngName]);
        assetManager.enqueue(data[sScale][sheetXmlName]);
        assetManager.loadQueue(loadAssetsHandler);
       }
      }
    
      private function loadAssetsHandler(ratio:Number):void
      {
       if(ratio < 1.0) return;
    
       addTextures();
      }
    

    addAssetsメソッドでは、Starling.contentScaleFactorからテクスチャのスケール係数を取得します。 スケール係数に適したSpriteSheetを用意し、jsonファイルで管理するという仕組みになります。
    SpriteSheetファイルが決定した所で、次にAssetManagerクラスを利用し指定した読み込み処理を行なっています。 読み込みが完了(1.0)になるまで、loadAssetsHandlerを繰り返しコールされます。

    Starlingコンテンツの描画領域とassetsの管理 実装編


    spriteSheetは各自で用意をして下さい。
    このサンプルでは、TexturePackerを利用して作成しました。

    ScreenMultiResolution.as
    package
    {
     import flash.display.Sprite;
     import flash.display.StageAlign;
     import flash.display.StageScaleMode;
     import flash.events.Event;
     import flash.geom.Rectangle;
    
     import starling.core.Starling;
     import starling.utils.RectangleUtil;
     import starling.utils.ScaleMode;
    
     [SWF(width="320",height="480",frameRate="60",backgroundColor="#0")]
     public class ScreenMultiResolution extends Sprite
     {
      public static const STAGE_WIDTH:uint = 320;
      public static const STAGE_HEIGHT:uint = 480;
    
      private var viewport:Rectangle;
    
      public function ScreenMultiResolution()
      {
       super();
    
       stage.align = StageAlign.TOP_LEFT;
       stage.scaleMode = StageScaleMode.NO_SCALE;
    
       addEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
      }
    
      protected function addedToStageHandler(event:flash.events.Event):void
      {
       removeEventListener(Event.ADDED_TO_STAGE,addedToStageHandler);
    
       var showType:int = 0;
    
       if(showType == 0)
       {
        showAll();
       } else if(showType == 1) {
        showCenter();
       } else {
        return;
       }
    
       Starling.handleLostContext = true;
       Starling.multitouchEnabled = true;
    
       var st:Starling = new Starling(Main, stage, viewport);
       st.stage.stageWidth  = STAGE_WIDTH;
       st.stage.stageHeight = STAGE_HEIGHT;
       st.start();
      }
    
      private function showCenter():void
      {
       viewport = RectangleUtil.fit(
        new Rectangle(0, 0, stage.stageWidth,stage.stageHeight), 
        new Rectangle((stage.stageWidth >> 1) - (STAGE_WIDTH >> 1),
        (stage.stageHeight >> 1) - (STAGE_HEIGHT >> 1),
        STAGE_WIDTH,
        STAGE_HEIGHT),
        starling.utils.ScaleMode.SHOW_ALL);
      }
    
      private function showAll():void
      {
       viewport = RectangleUtil.fit(
        new Rectangle(0,0,stage.stageWidth,stage.stageHeight), 
        new Rectangle(0,0,stage.fullScreenWidth,stage.fullScreenHeight),
        starling.utils.ScaleMode.SHOW_ALL);
      }
    
     }
    }
    
    Main.as
    package
    {
     import flash.events.Event;
     import flash.net.URLLoader;
     import flash.net.URLRequest;
    
     import starling.core.Starling;
     import starling.display.Image;
     import starling.display.Quad;
     import starling.display.Sprite;
     import starling.events.Event;
     import starling.text.TextField;
     import starling.textures.Texture;
     import starling.utils.AssetManager;
    
     public class Main extends Sprite
     {
      private var assetManager:AssetManager;
    
      public function Main()
      {
       super();
    
       addEventListener(starling.events.Event.ADDED_TO_STAGE,addedToStageHandler);
      }
    
      private function addedToStageHandler(event:starling.events.Event):void
      {
       var urlLoader:URLLoader = new URLLoader();
    
       urlLoader.addEventListener(flash.events.Event.COMPLETE,urlLoaderCompleteHandler);
       urlLoader.load(new URLRequest("./assets/setting.json"));
      }
    
      protected function urlLoaderCompleteHandler(event:flash.events.Event):void
      {
       var urlLoader:URLLoader = event.target as URLLoader;
    
       urlLoader.removeEventListener(flash.events.Event.COMPLETE,urlLoaderCompleteHandler);
       addAssets(JSON.parse(urlLoader.data as String));
      }
    
      private function addAssets(data:Object):void
      {
       var sheetPngName:String = "sheetPng";
       var sheetXmlName:String = "sheetXml";
       var scaleFactorName:String = "scaleFactor";
       var contentScaleFactor:int;
       var sScale:String;
    
       if(Starling.contentScaleFactor >= 1 && Starling.contentScaleFactor < 3)
       {
        contentScaleFactor = int(Starling.contentScaleFactor);
        sScale = "x"+contentScaleFactor.toString();
    
        assetManager = new AssetManager(contentScaleFactor);
        assetManager.verbose = true;
        assetManager.enqueue(data[sScale][sheetPngName]);
        assetManager.enqueue(data[sScale][sheetXmlName]);
        assetManager.loadQueue(loadAssetsHandler);
       }
      }
    
      private function loadAssetsHandler(ratio:Number):void
      {
       if(ratio < 1.0) return;
    
       addTextures();
      }
    
      private function addTextures():void
      {
       var scaleFactor:Number = Starling.current.contentScaleFactor;
       var quadW:Number = 100;
       var quadH:Number = 100;
    
       var bg:Quad = makeQuad(0,0,stage.stageWidth,stage.stageHeight,0x0000ff);
       bg.alpha = 0.5;
       addChild(bg);
    
       var luQuad:Quad = makeQuad(0,0,100,100,Math.random() * 0xffffff);
       addChild(luQuad);
    
       var ldQuad:Quad = makeQuad(0,stage.stageHeight - quadH,100,100,Math.random() * 0xffffff);
       addChild(ldQuad);
    
       var ruQuad:Quad = makeQuad(stage.stageWidth - quadW,0,100,100,Math.random() * 0xffffff);
       addChild(ruQuad);
    
       var rdQuad:Quad = makeQuad(stage.stageWidth - quadW,stage.stageHeight - quadH,
        100,100,Math.random() * 0xffffff);
       addChild(rdQuad);
    
       var texture:Texture = assetManager.getTexture("bird");
    
       var image:Image = new Image( texture );
       addChild(image);
       image.x = 0;
       image.y = 0;
    
       var image2:Image = new Image( texture );
       addChild(image2);
       image2.x = stage.stageWidth - image.width;
       image2.y = (stage.stageHeight) - (image.height);
    
       var image3:Image = new Image( texture );
       addChild(image3);
       image3.x = (stage.stageWidth >> 1) - (image.width >> 1);
       image3.y = (stage.stageHeight >> 1) - (image.height >> 1);
      }
    
      private function makeQuad(_x:Number,_y:Number,_w:Number,_h:Number,_color:Number):Quad
      {
       var quad:Quad = new Quad(_w,_h,_color);
       quad.x = _x;
       quad.y = _y;
    
       return quad;
      }
    
     }
    }
    
    setting.json
    {"x1":{"sheetPng":"./assets/spriteSheet.png","sheetXml":"./assets/spriteSheet.xml"},"x2":{"sheetPng":"./assets/spriteSheet2x.png","sheetXml":"./assets/spriteSheet2x.xml"}}
    


    Starlingコンテンツの描画領域とassetsの管理

    iPodTouchとNexus7の2機種を利用して、コンテンツの描画領域の処理を行います。

    画面解像度に差のある2機種で、縦480x横320を基準にして表示をしました。
    Nexus7右側の画像では縦480x横320の大きさにした状態で
    画面の中央に配置しました。
    この処理は、RectangleUtil.fitというメソッドを利用する事で実現が可能です。

    今回はこの描画領域の処理とAssetManagerクラスを利用したアセットの管理方法を
    紹介します。
    この方法は、Starling Framework 1.3からの機能になります。

    実行結果


    Nexus7で表示した結果


    iPodTouchで表示した結果

    開発環境
    FlashBuilder 4.6
    Starling Framework 1.3
    Nexus7実機
    iPodTouch実機

    2013年2月5日火曜日

    Feathers - デスクトップとモバイルで使えるUIコントロールフレームワーク

    Stage3D
    FlashPlayer11.0(AIR 3.0)よりGPUによる2D, 3Dのハードウェアアクセラレーション
    レンダリング機能が付きました。
    この機能により、描画処理の向上に期待ができるようになります。
    Stage3DはFlashPlayerとAIRで使う事ができます。

    Starling Framework
    Stage3Dの機能を使うにはAGALというアセンブラ命令をActionScriptに書きます。
    Starling FrameworkではAGALを意識する事なく、普段ActionScriptを書くようなスタイルでスプライト機能やアニメーションを利用できます。

    Feathers
    Starling Frameworkの機能を利用したUIフレームワークです。
    ボタンやリストのようなUI、画面の管理を行う事ができます。

    動作パフォーマンス
    Feathersを利用した動作パフォーマンスですがNexus7で検証した所
    おおむね良好だと思います。動画を撮影しましたのでご覧下さい。
    AIR3.5 Feathers UISample

    導入編
    Feathersを導入してアプリケーションを開発する方法はいくつかありますが
    FlashBuilderを利用した開発手法を取り上げます。
    Feathersについて簡単な概要とStarling FrameworkとFeathersの
    ライブラリプロジェクトの設定方法を記載しています。



    UIコンポーネント ボタン編
    ボタンの組み込み方法とスキンの変更処理を記載しています。

    ボタンとリストのサンプルソースコード作成と素材を組み込みます。
    サンプルソースコードを元にボタンの概要とスキンの変更処理について解説しています。

    UIコンポーネント リスト編
    リストコンポーネントとアイテムレンダラについて記載しています。

    画面の処理 スクリーン編
    複数の画面間の移動を行う処理を記載しています。

    スクリーンのサンプルソースコードを作成します。

    サンプルソースコードを元にスクリーンの解説をしています。

    Feathers Example まとめ

    はじめに

    Feathers ListとButtonのサンプル

    Feathers Screenのサンプル

    Feathers ScreenExample Screenについて

    このサンプルはFeathersのサイト
    「How to use the Feathers Screen Component(リンク先へ) 」
    「How to use the Feathers ScreenNavigator component(リンク先へ) 」
    「Feathers ScreenNavigator Transitions(リンク先へ) 」
    を参考にしています。

    Feathers ScreenExampleのソースコード(リンク先へ)

    Main.as
    this._navigator.addScreen(MAIN_MENU,new ScreenNavigatorItem(MainMenuScreen,MAIN_MENU_EVENTS));
    
    addScreenメソッド
    ScreenNavigatorItemコンストラクタで必要とされる最初の引数は、 画面のIDと画面のインスタンスまたはすでにインスタンス化されているのDisplayObjectです。

    イベントを利用した画面のナビゲーション
    ScreenNavigatorItemクラスの第2引数(Object型)でイベントを定義します。
     イベントを送出すると、ScreenNavigatorは自動的に別の画面に移動する処理を
    行います。

    MainMenuScreen.as
       this._list.dataProvider = new ListCollection(
        [
        { text: "Sub 1", event: SHOW_SUB1_SCREEN },
        { text: "Sub 2", event: SHOW_SUB2_SCREEN },
        ]);
    
    Main.asで定義したイベントをリストのdataProviderに設定します。
      private function list_changeHandler(event:Event):void
      {
       const eventType:String = this._list.selectedItem.event as String;
       this.dispatchEventWith(eventType);
      }
    
    リストのアイテムが選択された時に画面に移動する為のイベントを送出します。

    ownerプロパティによる画面のナビゲーション
    Sub1Screen.as
      private function onBackButton():void
      {
       this.owner.showScreen(Main.MAIN_MENU);
      }
    
    Screenクラスが持つownerプロパティのshowScreenメソッドで別画面の移動を行います。

    トランジションの設定
    Main.as
       this._transitionManager = new ScreenSlidingStackTransitionManager(this._navigator);
       this._transitionManager.duration = 0.4;
    
    画面の移動を行う時のトランジションとしてScreenSlidingStackTransitionManagerを使用します。

    Feathers ScreenExample 作成3

    Sub2ChildScreen.as
    package screens
    {
     import feathers.controls.Button;
     import feathers.controls.Header;
     import feathers.controls.Label;
     import feathers.controls.Screen;
     import feathers.controls.ScrollContainer;
     import feathers.layout.AnchorLayout;
     import feathers.layout.VerticalLayout;
    
     import starling.display.DisplayObject;
     import starling.events.Event;
    
     public class Sub2ChildScreen extends Screen
     {
      private var _container:ScrollContainer;
      private var _header:Header;
      private var _backButton:Button;
    
      public var horizontalAlign:String = VerticalLayout.HORIZONTAL_ALIGN_LEFT;
      public var verticalAlign:String = VerticalLayout.VERTICAL_ALIGN_TOP;
      public var gap:Number = 2;
      public var paddingTop:Number = 0;
      public var paddingRight:Number = 0;
      public var paddingBottom:Number = 0;
      public var paddingLeft:Number = 0;
    
      public function Sub2ChildScreen()
      {
       super();
      }
    
      override protected function initialize():void
      {
       this._container = new ScrollContainer();
       this._container.layout = new AnchorLayout();
       this._container.verticalScrollPolicy = ScrollContainer.SCROLL_POLICY_ON;
       this._container.snapScrollPositionsToPixels = true;
       this.addChild(this._container);
    
       this._header = new Header();
       this._header.title = "Sub2 ChildScreen";
       this.addChild(this._header);
    
       this._backButton = new Button();
       this._backButton.label = "Back";
       this._backButton.addEventListener(Event.TRIGGERED, backButton_triggeredHandler);
    
       this._header.leftItems = new &ltdisplayobject>
        [
        this._backButton
        ];
    
       this.backButtonHandler = this.onBackButton;
    
       var label:Label = new Label();
       label.text = "Sub2のサブビューです";
       this._container.addChild(label);
      }
    
      override protected function draw():void
      {
       this._header.width = this.actualWidth;
       this._header.validate();
    
       this._container.y = this._header.height;
       this._container.width = this.actualWidth;
       this._container.height = this.actualHeight - this._container.y;
      }
    
      private function onBackButton():void
      {
       this.owner.showScreen(Main.SUB2_SCREEN);
      }
    
      private function backButton_triggeredHandler(event:Event):void
      {
       this.onBackButton();
      }
     }
    }
    
    Sub2Screen.as
    package screens
    {
     import feathers.controls.Button;
     import feathers.controls.Header;
     import feathers.controls.Screen;
     import feathers.controls.ScrollContainer;
     import feathers.layout.VerticalLayout;
    
     import starling.display.DisplayObject;
     import starling.display.Quad;
     import starling.events.Event;
    
     public class Sub2Screen extends Screen
     {
      public static const SHOW_CHILD_SCREEN:String = "showChildScreen";
    
      private var _container:ScrollContainer;
      private var _header:Header;
      private var _backButton:Button;
      private var _childButton:Button;
    
      public var horizontalAlign:String = VerticalLayout.HORIZONTAL_ALIGN_LEFT;
      public var verticalAlign:String = VerticalLayout.VERTICAL_ALIGN_TOP;
      public var gap:Number = 2;
      public var paddingTop:Number = 0;
      public var paddingRight:Number = 0;
      public var paddingBottom:Number = 0;
      public var paddingLeft:Number = 0;
    
      public function Sub2Screen()
      {
       super();
      }
    
      override protected function initialize():void
      {
       const layout:VerticalLayout = new VerticalLayout();
       layout.gap = this.gap;
       layout.paddingTop = this.paddingTop;
       layout.paddingRight = this.paddingRight;
       layout.paddingBottom = this.paddingBottom;
       layout.paddingLeft = this.paddingLeft;
       layout.horizontalAlign = this.horizontalAlign;
       layout.verticalAlign = this.verticalAlign;
    
       this._container = new ScrollContainer();
       this._container.layout = layout;
       this._container.verticalScrollPolicy = ScrollContainer.SCROLL_POLICY_ON;
       this._container.snapScrollPositionsToPixels = true;
       this.addChild(this._container);
    
       this._header = new Header();
       this._header.title = "Sub2 Screen";
       this.addChild(this._header);
    
       this._backButton = new Button();
       this._backButton.label = "Back";
       this._backButton.addEventListener(Event.TRIGGERED, backButton_triggeredHandler);
    
       this._header.leftItems = new &ltdisplayobject>
        [
        this._backButton
        ];
    
       this._childButton = new Button();
       this._childButton.label = "ChildScreen";
       this._childButton.addEventListener(Event.TRIGGERED, childButton_triggeredHandler);
    
       this._header.rightItems = new &ltdisplayobject>
        [
        this._childButton
        ];
    
       this.backButtonHandler = this.onBackButton;
    
       var redQuad:Quad = new Quad(100,100,0xff0000);
       var greenQuad:Quad = new Quad(100,100,0x00ff00);
       var blueQuad:Quad = new Quad(100,100,0x0000ff);
    
       this._container.addChild(redQuad);
       this._container.addChild(greenQuad);
       this._container.addChild(blueQuad);
      }
    
      private function childButton_triggeredHandler():void
      {
       this.dispatchEventWith(SHOW_CHILD_SCREEN);
      }
    
      override protected function draw():void
      {
       this._header.width = this.actualWidth;
       this._header.validate();
    
       this._container.y = this._header.height;
       this._container.width = this.actualWidth;
       this._container.height = this.actualHeight - this._container.y;
      }
    
      private function onBackButton():void
      {
       this.owner.showScreen(Main.MAIN_MENU);
      }
    
      private function backButton_triggeredHandler(event:Event):void
      {
       this.onBackButton();
      }
     }
    }
    
    StarlingFramework,Feathers,FeathersThemeの
    Flexライブラリプロジェクトの登録を行います。(リンク先へ)
    ビルドを行います。

    Feathers ScreenExample 作成2

    MainMenuScreen.as
    package screens
    {
     import feathers.controls.Header;
     import feathers.controls.List;
     import feathers.controls.Screen;
     import feathers.data.ListCollection;
     import feathers.skins.StandardIcons;
    
     import starling.events.Event;
     import starling.textures.Texture;
    
     public class MainMenuScreen extends Screen
     {
      public static const SHOW_SUB1_SCREEN:String = "showSub1Screen";
      public static const SHOW_SUB2_SCREEN:String = "showSub2Screen";
    
      private var _header:Header;
      private var _list:List;
    
      public function MainMenuScreen()
      {
       super();
      }
    
      override protected function initialize():void
      {
       this._header = new Header();
       this._header.title = "Screen Test";
       this.addChild(this._header);
    
       this._list = new List();
       this._list.dataProvider = new ListCollection(
        [
        { text: "Sub 1", event: SHOW_SUB1_SCREEN },
        { text: "Sub 2", event: SHOW_SUB2_SCREEN },
        ]);
       this._list.itemRendererProperties.labelField = "text";
       this._list.addEventListener(Event.CHANGE,list_changeHandler);
       this._list.itemRendererProperties.accessorySourceFunction = accessorySourceFunction;
       this.addChild(this._list);
      }
    
      override protected function draw():void
      {
       this._header.width = this.actualWidth;
       this._header.validate();
    
       this._list.y = this._header.height;
       this._list.width = this.actualWidth;
       this._list.height = this.actualHeight - this._list.y;
      }
    
      private function accessorySourceFunction(item:Object):Texture
      {
       return StandardIcons.listDrillDownAccessoryTexture;
      }
    
      private function list_changeHandler(event:Event):void
      {
       const eventType:String = this._list.selectedItem.event as String;
       this.dispatchEventWith(eventType);
      }
     }
    }
    
    Sub1Screen.as
    package screens
    {
     import feathers.controls.Button;
     import feathers.controls.Header;
     import feathers.controls.Screen;
     import feathers.controls.ScrollContainer;
     import feathers.layout.HorizontalLayout;
    
     import starling.display.DisplayObject;
     import starling.display.Quad;
     import starling.events.Event;
    
     public class Sub1Screen extends Screen
     {
      private var _container:ScrollContainer;
      private var _header:Header;
      private var _backButton:Button;
      private var _settingsButton:Button;
    
      public var horizontalAlign:String = HorizontalLayout.HORIZONTAL_ALIGN_LEFT;
      public var verticalAlign:String = HorizontalLayout.VERTICAL_ALIGN_TOP;
      public var gap:Number = 2;
      public var paddingTop:Number = 0;
      public var paddingRight:Number = 0;
      public var paddingBottom:Number = 0;
      public var paddingLeft:Number = 0;
    
      public function Sub1Screen()
      {
       super();
      }
    
      override protected function initialize():void
      {
       const layout:HorizontalLayout = new HorizontalLayout();
       layout.gap = this.gap;
       layout.paddingTop = this.paddingTop;
       layout.paddingRight = this.paddingRight;
       layout.paddingBottom = this.paddingBottom;
       layout.paddingLeft = this.paddingLeft;
       layout.horizontalAlign = this.horizontalAlign;
       layout.verticalAlign = this.verticalAlign;
    
       this._container = new ScrollContainer();
       this._container.layout = layout;
       this._container.horizontalScrollPolicy = ScrollContainer.SCROLL_POLICY_ON;
       this._container.snapScrollPositionsToPixels = true;
       this.addChild(this._container);
    
       this._header = new Header();
       this._header.title = "Sub1 Screen";
       this.addChild(this._header);
    
       this._backButton = new Button();
       this._backButton.label = "Back";
       this._backButton.addEventListener(Event.TRIGGERED, backButton_triggeredHandler);
    
       this._header.leftItems = new 
        [
        this._backButton
        ];
    
       this.backButtonHandler = this.onBackButton;
    
       var redQuad:Quad = new Quad(100,100,0xff0000);
       var greenQuad:Quad = new Quad(100,100,0x00ff00);
       var blueQuad:Quad = new Quad(100,100,0x0000ff);
    
       this._container.addChild(redQuad);
       this._container.addChild(greenQuad);
       this._container.addChild(blueQuad);
      }
    
      override protected function draw():void
      {
       this._header.width = this.actualWidth;
       this._header.validate();
    
       this._container.y = this._header.height;
       this._container.width = this.actualWidth;
       this._container.height = this.actualHeight - this._container.y;
      }
    
      private function onBackButton():void
      {
       this.owner.showScreen(Main.MAIN_MENU);
      }
    
      private function backButton_triggeredHandler(event:Event):void
      {
       this.onBackButton();
      }
     }
    }
    

    Feathers ScreenExample 作成1

    プロジェクト名はFeathersScreenです。
    パッケージの構成です。

    FeathersScreenExample.as
    package
    {
     import flash.display.Sprite;
     import flash.display.StageAlign;
     import flash.display.StageScaleMode;
     import flash.events.Event;
     import flash.geom.Rectangle;
    
     import starling.core.Starling;
    
     [SWF(width="960",height="640",frameRate="60",backgroundColor="#2f2f2f")]
     public class FeathersScreenExample extends Sprite
     {
      private var _starling:Starling;        
    
      public function FeathersScreenExample()
      {
       if(this.stage)
       {
        this.stage.scaleMode = StageScaleMode.NO_SCALE;
        this.stage.align = StageAlign.TOP_LEFT;
       }
       this.mouseEnabled = this.mouseChildren = false;
       this.loaderInfo.addEventListener(Event.COMPLETE, loaderInfo_completeHandler);
      }
    
      private function loaderInfo_completeHandler(event:Event):void
      {
       Starling.handleLostContext = true;
       Starling.multitouchEnabled = true;
       this._starling = new Starling(Main, this.stage);
       this._starling.enableErrorChecking = false;
       this._starling.start();
    
       this.stage.addEventListener(Event.RESIZE, stage_resizeHandler, false, int.MAX_VALUE, true);
       this.stage.addEventListener(Event.DEACTIVATE, stage_deactivateHandler, false, 0, true);
      }
    
      private function stage_resizeHandler(event:Event):void
      {
       this._starling.stage.stageWidth = this.stage.stageWidth;
       this._starling.stage.stageHeight = this.stage.stageHeight;
    
       const viewPort:Rectangle = this._starling.viewPort;
       viewPort.width = this.stage.stageWidth;
       viewPort.height = this.stage.stageHeight;
       try
       {
        this._starling.viewPort = viewPort;
       }
       catch(error:Error) {}
      }
    
      private function stage_deactivateHandler(event:Event):void
      {
       this._starling.stop();
       this.stage.addEventListener(Event.ACTIVATE, stage_activateHandler, false, 0, true);
      }
    
      private function stage_activateHandler(event:Event):void
      {
       this.stage.removeEventListener(Event.ACTIVATE, stage_activateHandler);
       this._starling.start();
      }
     }
    }
    
    Main.as
    package 
    {
     import feathers.controls.ScreenNavigator;
     import feathers.controls.ScreenNavigatorItem;
     import feathers.controls.ScrollContainer;
     import feathers.motion.transitions.ScreenSlidingStackTransitionManager;
     import feathers.themes.MetalWorksMobileTheme;
    
     import screens.MainMenuScreen;
     import screens.Sub1Screen;
     import screens.Sub2ChildScreen;
     import screens.Sub2Screen;
    
     import starling.display.Sprite;
     import starling.events.Event;
    
     public class Main extends Sprite
     {
      public static const MAIN_MENU:String = "mainMenu";
      public static const SUB1_SCREEN:String = "sub1Screen";
      public static const SUB2_SCREEN:String = "sub2Screen";
      public static const SUB2_CHILD_SCREEN:String = "sub2ChildScreen";
    
      private var _theme:MetalWorksMobileTheme;
      private var _container:ScrollContainer;
      private var _navigator:ScreenNavigator;
      private var _menu:MainMenuScreen;
      private var _transitionManager:ScreenSlidingStackTransitionManager;
    
      private static const MAIN_MENU_EVENTS:Object =
       {
        showSub1Screen: SUB1_SCREEN,
        showSub2Screen: SUB2_SCREEN
      }
    
      public function Main()
      {
       super();
       this.addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
      }
    
      private function addedToStageHandler(event:Event):void
      {
       this._theme = new MetalWorksMobileTheme(this.stage);
    
       this._navigator = new ScreenNavigator();
    
       this._navigator.addScreen(SUB1_SCREEN,new ScreenNavigatorItem(Sub1Screen));
    
       this._navigator.addScreen(SUB2_SCREEN,
        new ScreenNavigatorItem(Sub2Screen,{showChildScreen:SUB2_CHILD_SCREEN}));
       this._navigator.addScreen(SUB2_CHILD_SCREEN,new ScreenNavigatorItem(Sub2ChildScreen));
    
       this._navigator.addScreen(MAIN_MENU,new ScreenNavigatorItem(MainMenuScreen,MAIN_MENU_EVENTS));
    
       this.addChild(this._navigator);
    
       this._transitionManager = new ScreenSlidingStackTransitionManager(this._navigator);
       this._transitionManager.duration = 0.4;
    
       this._navigator.showScreen(MAIN_MENU);
      }
     }
    }
    

    Feathers Screenサンプルについて

    画面の管理や切り替えを行う為のScreenクラスを使ったサンプルを作成します。

    サンプルアプリ概要

    • メインはリスト形式でビューを遷移する為のリストアイテムが2件あります。
    • Sub1をタップすると、Sub1 Screenに遷移します。
    • Sub2をタップすると、Sub2 Screenに遷移します。
    • ChildScreenボタンを押すとSub2 Child Screenへ遷移します。
    • Backボタンを押す事で1つ前のScreenへ戻ります。

    Feathers Example ItemRendererについて

    このサンプルはFeathersのサイト
    「Creating custom item renderers for the Feathers List control(リンク先へ) 」
    を参考にしています。
    FeathersExampleのソースコード(リンク先へ)

    アイテムレンダラクラスでは、ListクラスからdataProviderで設定した配列の情報を
    元に1件毎に表示するリストアイテムのレイアウトを行う事ができます。
    アイテムレンダラーはapache Flex(旧Adobe Flex)でも採用しています。

    BasicItemRenderer.as
      override protected function initialize():void
      {
       if(!this.itemBG)
       {
        this.itemBG = new Quad(1,1,Math.floor(Math.random() * 0xffffff));
        this.addChild(this.itemBG);
       }
    
       if(!this.itemLabel)
       {
        this.itemLabel = new Label();
        this.addChild(this.itemLabel);
       }
      }
    
    アイテム内のBGとラベルの初期化をします

    BasicItemRenderer.as
      protected function layout():void
      {
       this.itemBG.width = this.actualWidth;
       this.itemBG.height = this.actualHeight;
    
       this.itemLabel.width = this.actualWidth;
       this.itemLabel.height = this.actualHeight;
       this.itemLabel.y = (this.actualHeight / 2) - (this.itemLabel.y / 2);
      }
    
    アイテム内のBGとラベルの大きさ、配置を設定します

    BasicItemRenderer.as
      protected function commitData():void
      {
       if(this._data)
       {
        this.itemLabel.text = this._data.text.toString();
       } else {
        this.itemLabel.text = "";
       }
      }
    
    アイテム内のラベルの表示情報を設定します

    Feathers Example Listについて

    このサンプルはFeathersのサイト
    「How to use the Feathers List component(リンク先へ) 」
    を参考にしています。
    FeathersExampleのソースコード(リンク先へ)

    FeathersExampleを実行すると以下の画面になります

    Listの表示と設定の流れ
    ボタンサンプルからListサンプルへ表示を切り替える為に
    exampleIndexの値を変更します。
    FeathersExample.as
      private function loaderInfo_completeHandler(event:Event):void
      {
       var exampleIndex:int;
       Starling.handleLostContext = true;
       Starling.multitouchEnabled = true;
    
       exampleIndex = 1;
    
    ListExample.as
       this.removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
    
       this.theme = new MetalWorksMobileTheme(this.stage);
    
       var list:List = new List();
       list.width = this.stage.stageWidth;
       list.height = this.stage.stageHeight;
       this.addChild(list);
    
       var listData:Object;
       var listTable:Array = [];
       for(var i:int=0;i<1000;i++)
       {
        listData = { text : i.toString()+":"+"アイテム" };
        listTable.push(listData);
       }
       var groceryList:ListCollection = new ListCollection(listTable);
       list.dataProvider = groceryList;
       list.itemRendererProperties.labelField = "text";
       list.itemRendererType = BasicItemRenderer;
    

  • テーマの設定
  • インスタンスの作成
  • レイアウト、大きさの設定
  • 画面に対してaddChildを行う
  • リストに表示する1件単位のリストデータを作成
  • ListCollectionの作成
  • dataProviderの設定
  • labelFieldプロパティの設定
  • アイテムレンダラの設定