ActionScript3.0エラーアーカイブスを少し読んだ。

ActionScript 3.0 エラーアーカイブス コンパイルエラー・コンパイラ警告・ランタイムエラーの解法

ActionScript 3.0 エラーアーカイブス コンパイルエラー・コンパイラ警告・ランタイムエラーの解法

エラーが出たときにここから探す本・・・というよりは「ふんふんこんなエラーがあるのか」と読むような本の気がする。

だいたいエラーを吐いて困る場合は、「こうすれば解決なのは分かってるけど、実際にその処理は何らかの理由で実装できない」という場合が多い気がするし、そもそもエラーは出ないが動きが変という場合が圧倒的に多い気がする。エラーを吐いてくれさえすればJavaScriptよりは親切な気がする。AS。

なので、これで安心のスクリプトが書ける、というよりはプログラマとして読んで楽しむもののような気がします。

先日

1084:シンタックスエラー:leftparenがcolonの前に必要です


というエラーを吐いたんですが、調べても解決しませんでした。

まあgetterに()をつけ忘れたという初歩的なミスなので数分で解決しましたが。

・・・というかエラー文をちゃんと読めばコロンの前に括弧が足りないと明確に書いてあるんですよね。ちゃんとエラー文を読めよ、と。(left parenで左括弧ですね)

エラー集もいいんですが、FlashDeveloperがハマった罠を集めたAS3罠集みたいなのがあったらすごくいいなぁと思ったりします。

カヤックさん辺りが新サービスとしてやったりするんじゃなかろうかと勝手に思ってるんですがどうなんでしょう。罠共有サイト。問題はどうやって検索させるか、ということでしょうね。どういう状況でどうなったのかという説明を文字だけでするのは至難の業で、絵を使うと検索し辛くなるので、どういう方法で検索させるかが問題になりそうな予感。でもあったらFlash作るのが少しでも楽になるかなぁと思います。

タイムラインに置いて、名前をつけたシンボルのインスタンス名を取得するうまい方法はないだろうか。

随分あけてしまいましたが、なかなか書くネタを搾り出すのも大変ですね。もうちょっと間隔を狭められるように書けたらいいなと思ってます。

今回はFlash使ってて変な現象に出くわしたのでその話。

まあタイトルの通りなんですが、タイムラインに配置して、同じシンボルを違う名前で配置する時というのはそれなりにあると思います。タイムラインに置いてしまったほうが位置の調整が楽ということもあり、たまにやります。

で、タイムラインに配置したオブジェクトを、『オブジェクトにつけた名前はそのままに、インスタンス名に応じて処理をする』という処理が必要になりました。まあASだけで配置していれば適当に名前をつけてグループ化すればよかったんですが、タイムラインに配置しているので、そうもいかない。

諦めてASで配置することも考えましたが結構な手間になってしまうので、何か方法はないか、ということで探ってみたら、擬似的に何とかできました。

方法 → 対象となるオブジェクトの1フレーム目にラベルを付ける

ラベルがついていればMC.currentLabelで取得できるので、そこから名前を情報を取得する、と。うーん、多用すべきでないテクニック臭がプンプンしますね。どう考えてもスマートじゃありません。しかしまあ、目的は達成できてるので、OKとしておきます。

調べていく過程で気づいたのは、「対象となるオブジェクト自身のタイムラインのフレームアクションに何かしらのスクリプトが記述されていればインスタンス名が取得できるようになる」ということです。スクリプト、と言ってはいますが、単なるコメントのみならず半角スペース1つ入れるだけでインスタンス名が取得できるようになります。

trace((対象オブジェクト).toString())

というような感じで。(toString()は無くても動作します。)

通常、何も書かれてなければ

[object MovieClip]

になるけれど、何かしら書かれていると、

[object インスタンス名_数字]

となるので、インスタンス名を切り出せば使えることになります。

ただこの方法だと、MovieClipでない新しいクラスが作られているようにも見えるので、あまり良くないような気もします。どちらがメモリを食うか等々は調べてないので不明です。その作り方が悪い、というのはもっともな話ですが、小細工をすればある程度のことは何とかなるようです。

↑以外でもスクリプト付けたし法ではうまく行かない条件が何かあった気がするんですが(MovieClipに変換されますのような警告がでた気が)、また同じ状況に出くわしたら書いてみます。

画像をタイムラインに置いた場合のBitmapDataへのアクセス

FlashIDE上で画像を配置して、後でそのビットマップデータへアクセスしようと思ってもうまくいかない。

例えば、ステージに画像を直接貼り付けただけのflaファイルがあったとして、1フレーム目のスクリプト

trace(this.getChildAt(0));

