« 2007年05月 | メイン | 2007年07月 »

2007年06月27日

自動宣言と手動宣言のコンフリクト

バッドノウハウ気味ですが誰も書いてないようなので、後続の人たちのためにもそろそろ書いておきます。


FlashCS3でスクリプトを外部asで書く人は必ずステージのインスタンスを自動宣言のチェックを外しましょう。
このチェックはパブリッシュ設定のActionScript3.0設定のところにあります。


オーサリングツール上でテキストやムービークリップを配置しておくとスクリプトで addChild する必要がなくなりますが、それ以外に何らかの制御をas側で行うには必ず宣言しておく必要があります。
ですが、上記のチェックを外し忘れているとas側で宣言しているにも関わらずFlashCS3側で勝手にフレームに宣言文を挿入するようで、コンフリクトが発生してコンパイルエラーから抜けられません。


これってどこにも説明がないので微妙にスクリプトかじり始めた人にはかなり危険な罠っぽい。

2007年06月21日

Adobe EDGE

Adobe EDGE ニュースレターにインタビュー記事が掲載されました。
写真は掲載されていませんが、開発担当として技術的なコメントをさせていただきました。


もともとショーケースに載るという話は聞いてたんですが、EDGE の方にも掲載されるということを失念したまま、Twitter でむらけんさんが Apoll(AIR) についてのコメント募集をしているのに乗っかってしまい、会社名義での本名とブログ名義でのハンドル名が両方 EDGE に載るという珍妙なことになりましたとさ。。。


コメントを寄せた Apollo(AIR) についての記事はこちらです。


すごいクサいこと言っちゃってますが、実際問題として世の中のデスクトップアプリ開発者に比べて WEB クリエイターのアドバンテージは魅せる演出力だと思っているので、それをどこまで発揮できるかが勝負どころではないかと思います。
ただ高機能なアプリを作るだけならやはりまだまだCやJavaの開発者に一日の長があるので、同じものを作るにしてもより多くのユーザに「使ってみたい」と思わせるだけのインパクトを与えられるアプリを作っていきたいですね。

そのためにはまず何ができるかを知っていく必要があるので、気がついたことがあったらブログにまとめていきたいと思います。

2007年06月20日

ユーザをほぼ確実に落とす方法

異性をほぼ確実に落とす方法を読んで、その昔 RagnarokOnline オープンβテストの頃にまわりの友達を含めて妙なはまり方をしていたことを思い出した。


あれも一種の感情体積操作なんだよなあ。


終わりの見えないログインマラソン。
入れるようになったと思ったら今度はラグの嵐。
束の間の快適化。
予告なしの新機能実装。
なんとなく偏りのあるレアアイテム出現確率。


あれが最初からひたすら快適な環境だったらすぐに飽きてたかもしれない。
もちろん全く改善の見られないサポート体制なら早々に見捨てていただろう。
どう考えても振り回されていたとしか思えない。


特筆すべきは、飽きたのがちょうど快適になって大きな変化がなくなった頃だったような。

2007年06月19日

invisibleのススメ

こないだの勉強会で出した小ネタ紹介をば。

as1ネタになりますが、表示/非表示を制御する _visible の裏プロパティとして新たに _invisible を定義します。
分岐条件などでわざわざ !_visible のように否定をとるような状況が続くとコードが汚く見えたので、なんとなく用意してみました。


最初から prototype プロパティとして登録してしまってもいいのですが、好みの問題があるので以下のような prototype プロパティ追加用メソッドを用意しておきます。

function registerInvisible( target ){
    var setter = function( value ){
        this._visible = !value;
    }
    var getter = function(){
        return !this._visible;
    }
    target.addProperty("_invisible", getter, setter );
    ASSetPropFlags( target, "_invisible", 1 ); // 列挙ロック
}


たとえばムービークリップ全てに _invisible プロパティを追加したい場合は、以下のように記述します。

registerInvisible( MovieClip.prototype );


ちなみに as3 なら普通に public なメンバとして用意して、getter と setter を定義すればおしまい。
実行中に追加定義するには Proxy クラスを継承しなければいけないとか色々ややこしいので、最初から定義しておいた方がよさそうです。

_invisible なんて可読性下がるぜ!なんてツッコミは大歓迎。
はっきりいって好みの問題です。

2007年06月18日

駆け引き大好き扉の外

30を目の前にして未だにライトノベルをツマミ食いしてたりするのですが、いわゆる"ゲーム理論"好きにオススメできる小説を紹介してみます。





