知っ得?軽量・高速・サイズ気にしないでいい!スマートフォン向けAIRアプリ(Flashだよ)
御久方ぶりです
千歳です!
ここで取り扱うのは「air for android&AIR for iOS」です。(以下 AIRと一括りにします)
ツールの方は「FlashBuilder」ではなく「Flash」です。(以下、FlashといえばオーサリングツールのFlashのことです)
FlashBuilderでも使えると思いますが、試していないのでご了承下さい。
さて、AIRの最近のニュースだと
「Adobe AIR 3」が公開されましたね。
詳しくはkamijo氏のブログが大変に参考になるので必見です!
http://cuaoar.jp/2011/07/adobe-air-3-1.html
では、本題です。
AIRアプリをスマートフォンで見る時にネックになるのが
・ベクターレンダリングの遅さ 特にiOSだと顕著と聞きます。
・画像のサイズ分け
Flashで作る場合、端末のサイズによって切替て綺麗に出したいのになかなか大変です。
この2点を解決するクラスを作ってみました。(思いつきで書いたのでかなり適当&機能がないw)
これで、サイズを気にせず、ベクターの重さを考えないでゴリゴリアニメーションさせたりできます!
しかるべき場所にソースコードをアップしようと思ったのですが、面倒になったので&大したコードでもないので
ペッと貼っつけていきます。
サンプルswfはコチラ
ベクターレンダリングの遅さ
サンプルを見ていただければわかりますが、キャラの素材が画像(ラスター)になっています。
でも、素材はベクターデータです。
ウィンドウサイズを変えてリロードしてみてください。
どのサイズでも綺麗にでると思います。
やってることを簡単にご説明。
・ベクターの素材系をブロックごとにMC化(左上が必ず起点になるように)
・「シンボルプロパティ」から「基本クラス」にクラスを指定する
以上
一回クラスを作ってしまえば簡単です。
クラスはコチラです↓
package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Sprite; import flash.events.Event; /** * ... * @author pon */ public class SpriteBitmap extends Sprite { public static var scale:Number=1; private var bitmap:Bitmap private var bd:BitmapData public function SpriteBitmap(){ addEventListener(Event.ADDED_TO_STAGE, added); } private function added(e:Event):void { removeEventListener(Event.ADDED_TO_STAGE, added); var copy:Sprite=new Sprite(); var sp:Sprite = new Sprite(); copy.addChild(getChildAt(0)) sp.addChild(copy); copy.scaleX *= scale; copy.scaleY *= scale; bd = new BitmapData(sp.width, sp.height, true, 0x00000000); bd.draw(sp); bitmap = new Bitmap(bd); bitmap.scaleX /= scale; bitmap.scaleY /= scale; while(numChildren){ removeChildAt(0); } addChild(bitmap); copy.removeChildAt(0) sp.removeChildAt(0) copy=null sp = null } } }
- スケールを表示サイズに合わせる
- BitmapData.draw()
- スケールを元のサイズに戻す
- 元あったパスデータをremoveChild()
- BitmapをaddChild
という流れです。
これで、素材としてはベクターで用意して
アプリで表示する時に自動でラスター化することで、軽い&綺麗&早いを実現できます
画像のサイズ分けがメンドイ
前述の対応でほぼほぼ解決してしまいましたが、端末サイズを読みとって丁度イイサイズにするコードをドキュメントクラスに書きます。
package { import display.View; import flash.display.Sprite; //import net.hires.debug.Stats; import flash.display.StageScaleMode import flash.display.StageAlign import smartphone.src.display.SpriteBitmap /** * ... * @author pon */ public class Main extends Sprite { private const WIDTH:uint = 480; private const HEIGHT:uint = 320; public var view:View; //private var stats:Stats = new Stats(); public function Main():void{ //addChild(stats); stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; var sw:int = stage.stageWidth; var sh:int = stage.stageHeight; if (sh > sw) { sw = stage.stageHeight; sh = stage.stageWidth; } var ws:Number = sw / WIDTH; var hs:Number = sh / HEIGHT; if (ws < hs) { hs = ws; view.y=(sh - HEIGHT * hs) / 2; }else { ws = hs; view.x = (sw - WIDTH * ws) / 2; } view.scaleX = ws; view.scaleY = hs; SpriteBitmap.scale = ws; } } }
ポイントは
Flash上での画面サイズは480×320(320×480)が推奨です。(比率があってればOK)
iPhoneの比率がコレなのでこれで作っておくと丁度イイですAndroidではこれより長くなる端末があるので、長めに背景素材などを用意するか、最上位レイヤーの両サイドに黒い矩形を載せておきましょう。
さらにドキュメンクラスに画面サイズを定数として記述しておきます。
ドキュメントクラスではなくMCでラップしてそこをメインクラスにする。
このMCを丁度イイサイズに拡縮します。縦横の長さを比較して縦か横かを把握する。
iOSは知りませんが、Androidでは縦か横か取得できますがなんか信用できません。(実機でアレレ?ってことがありました。)なので、自力で調べます。
ビットマップ化してくれるクラスのstaticにスケールサイズを教えてあげる。
この値でビットマップ化のサイズを可変させますので重要です!このコードが走った後にそれぞれの「ビットマップ化してくれるクラス」が生成されるようにしましょう。(1フレ開けておくなど)
とまぁ、こんな感じです。
このコードはご自由にお使いください!
同じシンボルが複数登場する時とか、出たり消えたりする場合などの対応が必要かなーとおもってるのですが
必要になったときに追加しようかと思ってます。誰かやっちゃてもいいですよ!
ほかにも便利な機能をもたせたりしてくれたら、教えてくださいね!w
利用する時は、周りの人に「level0」を紹介してもらえればうれしいです
では快適なAIRアプリ制作ライフを!