連載
» 2012年12月06日 15時25分 公開

FlashPlayerを自作するSWF研究会UXClip(11)(2/3 ページ)

[岡本紳吾,hatte.Inc]

Shapeの基礎

 さて、構造が分かったところで、次はどうやって画面に展開していくかという話になる。ここでは、カヤックの荒賀謙作氏が1フレームのSWFをベクターデータとして再現するデモを行った。

カヤック荒賀氏。後ろに写っているのはご存じ、コンチだ

 SWFでベクターを描画するアクションは3つ存在する。

  • moveTo():ポイントの移動
  • lineTo():直線を引く
  • curveTo():2次ベジェ曲線

 例えば、AS3で四角形を書く場合は以下のようなスクリプトになる。

public function drawSquare(): Shape
{
    var shape: Shape = new Shape();
 
    shape.graphics.lineStyle(4, 0x0000ff);
    shape.graphics.beginFill(0xff0000, 1.0);
 
    shape.graphics.moveTo(50, 70);
    shape.graphics.lineTo(50, 210);
    shape.graphics.lineTo(190, 210);
    shape.graphics.lineTo(190, 70);
    shape.graphics.lineTo(50, 70);
 
    addChild(shape); 
}

 本来であればdrawRect()を使用して簡単に記述できるのだが、SWFで使えるアクションのみで定義すると上記のようになる。

 では円形はどうか

public function drawMaru(): void
{
    var shape: Shape = new Shape();
 
    shape.graphics.lineStyle(4, 0x0000ff);
    shape.graphics.beginFill(0xff0000, 1.0);
 
    shape.graphics.moveTo(163.60, 163.60);
    shape.graphics.curveTo(137.30, 190.00, 100.00, 190.00);
    shape.graphics.curveTo(62.65, 190.00, 36.30, 163.60);
    shape.graphics.curveTo(10.00, 137.30, 10.00, 100.00);
    shape.graphics.curveTo(10.00, 62.65, 36.30, 36.30);
    shape.graphics.curveTo(62.65, 10.00, 100.00, 10.00);
    shape.graphics.curveTo(137.30, 10.00, 163.60, 36.30);
    shape.graphics.curveTo(190.00, 62.65, 190.00, 100.00);
    shape.graphics.curveTo(190.00, 137.30, 163.60, 163.60);
 
    addChild(shape);
}

 非常に回りくどいことをしているが、本来はこれもまたdrawCircle()で置き換えられる部分だ。円や楕円はベジェ曲線を利用して分解して表現できる。

 荒賀氏によれば、swfdumpを使用するとこれら分解されたシェイプを得ることができるので、そこから別の形へコンバートしていけるという。

 では自分でバイナリを解析してコンバートする場合は、どのようにアプローチするのだろうか?

 答えはShapeタグを読んでいくところにある。Shapeタグは、

  • DefineShape
  • DefineShape2
  • DefineShape3
  • DefineShape4

 の4種類があり、数字が大きくなるにつれてSWFのバージョンが上がる。そしてその中は、

  • Header
  • ShapeId
  • ShapeBounds
  • Shapes

 が格納されている。HeaderにはTag typeが格納されており、基本的な位置情報はShapeBoundsに格納されている。描画情報がShapeに格納されているのだが、それがさらに以下のように分かれている。

  • FillStyles
  • LineStyles
  • NumFillBits
  • NumLineBits
  • ShapeRecords

 Flashを触ったことがある人なら分かるが、Flashは塗りと線に分かれていて、それぞれで色を設定することができる。また、線は線種をいくつか設定することができるようになっている。

 また、塗りに関してはグラデーション(線形、円形)のほか、ビットマップをタイリングすることもできる。これらを解析し、別のプログラムの描画方法へ置き換えていくのだ。デモではJavaScriptへの置き換えなどが行われていた。

 この日使用されたスライド

アクションスクリプト実行処理系

 そして最後にアクションの処理だ。

 例えばフレームアクションを設定した場合、これはどのタイミングで実行されるべきなのだろうか? サイバーエージェントの森野氏による解説が行われた。

ActionScriptについて解説するサイバーエージェント森野氏

 Flash Liteでアクションを設定する場所は、フレームとボタンの2つがある。フレームアクションはShowFrame時に実行する。アクション自体はDoActionに格納されている。

 ボタンアクションはDefineButton内に格納されている。キーボードイベントなどはDefineButton2に格納されている。これらの詳細はAdobeの公式ドキュメントにも記されているので、詳しくはここを参照してみるといいだろう。

 しかし、公式ドキュメントでも完全とはいえず、実装時にハマるポイントがいくつか存在する。例えば複数のアクションが設定されていたとき、実行順序はどうなるのか、またそのタイミングはどうなるのだろうか?

 直接座標をコントロールされたとき、レンダリングはどのように処理していけばいいのだろうか? このあたりの仕様ははっきりとしておらず、地道に観察していくしかない。

 まずはAdobeのPlayerで再生してみて、その挙動をよく観察すること。場合によっては「このアクションを実行するだけ」などというテスト用SWFを再生してみるのもいいだろう。そして、フレームレートを下げるのも手だ。その結果仮説を立てて実装。これを検証するというステップを繰り返す。

 普段何げなく書いている簡単なアクションでも、展開時はこれほどまでに苦労するのだなと実感したプレゼンだった。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。