FlashLite 動的生成の全てを教えます(その1?)

こんにちは。

カヤック自転車部盛り上げ担当でおなじみのaragaです。 自転車好きの方は是非一緒にヤビツ峠を登りましょう

今回は、いつか公開しようと2年間暖め続けていた、携帯サービスのFlashLite動的生成についてお話しします。

携帯サービスのFlash合成技術は、スマートフォンブームの普及により、この先の寿命は長くない技術かもしれません。しかし、モバゲーやGREEのガラケーソーシャルゲームの人気により現在進行形では最も熱い分野とも言えます。

今回はPHPライブラリの公開と、動的生成でできることの紹介をさせていただきます。

もし、携帯コンテンツのFlashで技術的に諦めて困っている人がいたら、少しでも参考になれば幸いです。

その前に、全ての機能を説明する為に、今回サンプルとして使用したサービスを簡単に紹介させてください。

ポケットフレンズコンチ

愛をモチーフにした可愛いペットのきせかえを軸に、多種多様のミニゲームで遊んだり、キノコを育てたり、 位置情報を使って道ばたに落ちているアイテムをバキュームで吸い込んだり、といった様々のコンテンツを全て可愛いペット「コンチ」と一緒に楽しむことができる超おススメの携帯ゲームです。

このゲームの大きなウリの1つに「うごき」があります。 ユーザーは50以上の「うごき」の中から好きなパターンから選んで最大4つの動きを組み合わせることができます。

うごきの動的生成は、モーションパーツのFlashのタイムラインを、ベースのFlashのタイムラインにコピーすることで実現させています。

サバイバルゲームタウン(サービス終了)

広いフィールドを移動し、銃で狙撃し合うFPS+RTSのような携帯ゲームで、コアなユーザー様には大変な評価いただきましたが、諸事情によりサービスは終了いたしました。

フィールドマップでは広いフィールドの中から常にプレイヤー周囲10x10のフィールドが見える状態で背景が変化していたのが特徴でした。

このゲームのフィールド画面では、MovieClipや画像の入れ替えはせずにテキストデータの入れ替えのみで様々なマップを生成しています

ボーリングパラダイス(モバゲータウンにて公開中)

ボウリングゲームでありながら、ピンをコレクションしたり、絶対に前を向かない後ろ向きのアバターを着せかえることができるゲームです。現在モバゲータウンにて公開されています。

このゲームのマイページで使われているFlashでは透過PNG、MovieClipの入れ替えを行っています。

FlashLite動的生成のツール

Flashの動的生成をするには用途に合わせて下記のようなツールを使います。

  • swfmill

    • ネット上でも非常に多くの情報が出ていますが、swf - xmlの双方向変換が可能なツールです。
    • xmlを編集しswfを生成するということが可能なため、swfのフォーマットを理解しXMLを操作できる技術者であればどんなものでも作ることができます。
    • しかし、swfをxmlに変換するためデータサイズが大きくなることやswfコマンドをたたく必要があるため負荷が高めになります。
  • SWFEditor

    • php拡張としてCで書かれているため非常に高速です。
    • phpでswfに画像を埋め込むなら圧倒的に早いです(当社比)。
    • しかし、様々な用途ひ合わせてカスタマイズをするにはややハードルが高い気がします。
  • Ming

    • PHPのPECLモジュールとして提供されています。
    • SWFに単純にswfを足し算するだけなら効果的な気がしますが、ドキュメントが充実していないので使い方がよくわかりません。
    • 純粋にswfを足し算するならswftoolsもおすすめです
  • バイナリを直接いじる

    • バイナリを直接操作するのも、状況によっては非常に効果的です。
    • 特にswfはフォーマットが公開されているので、バイナリ操作になれてしまえば簡単に扱うことができます

弊社の携帯チームでは、swfmillをつかった方法とバイナリを直接操作する方法を主に利用しています。

当初はswfmillのみだったのですが、変数を入れ替えるだけでswfmillを使うのは重すぎるといったこともあり、 バイナリを直接いじる手法を採用するようになりました。

SWFフォーマットについて

swfの動的生成について詳細を解説してもよいのですが、GREEのyoyaさんの記事よりわかりやすく解説する自信はないので、今回は参考の記事の紹介までとさせていただきます。

もし、とっても気になるようでしたら、僕に個人的に質問してください。とってもマニアックで楽しいひとときを一緒に過ごしましょう。

FlashLiteの動的生成をしてみよう

先に上げたような弊社サービスで利用しているPHPライブラリを公開します。

  • Media_SWF

    バイナリを直接いじるためのライブラリです。 IO_BitIO_SWFに依存しています (IO_Bitが無いと本当にめんどくさいです。)

  • swfmill

    swfmillを利用してswfの動的生成をします

今回、ライブラリの細かい紹介やリファレンスは割愛させていただきますが、 このシリーズにもし続きがあったらその時に詳細の説明をさせていただくかもしれません。

ちなみに公開したコードにはコメントなどはほとんどありませんし、大変お恥ずかしい部分も大量に残っています。 しかし、コードを整理してから公開すると言い続けて早2年が経過してしまったので諦めました。ご勘弁ください

