[AS][iPhone]FlashBuilder4.5のActionSclriptモバイルプロジェクトにて、iOSでプレビューした際のステージサイズが正常に取れない場合

だいぶはまってネットに情報が見当たらなかったのでメモ。

FlashBuilder4.5でiPhone、Androind等のアプリを作るため、以下2つのプロジェクトが用意されました。

  1. Flexモバイルプロジェクト
  2. ActionScriptモバイルプロジェクト

1.はMXMLベースのプロジェクトで2はASだけで作れるプロジェクト。
ボクはMXMLはさっぱりなのでASだけで作れる2.を選択。
普通のFlashコンテンツを作ると同様にドキュメントクラスからゴリゴリ書いていけばOKですが、
iOS用の書き出しをした際にステージサイズの参照値おかしなことになりました。

こちらの想定は、シミュレートデバイスが、iPhone3GSなら320 × 480、
iPhone4設定なら、640 × 960となってほしいところですが、
stage.stageWidth,stage.stageHeightのtrace結果は常に、500, 375

なんぞこれ、と思えどステージサイズの設定する箇所は見当たらず。
ためしにapp.xmlのwidthとheightに直接値(320 480)を入れてみるも変化無し。
さらにドキュメントクラスにSWFのembedタグを書いてみるも変化無し。


FlashBuilderのHelpを観てみるとこんなページに行き着きました。
http://www.randytroppmann.com/2011/04/12/pure-as3-workflow-with-flex-builder-4-5/

そこに書かれていた見慣れぬ1行を追加してみると。。。

stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;

これを入れることでstage.stageWidth,stageHeightが想定通りの値となりました。
(シミュレートデバイスを変えることにより値も変化する)
とりあえず、よくわからんけど、上記一行は必須らしい。


P.S.
Retina対応もできるらしいけど、3G/3GSとRetinaの混合設定がよくわからん。。
highを書くだけで、Objective-Cみたいに自動でいい感じに変換してくれるのか、それとも2種類の画角を分けて作らないのいけないのか。。
Retinaの実機がないから検証できんのよね。。

[AS]Flash(AS3)におけるローディングバーが正常に動作しないときのひとつの理由

すげぇ、はまったのでメモしておきます。

まずは状況説明

  • テスト環境(heteml)では何の問題もなくローディングバーが表示されていた。
  • 本番環境(海外のよくわからんサーバー)にアップするとローディングバーの挙動がわけわからんようになった。
  • FFだと常に100%表示で、IEとかChromeだと常に0%表示になってしまう。

数日悩んだ後、飲み会の席で某HIGE先生に相談したら1分で解決してくれました。

「サーバーがHttpヘッダにContentLength返さない仕様だとbytesTotalがおかしくなるよ」
「ブラウザごとで解釈が違うと思うよ」


サーバー側がContentLengthを返さないのが原因かもとのこと。
対策としては、あらかじめ読み込むファイルのサイズがわかってるなら、bytesTotalを使わずにバイト数を決め打ちで入力しておく。
ファイルサイズがわからんのなら、いっそ%表示のないポンデリングローダーにしちゃう。
そんな感じでOK。


ちなみに実はAS3のリファレンスにも書いてありました。

ダウンロードデータの合計バイト数を示します。このプロパティは、ロード操作の進行中は 0 を格納し、操作が完了した時点で設定されます。また、Content-Length ヘッダーがない場合、bytesTotal の値が不確定になります。

URLLoaderのbytesTotalの項目に書かれています。
がしかし、LoaderInfoのbytesTotalの項目にはこれ書いてないんですよね。。。
今回はswfの読み込みで発生したので、LoaderInfoのbytesTotalも同様の現象が起きますよ、ということ。
なんともいやらしい罠でした。

[AS]ProgressionのPreloaderで”「Error #2044: ハンドルされていない ioError : text=Error #2036: 読み込みが未完了です。 URL: index.swf?”となってしまう場合の対処方法

ProgressionでPreloader.asからindex.swfを読み込むときにこんなエラーダイアログに悩まされてました。

どういうときにこのエラーになるかというと、Preloader.swfがindex.swfの読みこみが終わらないうちに、ブラウザを閉じてしまうとこうなります。
index.swfが重い場合、「ローディング長いからもう観なくていいや」ってブラウザ落とすと上記ダイアログで固まるんですね。
最高にうざい状態です。

で、エラーとしては、IOErrorってわかってるので、そこのエラー処理を書いてあげればいいんですけど、読み込みの処理はPreloader.asの親クラスに書いてあるので、どのオブジェクトに対して、IOErrorのハンドリングをすればいいのかわからなかったのですが、ついに重い腰をあげて親クラスの中身を覗いてみたら、5分で解決したというオチです。