と書くと、

[object Shape]

となって、BitmapやBitmapDataにはアクセスできないみたい。

これをどうにかできないかと思っていろいろ情報を探してみたら、ライブラリでその画像データを『ASに書き出し』にすると、その他何も変更しなくても

[object Bitmap]

となって、画像へアクセスできるようになる様子。

つまりは画像をタイムラインに配置しているだけだと、その画像は内部的には自動でFlashIDE上で「分解」をしてShapeになった状態として認識されてるということかな?

アクセスはし辛い代わりに後でdispose()する必要もなくなるわけで、必要によりけりですが、どうしてもタイムラインに配置した画像を制御したいという時には役に立つかもしれません。

ただ、この間これをやろうとしたら、対象となるMCを作り直すときに毎回画像データとしてnewすることになるのか、ASに書き出したほうが動作が遅くなった気がします。

スクリプトで画像をnewして表示する場合も多々あると思いますが、意外とBitmapを作るよりもshapeにbeginBitmapFillした方が速かったりして。この辺は時間があるときに確認してみたいです。

緑色になる謎

Flashを使ってて、ライブラリに入ってるムービークリップが、クラスを割り当てた時に緑色のアイコンになるときがあって、ずっと何故なんだろうと思ってたんですが、最近ようやく分かりました。

原因:割り当てたクラスがSpriteである

要するにMovieClipだと紫色で、Spriteだと緑色らしい。

うーん、FlashIDE上でSpriteかMovieClipかを意識する必要はあんまり無い気がするんだけどどうなんだろう。まああるに越したことは無いのでいいっちゃいいんですが。CS3にはこの機能は無く、CS4からみたいです。ちなみにflash.display.Spriteでなくとも、これをextendsした独自クラスでもSpriteとして判定されて緑色に変化するみたいです。そんなところまで見てたのか、とちょっと感心しました。

wonderflのCHECKMATEにチャレンジしてみる

wonderfl上で行われているActionScript天下一武道会CHECKMATEに興味があったので参加してみました。

火の玉のような感じに。

wonderfl build flash online | 面白法人カヤック
(iframeだと貼れないようなのでリンクで)

面白い動きが思いついたらまた投稿してみようと思います。

swfの親の有無

たまに使おうとすると忘れてるのでメモ。

自分に親がいるかどうか確認する

this.loaderInfo.addEventlistener(Event.COMPLETE, selfLoadComp);

private function selfLoadComp(e:Event):void{
if(!loaderinfo.loader){
    //親がいない
  }
  else{
    //親がいる
  }
}

これを最初に仕込んでおいて、initializeメソッドを呼ぶ前に何か処理させれば使えるはず。「自分が読み込まれたら」というイベントは自分だけで実行した時もEvent.COMPLETEするようです。

プリローダを実装している場合や、後読みのswfファイルである場合に、親となるswfがいないときでも正常に動作させるために、親がいない場合の特殊処理を書く時に使えると思ってます。特に親ファイルでデータをロードして子供に渡す場合、これを使うと親なしで子供だけでパブリッシュして実験できるようになったりするので便利かなーと。(間違えると2重に読み込んだりすることになりますがw)

この場では関係ないですが、Loaderで指定したURLがない場合、IOErrorEventになるわけですが、この時の失敗したURLをIOErrorEvent自体から取得する方法というのはないんでしょうか。どうにもロード失敗すると、loaderInfoのプロパティが一部しか取得できないみたいで、urlその取得できない値の一部の様子。

単品だったらそれでOKですが、何個もロードしている時はどれがエラーだったのかわかると便利そうなんですけどね。loaderにname属性をつけたらなんとかなるのかな・・・?

論理演算のXORを実現する

AS3ではビット単位でのXORはできるけど(^)、論理演算でのXORは用意されていないようなので、何とかできるように工夫してみた。

普通に

if(isA ^ isB){
    //XORでtrueの処理
}

という感じで書くこともできるかと思ったら、数値型でないとパブリッシュできません。というわけで、

if(int(isA) ^ int(isB)){
    //XORでtrueの処理
}

のような感じにしたらできました。一応traceさせると、

trace(Boolean(int(true) ^ int(true)));//false
trace(Boolean(int(true) ^ int(false)));//true
trace(Boolean(int(false) ^ int(true)));//true
trace(Boolean(int(false) ^ int(false)));//false

ということでXORが実現できました。まあビット単位の演算はできる以上当たり前ですし、遅くなったりしないのかという疑問も残りますが、条件文2つ書くよりはいいかなと。

計算もビット演算使った方が早い場合もあるようなので、ビット演算についてはもうちょっと使えるようにしたい。ビットシフトとか。