いわゆる"ゲーム理論"好きと書いたのは心理的な駆け引きを主体とした小説だからなのですが、分かりやすい例を挙げれば「ライアーゲーム」をとっつきやすくして、さらに恋愛沙汰を絡めたような感じです。
映画「CUBE」に近いものもありますね。

設定に多少無理があったりと粗探しはいくらでもできますが、読んでいるうちに「俺だったらもっとこうする」みたいなプチつっこみ&考察がいくらでもできるところが面白かったです。
ストーリー自体にはあまり期待しすぎない方がいいかも。


ゆくゆくはこの手の駆け引きを行うネットワークゲームを作ってみたいなと考えています。
以前作った THE DAY OF SAGITTARIUS もそれなりに駆け引き要素がありますが、元ネタありきの作品なのでなんとかオリジナルに手を出したいところ。


「囚人のジレンマ」「3すくみ」「ルシファー効果」といったキーワードに少しでもピクっときた人は是非手にとってみることをオススメします。

コード品評会もどき

先日 taka@nium さんとメッセで以下略もとい参照といった具合で、Taka@fladdictさんtaka@niumさんyossy@beinteractiveさんと4人でas勉強会を行いました。

これまで参加した勉強会や、Twitterでの発言、身近な友達との会話でもよくあったことなのですが、どうにも他人に発破をかけるのが大好きなようです自分。
今回も散々発破かけまくりました。。。でもほんと期待の裏返しなんですよ!
そうすることで自分のモチベーションアップにも繋がるしー

僕が発表したのはちょっとしたJSFLと現在開発中のBulletMLエディタです。

JSFLは端的に言うとFlashIDEでの手作業を全て再現できるプログラムで、あーこの作業うざいなあと思ったら作るとあら便利なものです。
便利さの割に国内での認知度があまりに低いので、Snippetsで一発集めてしまうのもよさそうですね。
チケットが全く増えてないけどw

BulletMLエディタはずいぶん前に個人サイトで公開していたものなんですが、投稿機能を付けたのとデザインやコードに若干手を入れています。
ほんとは全部as3で作りたかったんですが、母体があまりにas1だったのでエディタ部分だけas1で組んで、実際に弾幕がほとばしるプレビューだけas3で作っています。
今は壮大にバグが発生しているのでそれが取れたら公開予定。


なんだかんだいって楽しかったけれど、やりたかったソースコード品評会ができなかったのが残念でした。
ソースコードであーだこーだいうには、完成品を持ってきてはいけないなというのが今日得られた教訓w
開発中あるいはお蔵入りになった未完成品なら、他人のソースコードに口出ししやすいし口出しされたい。
もしくはちょっとしたお題を用意して参加者全員が同じものを作り、そのソースコードを比較するというのもよさそうなので、次回は是非やってみたいなと思います。

2007年06月16日

ガーベジコレクション発動!?

いつのまに追加されていたのか気付かなかったんですが、おそらく上条さんのブログで公開されている playerglobal.swc の最新版を入れてからか、とんでもないものがFlexBuilder2のコードヒントに現れました。

flash.system.System.gc()

GC任意発動ktkr
定義だけかと思ったら、ちゃんと動いてるー

メモリリークに悩まされてきた ASer にはかなり朗報なんじゃないでしょうか。

2007年06月15日

AIRのドラッグ&ドロップ起動について調べてみた

任意のファイルをAIRアプリのアイコン上にドラッグ&ドロップして起動した時に、そのドロップされたファイル情報を取得する方法について調べてみました。


AIRアプリの起動情報に関しては flash.system.Shell クラスが把握していますが、プロパティとして直接参照はできません。
その代わりに flash.events.InvokeEvent から参照することができます。

どのタイミングでもいいようですが、起動時に必要になることが多いため applicationComplete に設定したメソッド内に以下のように記述しておくことにします。

Shell.shell.addEventListener( InvokeEvent.INVOKE, onInvoke );


そしてイベントハンドラを以下のように記述します。

private function onInvoke( e:InvokeEvent ):void {
for ( var i:uint = 0; i < e.arguments.length; ++i ){
var file:File = new File( e.arguments[ i ] );
}
var currentDir:File = e.currentDirectory;
}


InvokeEvent の arguments プロパティは、起動時に渡されたファイルのフルパスを格納した配列引数の配列です。
コマンドラインからの実行により任意の引数を渡すことができますが、デフォルトでは何も指定されていないためファイルをドロップした場合はファイルのフルパスのみが格納されます。