また、次から上げていく機能については、両方に実装されているものもありますが、より高速なバイナリ版を優先して、バイナリ版で実装しているものはMedia_SWFで、swfmill版でしか実装していないものはswfmillを使ってサンプルを書いています

なお、実運用上はサンプルコードのままではなく、適宜MemcacheやAPCを用いて中間データをキャッシュしています。

ActionScript変数を入れ替える

URLや台詞、不正防止のトークン、ゲームのパラメータ等を埋め込むために最もよく使います。

// 元データ読み込み
$swf_data  = file_get_contents('path/to/base.swf');
$editor = new Media_SWF_Builder();
$editor->parse($swf_data);

// rootの最初のアクション部を取り出す
$firstAction = $editor->getFirstAction();
$firstAction->replaceValue('token', 'token'); // トークンを埋め込む
$firstAction->replaceValue('callback_url', 'http://example.com/index.php?hoge=fuga'); // コールバックのURLを指定

// 出力
echo $editor->build();

https://github.com/ken39arg/Media_SWF/blob/master/sample/100.php にサバイバルゲームタウンを例にしたサンプルを作成しました

JPEG画像を入れ替える

ユーザーが投稿した画像とFlashを合成する場合などに使います。

$swf_data  = file_get_contents('path/to/base.swf');
$editor = new Media_SWF_Builder();
$editor->parse($swf_data);

// インスタンス名でデータを取り出す為のデータを解析 
$editor->loadCharacterMap();

// BitmapID(ObjectID)を取り出す
$bitmap_id = $editor->getBitmapIdBySpriteName('/img');

// JPEGからSWFに埋め込むデータを作成
$image = new Media_SWF_Bitmap_JPEG('path/to/image.jpg');
$image->build();

// 生成したデータの埋め込み
$editor->setTagByCharacterId($bitmap_id, $image->getTag($bitmap_id));

echo $editor->build();

GIF画像を入れ替える

使い方はJPEGとほとんど変わりません。 PNGとの違いはSWFに変換する時にカラーパレットを利用しています

$image = new Media_SWF_Bitmap_GIF('path/to/image.gif');
$image->build();
$editor->setTagByCharacterId($bitmap_id, $image->getTag($bitmap_id));

PNG画像を入れ替える

GIFと違いカラーパレットを使用していません

$image = new Media_SWF_Bitmap_PNG('path/to/image.png');
$image->build();
$editor->setTagByCharacterId($bitmap_id, $image->getTag($bitmap_id));

MovieClipを入れ替える

MC及びその子のMCとShapeを再帰的に入れ替えます。

上記の画像もあらかじめMCに組み込んでおけばよいので最も自由度が高く調整しやすいです

$swf_data  = file_get_contents('path/to/base.swf');
$swf_data1 = file_get_contents('path/to/item_1.swf');

$editor = new Media_SWF_Builder();
$editor->parse($swf_data);
$editor->loadCharacterMap();

$item_editor1 = new Media_SWF_Builder();
$item_editor1->parse($swf_data1);
$item_editor1->loadCharacterMap();

$editor->changeSpriteBySpriteName($item_editor1, '/abatar/b/body'); // 上半身おなか
$editor->changeSpriteBySpriteName($item_editor1, '/abatar/b/left'); // 上半身左手
$editor->changeSpriteBySpriteName($item_editor1, '/abatar/b/right'); // 上半身右手

echo $editor->build();

https://github.com/ken39arg/Media_SWF/blob/master/sample/200.php にMCとPNGを入れ替えるボーリングパラダイスの例を作成しました

MovieClipの持つShapeの塗り色を変更する

最近はMovieClipで統一することが多いので、あまり使っていませんが、気軽にアイテムを増やすには色を変更するだけが一番お手頃です。

$swfmill_editor = new Swfmill('path/to/base.swf'); // Swfmill版でしか実装していません
$swfmill_editor->changeFillColor('avatar/h/skin', '#ff0000'); // 肌の色を赤に

echo $swfmill_editor->getSwfBinary();

モーションを入れ替える

タイムライン上のモーションを入れ替えます。 また、モーション素材の作り方には独自のルールをもうけています。

$swfmill_editor = new Swfmill('path/to/base.swf');
$motion_editor = new Swfmill('path/to/motion.swf');

// モーション同士(ラベルがモーション名)を入れ替える
$swfmill_editor->changeMotion('avatar', 'motion1', 'motion', $motion_editor);

// ラベル名を変更する
$swfmill_editor->changeMotionLabel('avatar', 'motion', 'motion1');

echo $swfmill_editor->getSwfBinary();

https://github.com/ken39arg/swfmill/blob/master/sample/300.php にコンチを例にしたサンプルを上げています

  • Media_SWFシリーズはparse()loadCharacterMap()は負荷が高いので実運用時は、必ず、serialize()したデータをキャッシュしてください。

さて、最初にも書きましたが、もし評判がよければ、次回以降「Flashデベロッパーとサーバーサイドエンジニアとのお約束ごと編」や「マップ生成のFlashLite実装編」「モーション入れ替え解説編」等を書いてみようかと思います。

あ、カヤックではいつでもエンジニアを募集しています!

すぐ近くの警察署の裏に防犯カメラ&屋根付きの私営の駐輪場があるので、自転車通勤でも安心です。