結論としては、こんな感じ。

//Preloader.asの atReady()の中に一行追加
override protected function atReady():void{
//↓これを追加
this.addEventListener(IOErrorEvent.IO_ERROR, function():void { trace("エラー") } );
}

Preloader.asのatReady()の中で、thisに対してIOErrorのハンドリングを書けばOKです。

なぜ、thisに書くかといえば、Preloader.asの親クラス、CastPreloader.asの中にこの一行があるので。

_loader.contentLoaderInfo.addEventListener( IOErrorEvent.IO_ERROR, super.dispatchEvent );
//_loaderはindex.swfを読むためのもの

リスナー関数でsuper.dispatchEventを飛ばしてるから、Preloader.asのthisでイベントを取れるようです。

ちなみに、CastPreloader.as内の_loaderは、Preloader.asからはcontentLoaderInfoで参照が取れるので、Preloader.as内で、

//thisの代わりにcontentLoaderInfoでイベントをハンドリング
contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, function():void { trace("エラー") } );

という感じで書いてみると、一応traceは出力されるんですけども、traceの前に最初のエラーが表示されてしまい、まったく意味がないことになりました。
なので、contentLoaderInfoではなく、素直にthisでIOErrorEventをハンドリングすればOK。

[iPhone]UISliderのつまみ(thumb)を独自の画像に変更するときの注意

簡単にできたようで出来てなくてちょっとはまったのでメモ

基本的にはメソッドが用意されます。

//setThumbImage
//使用例
//speedLevelSliderというUISliderが宣言してあって、Resourceに"sliderThumb.pngがあるとして
//sliderThumb.pngはwidth:100px,height:100pxとする
//通常状態
[speedLevelSlider setThumbImage:[UIImage imageNamed:@"sliderThumb.png"] forState:UIControlStateNormal];
//つまみをタッチ状態も登録しておかないとデフォルトが表示されちゃう
[speedLevelSlider setThumbImage:[UIImage imageNamed:@"sliderThumb2.png"] forState:UIControlStateHighlighted];

これだけで指定した画像につまみが変更される。
が、UISliderをInterfaceBuilderで配置した場合にはこれだけではうまくいかない場合がある。
デフォルトのUISliderのheightは23になるのだけど、自分で用意したつまみ画像の高さが23を超える場合は、はみ出した部分はタッチ領域にならない。
上記の例だとつまみの高さは100pxなので見た目はでかいつまみになっているけど、実機でタッチできる領域は中心の23px分しか反応しないことになる。
InterfaceBuilder上からheightを修正してあげればいいかと思うと、Hの領域だけグレイアウトされていて修正ができない.

なのでframeプロパティを修正して描画領域を書き換えてあげないといけないのでした。

//変更前
//Sliderのx,y座標やwidthはInterfaceBuilderから確認
speedLevelSlider.frame = CGRectMake( 10, 200, 200, 23);
//変更後
//(実際は左上基準なので、つまみが大きくなった分、y座標も修正する必要あります)
speedLevelSlider.frame = CGRectMake( 10, 200, 200, 100);

/////////////////////////////////////////////////////////////////////////////////////////////////////////
というようなことが下記のブログには、しっかり書かれていましたのですが、、
スライダーバー(UISlider)のカスタマイズ的:いまログ
細かいところが理解できずに結構はまってしまった。。。

[AS]SWFSizeを使うとIE6でフリーズする場合はDTD宣言に注意する

はまったのでメモメモ。

FlashをHTMLでの領域を指定できる便利ライブラリSWFSize。
Progressionにも採用されてて単体で使うケースがあんまりなかったのだけど、単体で使ったらIE6だけでエラーになった。
具体的には最低サイズ以下(resizeが機能したとき)になるとブラウザが固まる。

なんだこりゃとググってみると開発者のHIGEさんからのコメントが。

さらにググるとボクのケースでの原因と一致する記事を発見。
IEでonresizeの操作がうまくいかない – Miuran Business Systems

具体的にはDTDがonresizeに対応していなかったということ。

<!--最初に書いてた宣言-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<!--修正した宣言-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!--"http://www.w3.org/TR/html4/loose.dtd"を削除-->

普段DOCTYPE宣言とか意味もよくわからず呪文のように書いてる(正確にはコピペ…)からこういうところよくわからんです。。

[AS]fl.swcを使った際にちょっとはまったこと

ちょっとはまったので検索用のメモ