たとえばショートカットの設定に /a というコマンドを自前でつけてしまうと、arguments の先頭要素が /a という文字列になり、その後にドラッグ&ドロップ起動時のドロップしたファイルのフルパスが続くことになります。

このフルパスはあくまで文字列なので、実際にファイルを読むためには File インスタンスをパス情報から自前で生成する必要がありますが、コマンドラインから実行された時のことを考慮して有効なパスかどうか念のため確認した方がよさそうです。
ディレクトリをドロップした場合はディレクトリのフルパスのみが渡され、ディレクトリ内の全ファイルが配列に格納されるわけではありません。


currentDirectory プロパティは、起動パス情報を持つ File インスタンスです。
設定ファイルなど AIR アプリの格納ディレクトリ下に置く場合には、ここから参照すればよさそうですが、たまに正確な情報を返さないことがあるようなのでもう少し探ってみます。


ドロップ起動に対応するアプリが作れるなら、やれることが大幅に増えますね。

----追記----
arguments プロパティの説明について若干誤りがあったので書き直しました。
ドラッグ&ドロップ起動だけでなく、隠しコマンド起動をつけられるということですね。

2007年06月13日

AIRにドラッグ&ドロップできるものについて調べてみた

AIRアプリにドラッグ&ドロップするためには、NativeDragEvent.NATIVE_DRAG_DROP についてイベントリスナ登録する必要があります。
そこで登録したイベントハンドラが呼ばれる際に引数として渡される NativeDragEvent インスタンスに transferable というプロパティ(TransferableDataインスタンス)があり、そこにドラッグしたデータの情報が全て格納されています。


せっかくなのでどういったものをドラッグすると、どういったデータが AIR に渡されるか調べてみました。

■Firefoxで表示した Web ページのリンクテキストをドラッグした場合

1.TransferableFormats.URL_FORMAT
 リンク先URL

2.TransferableFormats.TEXT_FORMAT
 リンク先URL+テキスト


■Firefoxで表示した Web ページの画像(リンクなし)をドラッグした場合

1.TransferableFormats.URL_FORMAT
 画像URL

2.TransferableFormats.BITMAP_FORMAT
 画像をビットマップデータ化したもの

3.TransferableFormats.FILE_LIST_FORMAT
 おそらくビットマップ化する際に格納したらしき画像ファイル
 格納先 C:\Documents and Settings\{username}\Local Settings\Temp

4.TransferableFormats.TEXT_FORMAT
 画像URL+代替テキスト


■Firefoxで表示した Web ページの画像(リンクあり)をドラッグした場合

1.TransferableFormats.URL_FORMAT
 リンク先URL

2.TransferableFormats.BITMAP_FORMAT
 画像をビットマップデータ化したもの

3.TransferableFormats.FILE_LIST_FORMAT
 おそらくビットマップ化する際に格納したらしき画像ファイル
 格納先 C:\Documents and Settings\{username}\Local Settings\Temp

4.TransferableFormats.TEXT_FORMAT
 リンク先URL+代替テキスト


■PC上のファイルとディレクトリをまとめてドラッグした場合

1.TransferableFormats.FILE_LIST_FORMAT
 ファイルとディレクトリそれぞれのFileインスタンスを格納した配列


■Flashオーサリング環境のステージに配置されているムービークリップをドラッグした場合

1.TransferableFormats.BITMAP_FORMAT
 ムービークリップをビットマップデータ化したもの


■Flashオーサリング環境のステージに配置されているテキストをドラッグした場合

1.TransferableFormats.BITMAP_FORMAT
 テキストをビットマップデータ化したもの


WebページについてはFirefoxで確認しましたが、IEではリンクをドラッグできなかったため割愛しました。
Win版Safariでも若干挙動が異なるようです。

Flashオーサリング環境の配置シンボルについては複数まとめてドラッグすると多少縮小されてしまうのがよく分からない仕様ですが、ビットマップ化された状態とはいえ何か面白いものが作れそうです。

2007年06月12日

PrintScreenした画像をAIRで表示させてみる

前回のエントリではクリップボードの文字列データを問題なく拾えることが分かったので、次は PrintScreen でキャプチャしたデスクトップの画像を AIR アプリ内に表示できるかどうか試してみました。

