前回のエントリでは、サーバで生成した FlashLite コンテンツを配信するケータイサイトの開発/制作フローとして、以下のような流れを紹介しました。
- SWF への入出力(input/output)に見通しを立てる (全員で)
- Flash IDE でプロトタイプの fla ファイルを制作し、SWF でパブリッシュ (デザイナ)
- SWF 中の何(What)を、どのように動的にいじりたいかを整理 (全員で) (ここまでが前の項)
- 動的にいじる手段を選択 (主に開発者で)
- 決定した手段に応じて、SWF への入出力を決定 (主に開発者とデザイナで)
- fla の制作ルールを決める (主に開発者とデザイナで)
- 上の制作ルールに基づいて Flash IDE で fla ファイルを制作し、本番用の SWF をパブリッシュ (デザイナ)
- 制作した SWF を必要に応じてテンプレート化する (開発者もしくはデザイナで)
- テンプレート化した SWF をいじるアプリケーションを実装する (開発者)
- できあがり。運用時の更新は、7〜8〜9の繰り返し
前回は、このフローの4まで、つまり SWF をサーバ上でどのようにいじりたいかを検討し、そのための手段(ツール)として、swfmill を選択する、というところまで紹介しました。
今回は、具体的なコンテンツを想定しながら、このフローの5以降の流れについてまとめていきたいと思います。
サンプルコンテンツの概要
動的にいじるサンプルコンテンツとして、以下のような背景画像+キャラクタのアニメーションを再生するシンプルなFlashLiteコンテンツの動的生成要件を考えてみます。(上記のフローの 3 までの検討結果イメージについても併記してみます。)
- ステージサイズは 176×208
- 背景画像とキャラクタのアニメーションをステージ上に持つ
- SWF を動的に生成するときの入力(input)
- 背景画像
- キャラクタ画像
- SWF 再生後の出力(output)
- なし。ただ再生するだけ
- SWF 中の何(what)をいじるのか
- 背景画像とキャラクタ画像
文字だけだとどんなコンテンツなのかイメージがわきにくいので、サンプルも貼っておきます。(DeviceCentral で再生しているものをキャプチャしています。)
今回は、このコンテンツをベースに、
- 背景の jpeg 画像を指定のものに差し替え、
- 飛んでいるキャラクタの画像とアニメーションを指定のムービークリップシンボルに差し替える
ということをやってみます。具体的には、背景画像を以下のもの:
に差し替え、さらに、キャラクタのアニメーションを、別途作成した以下のようなムービークリップシンボル:
に差し替えたものを、新しい FlashLite コンテンツとして生成することとします。(余談ですが、FlashLite の動的生成が「FlashLite の(動的)合成」と表現されている事がありますが、その意味するところは、上記のように「ムービー中の画像素材などを指定して、これらを組み合わせて(合成して)FlashLite の生成をおこなう」ということと理解しています。)
それでは、以下、先に紹介した制作フローの続きを紹介していきます。
SWF 生成(合成) 時の入出力を決める
先に検討した入出力を精査し、何を入力パラメタとして SWF をつくり、ムービー再生後にどのような出力パラメタをもってサイト遷移に戻るか、を決定します。今回は、以下のように決定したとします。
- 入力
- 背景画像: ステージサイズと同じ大きさの jpeg データ
- キャラクタ画像: アニメーションを伴ったムービークリップシンボルとして指定される(元のキャラクタ画像は GIF89a)
- 出力
- なし
なお、実際の要件や制作/開発の現場では、上のようにまとめられるとは限りません。「背景画像には jpeg と GIF の形式のどちらかが指定されうる」とか「キャラクタ画像は画像のビットマップのみ入力として与えるだけとし、アニメーションは固定で良い」などの要望が出る場合があります。今回は、この後のステップを紹介するのに都合が良いように要件を決めていますので、まずは以下をお読みいただいた上で、上記のような要件変更/要望の取り込みがどの辺りの開発ステップ/難易度/コストに影響を与えてきそうかを捉えていただければと思います。正直なところ、ここ以降の制作フローの詰めが、FlashLite コンテンツの動的生成をおこなう際の一番の難所(業務でやる場合は、リスク要因となりやすいフェーズ)と、個人的には感じています。
.flaの制作ルールを決める
SWF 中の差し替えをおこなう要素と、そのときに与えられる入力が決まったところで、デザイナと開発者との間でベースとなる SWF の制作ルールを決めていきます。なぜ、制作ルールを決める必要があるかと言うと、一番の理由は、プログラムから差し替えをおこなう要素が特定できるようになっていないことには、画一的な処理で要素の差し替え(SWF の動的生成)をすることができず、ベースとなる SWF ごとに処理をつくってやらなければならなくなるからです。
これは逆を言えば、ベースとなる SWF が少なく、運用時の SWF 追加や更新も無い、などの理由で、個別の動的生成処理を実装していくのにコストがかからないのであれば、この時点で厳密な制作ルールの握りをつくる必要は無い、ということにもなります。
今回は、この後の説明を簡単にする都合で、以下のように制作ルールを決める事ができた、と仮定します。
- 背景画像は、jpeg を貼付けただけのムービークリップシンボルを別途作成しておき、これをステージに配置する際に “bg” というインスタンス名を付与しておく事にする
- キャラクタ画像は、アニメーションを含める形でムービークリップシンボルを別途作成しておき、これをステージに配置する際に “animation” というインスタンス名を付与しておく事にする
上記のように、今回は、差し替えをおこなう要素をふたつともムービークリップシンボル化しておくことを仮定しています。
ただ設置するだけの背景画像を、わざわざシンボル化して、インスタンス名まで付与するのは、制作側からすれば一見非効率かも知れません。ただし、これらのルールは、先にも述べた通り、プログラム側から差し替えをおこなう要素(ムービークリップ)を特定/識別するためのルールですので、ケースバイケースと考えていただければよろしいかと思います。たとえば、「SWF 中には、背景画像として唯一 jpeg 要素を使用する」という制作ルールがあれば、「背景画像として入力した jpeg を SWF 中の jpeg データと置き換える」という処理を作ってやれば、わざわざインスタンス名で特定する必要がないということにもなります。
本番用 SWF をパブリッシュし、必要に応じてテンプレート化し、差し替え処理を実装する
上記のルールに基づいて .fla を制作し、SWF をパブリッシュしたら、いよいよ、具体的な FlashLite 動的生成処理の実装に入っていきます。
まずは swfmill swf2xml を使って、できあがったベースの SWF の構造を確認してみます。(swfmill の基本的な使い方は、他のサイトでもわかりやすい説明が多いので、ここでは割愛します。)今回のサンプル SWF は以下のようになっていたとします。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <swf version="4" compressed="0"> : 13 <DefineBitsLossless2 objectID="1" format="3" width="30" height="30" n_colormap="7"> 14 <data> 15 <data>eNq9kEsO... : 17 </DefineBitsLossless2> 18 <DefineShape objectID="2"> : 30 <ClippedBitmap objectID="1"> 31 <matrix> 32 <Transform scaleX="20.00000000000000" scaleY="20.00000000000000" transX="-300" transY="-300"/> 33 </matrix> 34 </ClippedBitmap> : 52 <DefineSprite objectID="3" frames="20"> 53 <tags> 54 <PlaceObject2 replace="0" depth="1" objectID="2"> 55 <transform> 56 <Transform transX="299" transY="299"/> 57 </transform> 58 </PlaceObject2> 59 <ShowFrame/> : 176 </DefineSprite> 177 <PlaceObject2 replace="0" depth="3" objectID="3" name="animation"> 178 <transform> 179 <Transform transX="3541" transY="1031"/> 180 </transform> 181 </PlaceObject2> : 182 <DefineBitsJPEG2 objectID="4"> 183 <data> 184 <data>/9n/2P/Y/+AAEEp.. : 186 </DefineBitsJPEG2> 187 <DefineShape objectID="5"> 188 <bounds> 189 <Rectangle left="0" right="3520" top="0" bottom="4160"/> 190 </bounds> 191 <styles> 192 <StyleList> 193 <fillStyles> 194 <ClippedBitmap objectID="4"> 195 <matrix> 196 <Transform scaleX="20.00000000000000" scaleY="20.00000000000000" transX="0" transY="0"/> 197 </matrix> 198 </ClippedBitmap> : 216 <DefineSprite objectID="6" frames="1"> 217 <tags> 218 <PlaceObject2 replace="0" depth="1" objectID="5"> 219 <transform> 220 <Transform transX="0" transY="0"/> 221 </transform> 222 </PlaceObject2> 223 <ShowFrame/> 224 <End/> 225 </tags> 226 </DefineSprite> 227 <PlaceObject2 replace="0" depth="1" objectID="6" name="bg">
swfmill を使った FlashLite の動的生成処理を作る際は、(場合にもよりますが、)
- ベースの SWF をそのまま保持しておき、動的に swf2xml => 差し替え処理 => xml2swf するよりは、
- 上記のように XML 化したものを要素を差し替え可能な状態に適宜編集して保持しておき、動的に 差し替え処理 => xml2swf したほうが、
応答速度的にも効率が良くなると思います。ですので、ここでベースの SWF の構造を XML 化しておき、差し替えをおこなう要素の構造を理解しておくとともに、この XML を差し替え可能な状態に編集し、テンプレートとして保存しておく事にします。
今回の要件では、ステージにムービークリップを配置した際のインスタンス名を “bg” または “animation” で指定してもらっているはずですので、まずはこれらがどこに位置しているかを見ていきます。FlashLite 1.1 でパブリッシュされた SWF では、ムービークリップは PlaceObject2 要素(Tag)で name 属性をともなって配置されているはずです。(このあたりの SWF の構造に関しては、Adobe 社が公開している SWF の仕様 – SWF Technology Center (必要に応じて Open Screen Project )も参考にしてください。)上記の場合では、
177 <PlaceObject2 replace="0" depth="3" objectID="3" name="animation">
の行と、
227 <PlaceObject2 replace="0" depth="1" objectID="6" name="bg">
が該当する事になります。
ここから、さらに PlaceObject2 が参照している object を辿っていきます。objectID 属性を確認すると、たとえば animation インスタンスは objectID=”3″ ですので、objectID=”3″ となっているムービークリップ要素 = DefineSprite 要素を探します。今回の例ですと:
52 <DefineSprite objectID="3" frames="20"> 53 <tags> 54 <PlaceObject2 replace="0" depth="1" objectID="2"> 55 <transform>
ここが該当します。このなかで、さらに PlaceObject2 により objectID=”2″ が参照されていますが、ここではムービークリップ内に設置されたキャラクタ画像が参照されているはずです。FlashLite 1.1 でムービークリップ内に画像を定義する方法は何種類かありますが、基本的には、
- DefineBitsLossless2 もしくは DefineBitsJPEG2 で定義した画像データを、
- //DefineShape/styles/fillStyles/ClippedBitmap で参照し、このシェイプを PlaceObject2 で配置する
というのが一般的な構造になるようです。今回は、上で指定されていた objectID=”2″ な DefineShape を辿って、さらにそのなかの ClippedBitmap というように、objectID をたどっていきます。最終的には、
13 <DefineBitsLossless2 objectID="1" format="3" width="30" height="30" n_colormap="7"> 14 <data> 15 <data>eNq9kEsO...
に行き着きます。ここの data 要素の中身が、アニメーションをおこなっているキャラクタ画像のビットマップデータということになります。今回はアニメーションとキャラクタ画像を丸ごと差し替えたいという要件ですので、このあたりの DefineBitsLossless2, DefineShape, DefineSprite の構造を、objectID の参照関係を維持したまま作り替えてやれば、アニメーション部分の差し替えができるということになります。
同様に、背景画像については上記 227 行目の PlaceObject2 で参照されている objectID=”6″ を追っていってやれば、
182 <DefineBitsJPEG2 objectID="4"> 183 <data> 184 <data>/9n/2P/Y/+AAEEp..
に辿り着きますので、この data 要素を差し替えてやれば良い、ということになります。
対象の SWF の構造がわかったところで、この XML をテンプレート化します。差し替え処理の実装方法は幾つか考えられますが、
- XML 中の置き換えをおこなう部分を場所を一意に特定できる文字列にしておき、プログラムからは文字列置換により書き換える
- 置き換え対象部分を独自に定義した要素などに編集しておき、適当な XML 操作のための API (僕の場合は、PHP であれば SimpleXML、Ruby であれば REXML や Libxml-Ruby などを使ったりしてます) を介して書き換える
などの方法があります。前者は単純な文字列置換なので、対象の SWF がシンプルであれば非常に簡単に実装できますが、その分、.fla の制作ルールや実行環境によってはバグやセキュリティホールを作り込んでしまう可能性もあるので、注意した方が良いかもしれません。
ちょっと長くなってきたので、実際の入れ替え処理を書いていくところは、次回以降にしたいと思います。
まとめ
以上、2回にわたってケータイサイトで FlashLite コンテンツを動的生成する方法の概要をまとめてきました。全体の流れが見えると、ベースとなる SWF の制作ルールと、システム開発コストがどのように関連してきそうか、が、なんとなく見えてくるんじゃないかな、と思います。
実際のところ、制作ルールの策定は、動的生成処理の開発コストを、システム開発側とSWF制作側とで分担する割合/バランスを探る作業であるようにも感じています。ですので、全体の流れや仕組みの見通しが立たない事には、実サービスにこういった仕組みを入れていくのは大変かもしれません。
FlashLite 動的生成のシステムには何回か関わらせていただいていますが、正直なところ、こういった流れ、とくに制作側にいろんな制作ルールをお願いするようなやり方が本当に良いのかどうかは見え切れていません。今でも、わりと試行錯誤しています。この手のシステムに関わった方と情報交換する機会がほとんど無いので、いろんな方のご意見をうかがってみたいです。
さて、次回以降は、今回紹介したサンプルコンテンツの動的生成の続きから、実際に FlashLite 動的生成をやっていて使用したコードや、ハマったところなどが紹介できればと思います。
長々と読んでいただいてありがとうございました。期待せずにお待ちください。
最近のコメント