FlashIDEを使わずにFlexSDK(FlashDevelop)で製作中に、Flashのコンポーネント(具体的にはComboBox)が使いたいと。
FlashDevelopにはコンポーネントのライブラリが入ってない。
どっかにないかなと探すとfl.swcってやつが見つかった。

EVOLVE | Downloads

DLして、プロジェクトにライブラリパスを通すとコンポーネント系のコード補完がでるようになってインスタンス化することもできるようになった。

がしかし、addChidすると以下のようなエラーがでる。

TypeError: Error #2007: パラメーター child は null 以外でなければなりません。
at flash.display::DisplayObjectContainer/addChildAt()
at fl.controls::BaseButton/drawBackground()
at fl.controls::BaseButton/draw()
at fl.core::UIComponent/drawNow()
at fl.controls::ComboBox/drawLayout()[D:\DEVELOP\test_lib\fl\controls\ComboBox.as:1500]
at fl.controls::ComboBox/draw()[D:\DEVELOP\test_lib\fl\controls\ComboBox.as:1421]
at fl.core::UIComponent/callLaterDispatcher()

たぶんコードはあるけど、アセット的なグラフィックデータが用意されてないんじゃないかなぁ、と。
ランタイムエラーかつ、妙な時間差で発生するので、何が悪いかわからなくてちょっとはまってしまった。
対策としては、FlashIDEからあらかじめComboBoxクラスを埋め込みアセットクラスでswcとかにして書き出しておき、それを使えばaddChildしてもエラーにならずに使うことができるよ、と。

あらかじめ、コンポーネント一式を含んだオレオレswcを用意しておいてもいいかもね。

[Event][AS]スクリーンセーバー作りました。>>Re-BUILD

先日、東京てらこ 15で発表してきたお話をメモ。

本題は、スクリーンセーバーDL用の特設サイト作りましたよってお話。
Re-BUILD

////////////////////////////////////////////////////////////////////////////
まず最初からスクリーンセーバーを作ろうと思ったわけじゃなくって。。
以前から考えてたネタをワンダフル用に作ってたら、アレもコレもとだんだんと手がこんできたので、これスクリーンセーバーにすればいいんじゃね、と。
じゃあSWFをスクリーンセーバーにするにはどうすりゃいいの?ってことで調べてみました。

ざくっとググって以下の二つが見つかりました。

1)は完全無料でいろいろかゆいとこに手が届くような感じだけどmac用は不可
とりあえずwin用にはこっちを使いました。

2)はwin/macどちらも対応で、低機能の無料版と高機能の有料版があるんだけど無料版ではOSX10.6用(64bit版)の対応はできない、と。
win用/mac用で個々にライセンスが分かれていて各ライセンスが19,800円
win/mac、まとめて買うと34,800円。
mac用にはこっちの有料版を使いました。
・・・えぇ、mac用のライセンス買いましたよ。19,800円。

////////////////////////////////////////////////////////////////////////////
あと製作に関する裏話的なこと。

もともとは数年前にみた海外のサイト(たぶん製作会社だったと思う。。)で、地平線がみえるようなシンプルなランドスケープなデザインに、ランダムに家がでてきてスクロールして流れていくようなやつをみたときに、こういうの作ってみたいなーと思ってたのが最初。
(当のサイトはググっても見つけられず。。思い出補正でぜんぜん違うものかも。。)

なんとなくChemical Brothers – Star Guitarを思い出した人もいるかも
Chemical Brothers – Star Guitar
これ、好きなんです。DVD持ってます。

あと、groovisions – GRV2196を思い出した人もいるかも
GRV2196
これ、好きなんです。DVD持ってます。

++++++++++++++++++++++++++++++++++++++++++++
GRV2196はyoutubeになかったけどGRV2126を発見。
これは観てなかったのだけど、トラックの形とかそっくりだったw
(トラックは軽トラの側面画像を適当にトレースしてたんだけどね)

////////////////////////////////////////////////////////////////////////////
元になるソースはwonderflにアップしてあります。
(実際にスクリーンセーバーに使ってるものとはちょっと違います)
なにげに車を描画するクラスがボリュームありますw

Re-BUILD – wonderfl build flash online

[GAE/J][Event]FLASHerによる【初めてのGAE(GoogleAppEngine)】

先日、東京てらこ 14に参加してきました。

GoogleAPIということで「はじめてのGAE(GoogleAppEngine)」というテーマで発表しました。

発表のスライドはこちら。
【初めてのGAE/てらこ14発表資料】

///////////////////////////////////////////////////////////////////////////

環境設定のざっくりとした流れ
1.Eclipseのインストール

2.Eclipseの日本語化

3.(Eclipseへ)Goolge Plugin for Eclipseのインストール

