こんばんわ。
今回はですね、ぼんやりわかってるつもりでいたProgression4を実務案件に使い始めたら思うように動かせず途方に暮れた昨今の僕が、備忘録として引っ掛かってた箇所を挙げていくエントリーです。
ある時はTwitter上でうるさくヘルプを求めて叫んだり、またある時は休日にも関わらず知り合いFlaherさんに直接スカイプ通話を繋いでもらったり、はたまたProgression4勉強会に急遽駆け込んだりしてたわけなんですが、いざ原因をまとめてみるといかに自分が初歩的なところから抜け落ちてたんだなということがわかりました。まあ、それでもコレを見て救われる人がもしかして居るかもしれないので書き残しておきます、ってことで。
単独swfではちゃんと動作するのに、preloader.swfを介して複数swfを読み込むと挙動がおかしかった時の原因
「うまく・・・いかないです・・・><」などとTwitter上でわーわー叫んでいたら、
Flasherのみなさんが口々に「コンフリクトがどうのこうの」と返信してくれました。
いくつか抜粋させていただきます。
「コンフリクトエラー」って殴り書いた紙をぐちゃぐちゃにしてるよ!
(by 私)
僕の、得体の知れないコンフリクトエラーに対する八つ当たりがTwitterのタイムラインをコダマする。。
↓↓↓
デフォルトで、リンケージのみのクラスは自動生成されるから、実質からのMovieClipのサブクラスが補完されるのでクラスのコンフリクトが起こるときもあるよ。同じリンケージを設定できないのも、事実上クラスがコンフリクトするから。
(by @doke さん)
たぶん、デフォルトで ApplicationDomain が currentDomain 指定になっていて、コンフリクトしまくってるんだと思われまっす。ここらへん prog ってよりは AS3 のとっつきにくさから来てると思います。
(by @soundkitchen さん)
SWFで親子構造になるときって、たいていクラス側でパッケージ名を変えてやるのが定石ですかね。クラス名がかぶってもパッケージ違うからOKみたいな。ただ、Main重複は見通しがよくないので避けたりしますね。
(by @naggg さん)
今思い出したけど、わたしもpreloader通すと読めなくなるって現象やったわ。原因は子swfでも画像とか読むために同じ名前で中身のちがうloading使ってたから。
(by @chabudai さん)
もっと言うと、僕が作る場合はかなりがっしり仕様固めるという頭の悪い作りで、ライブラリのリンケージ書き出しのとき、たとえそのクラスが存在しない場合でも(例:ビットマップのリンケージ設定)、パッケージ名を設定するようにしてます
(by @nagggさん)
うわーーーみなさんありがとうございます!!めちゃくちゃありがとう!
この助けてくれた方の中から抽選で1名の方に金塊を送らせて頂きました!
えーとですね、これらをまとめると。。
親swfから複数の子swfを読み込む際に、それぞれのswf同士で定義したクラスやリンケージに同じ名前のものがあるとコンフリクト(衝突)して、内容が上書き?無効化?されてしまい、意図しない命令が実行されたり別の箇所のパーツが読み込まれたりしてしまいます。
なので、これを回避するには、それぞれのswfで定義するクラス名やリンケージ名が他と被らないように命名するか、新しい別のApplicationDomainを定義してそちらで読み込むかするといけると思います。
僕の場合は、全てのswfのドキュメントクラスを「Main.as」としてましてコンフリクトの嵐が巻き起こっていたようです。。複数swfで組むようなサイトはファイル構成も気をつけないといけないですね。。
ちなみに、これはProgressionがどうのこうのというよりはAS3の仕様的なルールだそうですので、Progressionは悪くありませんよ!
(ちょっとでも疑ってごめんなさいw)
「アプリケーションドメイン(ApplicationDomain)」ってなんですか?
アプリケーションドメインという概念は、クラス定義の親子関係やグループ分けを管理するためのもの、と本に書いてあったのですが、まだあんまりよくわかってないのでw、他サイトさまのわかりやすいエントリーを参照してくださいませ。
- Adobe ActionScript 3.0 * ApplicationDomain クラスの使用
- 親SWFと子SWFと同名クラス | eternity design BLOG
- AS3.0 | ApplicationDomain 知らんかった – DUBFLASH
addCommandの中と外に命令書いた時の処理の違い
処理の完了を待って上から順に実行してくれるという便利なaddCommand内で、
new AddChild(container, CastObject)するという当たり前の作法を私は疎かにしていたのだった。
どうりで、CastObjectの atCastAdded()、atCastRemoved()が機能しないわけだ。。
同様に、addCommandの外に、Tweener.addTween()も書いていましたが、やはりonCompleteを書こうが終了は待たずにシーンは遷移していく罠にハマってしまってました。まーそりゃそうですよね。。
なぜこういう書き方に固執してたかというと、
addCommand内でのfor文の書き方がわからなかったからなのです。
こうやろうとしてあがいてました><↓↓↓
addCommand( function(){ for (var i:int = 0; i < ITEM_MAX; i++ ){ var btn:HogeButton = new HogeButton(); new AddChild(container, btn); }, "ボタン生成できたかな?どう?" //できるわけねーよどうすんだよこれ・・ } )
という書き方でエラーが出て困っていたところ、最寄のFlasherさんに相談したところ正解な書き方を教えてもらいました。
addCommand( function(){ for (var i:int = 0; i < ITEM_MAX; i++ ){ var btn:HogeButton = new HogeButton(); this.parent.insertCommand( new AddChild(container, btn) ); } } )
なんかうまいことinsertCommand()を使うようです。この書き方でうまくいきました。
ikekouさん、教えてくれてありがとう!かっこいい!今度ラーメン奢ります!
その他のつまづいた箇所
- 子swfのコンストラクトでstageを参照しようとしてたらエラー出ました。
public function Constructor(){ if (!stage) addEventListener(Event.ADDED_TO_STAGE, init); else init(); } private function init(e:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); //初期設定 }
こういう書き方で回避できましたっけ?
まあとにかく、いきなりコンストラクタでstage参照したらnullになってエラーで止まりましたっていう事例です。
- alpha=0の透明DisplayObjectを消し忘れてて下層がクリックが出来なかったです。うっかりしてました。
それはうっかりだね気をつけよう。(だんだんコメントが適当になってきました)
閉め
というわけで、助けてくれたみなさん。
大変お世話になりましてありがとうございました!貴方が居るから僕も居る、よくわかりませんがそんな感じです!
僕もProgression乗りこなせる様に頑張っていきますので、今後ともよろしくお願いします!
「説明書をよく読まないタイプの僕がProgression案件でつまづいて泣きそうになってた箇所を今夜ついに発表!」への1件の返信
[…] ドメインにApplicationDomain.currentDomainを指定します。 アプリケーションドメインについてよくわからない人は、ここを見てたらい回しにされるか、諦めて上のソースをコピペしてください。 […]