前回言及したクリップボードアクセス用クロージャ内に以下のように記述することでビットマップデータが拾えます。
サンプルなのでエラーチェックとかそういうのは省略。

var data:TransferableData = ClipboardManager.data;

if ( data.formats[0] == TransferableFormats.BITMAP_FORMAT ){
var bd:BitmapData = data.dataForFormat( TransferableFormats.BITMAP_FORMAT ) as BitmapData;
}

で、実行したら

air_printscreen.png

あれ?
.icoしか拾ってなかったりする?
どういう構造になってんだろ。。。某ウイルスもどきが作られないように対策でもしたのかなと勘ぐってみました。
キャプチャ画像をクリップボードから直接あれこれするアプリは今のところは作れないようです、残念!

2007年06月11日

クリップボードのデータを拾ってみる

Adobe Apollo が正式名称 AIR として公開されました。
同時に FlexBuilder3 のパブリックベータ版も公開されたので、追加された機能をふんだんに使った AIR アプリが続々と出てくると思います。


今回新たに追加された機能の中で特に注目すべきはデータベースモジュールでしょう。
flash.data パッケージ以下に SQL 関連クラスがごっそり入っていますが、ざっと目を通しただけでもかなり充実している模様。
このタイミングで入ってくるとは思っていなかったのですが、先日公開された Google Gears でローカルデータベースの機運が高まりつつあるので、それに合わせてきた感じがしないでもありません。

とにかく弄ってみたい機能が目白押し。
前々から気になっていたドラッグアンドドロップやクリップボード管理のドキュメントを真っ先にチェックしてみました。
たとえばクリップボードのデータを拾うには以下のように書きます。


ClipboardManager.accessClipboard( onAccessClipboard );


private function onAccessClipboard():void {
var data:TransferableData = ClipboardManager.data;
var text:String = data.dataForFormat( TransferableFormats.TEXT_FORMAT ) as String;
}

いつでもクリップボードのデータにアクセスできるわけではなく、処理を記述したクロージャメソッドを引数として ClipboardManager.accessClipboard メソッドを実行することで初めてアクセスできるようになります。

データは TransferableData 型としてClipboardManager.data に格納されていますが、中身がテキストだったり画像データだったりするので dataForFormat メソッドによってフォーマット指定する必要があります。


また、逆にクリップボードに文字列データをペーストする場合は上記のクロージャ内に


var data:TransferableData = new TransferableData();
data.addData("hoge", TransferableFormats.TEXT_FORMAT );
ClipboardManager.data = data;

といった処理を記述します。


ヘルプにわざわざクロージャと書かれているのが気になったのですが、任意の文字列をクリップボードにペーストしようとする際に ClipboardManager.accessClipboard の引数に直接指定ができないので、下記のようなクロージャ生成メソッドを用意してねという意味なんだと思います。

ClipboardManager.accessClipboard( pasteString("hoge") );
private function pasteString( str:String ):Function {
	return function():void {
		var data:TransferableData = new TransferableData();
		data.addData( str, TransferableFormats.TEXT_FORMAT );
		ClipboardManager.data = data;
	}
}

2007年06月10日

うっかり限界突破

一瞬はまりかけたので備忘録も兼ねて。

int や uint 型の変数に Number.POSITIVE_INFINITY を代入すると 0 扱いになります。
あたかも初代スーパーマリオの無限1UPで128突破すると死んだら突然ゲームオーバーみたいな(ちょっと違う
なお、以下の4種は強制的に0になります。

・Number.POSITIVE_INFINITY
・Number.NEGATIVE_INFINITY
・Number.MAX_VALUE
・Number.MIN_VALUE

Number に定義された定数なんだから Number 型変数にしか正しく代入できません。
そりゃそーだ。

でも逆に int.MAX_VALUE はちゃんと Number 型変数に代入できる。
そりゃそーだ。

せめて最大値(最小値)に丸めてくれたらいいのになーと思った日曜の昼下がりでした。
とはいえ、丸められてたらこのことに気付かないままだったかと思うとなんだかなー

~ せっかくなので試しにイロイロやってみた ~

new Array( uint.MAX_VALUE + 1 ); // ランタイムにお叱りを受けた

var arr:Array = new Array( uint.MAX_VALUE );
arr.push( 0 );
trace( arr.length ); // 0になったよー

stage.frameRate = Number.POSITIVE_INFINITY;
trace( stage.frameRate ); // どうやら1000で打ち止めらしい

あわせて読みたい