4.(Eclipseへ)Slim3 Plugin for Eclipseのインストール

1~3.については以下に詳しく書いてありました。
Google App Engine for Java(GAE/J)プログラミング入門: 「開発環境の準備からデプロイまで」 (1/5)
※一点だけはまったのは日本語化する際に、Eclipseのインストール場所に注意
気持ち的にc:\Program Files\eclipseにインストールしたところだけど、途中のファイルパスにスペースの入ったフォルダがあるとだめみたい。
というわけで、c:\にインストールしました。

4.に関しては以下に詳しく書いてあります。
Slim3 日本語サイト(非公式)
※Eclipse3.4と3.5をサポートと書いてありますが、3.6でも一応できるようです。

///////////////////////////////////////////////////////////////////////////

実際に作ってみたサンプル
393.bz/Invader
GAEと連動してレトロアーケードゲーム的なネームエントリーによるスコア共有の仕組みを仕込んでいます。
(NAMEとSCOREをGAEのDatastore(DB的なもの)に保存し、別ドメインからアクセス)
///////////////////////////////////////////////////////////////////////////

作成したGAE/Jのプロジェクト一式はこちら
Flash2GAE(10MB)

一応invaderゲームプロジェクト一式はこちら
(やっつけ書いたのでソース汚い。。)
InvaderForGAE(1MB)

///////////////////////////////////////////////////////////////////////////

今回のポイントは、別ドメインからGAEのドメインへのアクセス。
何もしないとセキュリティポリシー引っ掛かりますが、crossdomain.xmlをGAE側においてあげれば問題ないみたい。
配置の仕方は、GAEのwarフォルダ内にcrossdomain.xmlを置いた状態でデプロイ処理(アップロード)をするだけ。

不明なところがありましたら、コメントなりどうぞ。
(というかJavaはぜんぜんよくわかってませんが…)

///////////////////////////////////////////////////////////////////////////
PS.
他の方の発表を聞いて、Python+AMFの方が楽そうだなぁと思ったのでそっちも試してみたいところ。
pyAMFというライブラリがあるみたい。
さらにもっとお手軽なのは、PREAIR
これならJavaもPythonも書かなくてもAS3だけでGAEと連動できるサービス作れちゃう!

[GAE/J]Slim3プロジェクトでjava.lang.ExceptionInInitializerError at org.slim3.datastore.DatastoreFilter.doFilter(DatastoreFilter.java:68) が出続けたけどいつのまに直った。

謎謎謎。。。

java.lang.ExceptionInInitializerError at org.slim3.datastore.DatastoreFilter.doFilter(DatastoreFilter.java:68)

Slim3 日本語サイト(非公式)を見ながらSlim3プロジェクトを生成しHelloWorld的なことをやろうと思ったら、上記エラーが発生
コード書いてないんだから当然DatastoreFilterとか使ってるわけがなかろうに。。。

同じような人がいたけど、ごにょごにょしてたら直ったらしく原因わからず。。。

べつのチュートリアルを覗いてみたところ、

Slim3プラグインいれてみた

repackaged-appengine-jakarta-standard-1.1.2.jar
↑をBuildPathに追加とあったので試したら、エラーがでなくなった。
ただし、ビルドパスからはずしてもエラーでないまま。。。
ホントにこれが原因だったのか・・・?

謎謎謎。。。

>2011.03.26追記
なんとなくわかった。
上記作業は必ず必要。
ビルドパスパスからはずしても問題ないというのは、ビルドパスを通すとwar/WEB-INF/libに必要なjarがコピーされるので、コピー後はビルドパスからはずしても問題ないということみたい。

[GAE/J]JSONPなサーブレットにクロスドメインでアクセスできるようにするには

GAEもJavaもまるでわかってないけど、わからないなりに調べたことをメモ。

JASONPを返すようなサーブレットを作ったとして、クロスドメインでアクセス可能にするには、

“Access-Control-Allow-Origin”に”*”を設定する。
具体的には、

resp.setHeader("Access-Control-Allow-Origin", "*");
//※resp:HttpServletResponseインスタンス

あとこんな感じでMethodも設定が必要らしい。

resp.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, DELETE, OPTIONS");  

ただこれだとIEだとダメらしい。
Ajaxならクロスドメインで値が取れた。

参考記事
Google App Engineでクロスドメイン通信
※GAEソースはPython

ちなみにFlashではセキュリティポリシーひっかかってダメだった(なぜ?)
もちろんGAE元にcrossdomain.xmlを配置すればOK。

※元にしたGAEのDataStoreいじるサーブレットのサンプルはこちら
「Google App Engine for Java(GAE/J)プログラミング入門」