2008年10月アーカイブ

小さいと分かり難いんですが、赤線が curveTo で引いた線。青線が lineTo で20分割して描いてる線。
curveTo の分割数は曲線の形によって変化しています。
少ないときで 1 本。多くて 8 本くらいです。


なんだか、やたら長くなってしまった。
最初は曲線の角度から分割しようと思ってたけど、どうやって割り出せばいいかよくわからず、結局こんなことになってしまった。
一応これだと、どんだけひねっても、ほとんどずれないです。

それにしても、もうちょっとやりようはありそうなもんだけども。
とりあえず僕の低い学力では、今はここまで。

function bezierCurve(
        ax:Number, ay:Number, 
        bx:Number, by:Number, 
        cx:Number, cy:Number, 
        dx:Number, dy:Number, n:Number, t:Number):void
{
    var t1:Number = n + (t - n) * 0.5;
    var t2:Number = n + (t - n) * 0.25;
    var ax2:Number = cubicBezier(ax, bx, cx, dx, n);
    var ay2:Number = cubicBezier(ay, by, cy, dy, n);
    var dx2:Number = cubicBezier(ax, bx, cx, dx, t);
    var dy2:Number = cubicBezier(ay, by, cy, dy, t);
    
    var px:Number = cubicBezier(ax, bx, cx, dx, t1);
    var py:Number = cubicBezier(ay, by, cy, dy, t1);
    var rx:Number = getControl(ax2, px, dx2);
    var ry:Number = getControl(ay2, py, dy2);
    var qx:Number = quadraticBezier(ax2, rx, dx2, 0.25);
    var qy:Number = quadraticBezier(ay2, ry, dy2, 0.25);
    var px2:Number = cubicBezier(ax, bx, cx, dx, t2);
    var py2:Number = cubicBezier(ay, by, cy, dy, t2);
    
    if (checkPosition(qx-px2, qy-py2, 0.5))
    {
        curveTo(rx, ry, dx2, dy2);
    }
    else
    {
        bezierCurve(ax, ay, bx, by, cx, cy, dx, dy, n, t1);
        bezierCurve(ax, ay, bx, by, cx, cy, dx, dy, t1, t);
    }
}

ベジェ曲線のそれぞれの計算は以下。

//曲線が許容範囲内に収まってるかチェック
function checkPosition(x:Number, y:Number, d:Number):Boolean
{
    return (Math.abs(x) < d && Math.abs(y) < d);
}

//2次ベジェ曲線の通過点からコントロールポイントを得る
function getControl(
        a:Number, b:Number, c:Number):Number
{
    return (b * 4 - a - c) * 0.5;
}

//2次ベジェ曲線の任意の点を取得
function quadraticBezier(
        a:Number, b:Number, c:Number, t:Number):Number
{
    var s:Number = 1 - t;
    return s * s * a + 2 * s * t * b + t * t * c;
}

//3次ベジェ曲線の任意の点を取得
function cubicBezier(
        a:Number, b:Number, c:Number, d:Number, t:Number):Number
{
    var s:Number = 1 - t;
    return s * s * s * a 
        + 3 * s * s * t * b 
        + 3 * s * t * t * c 
        + t * t * t * d;
}


やっぱりソースが長い。
無駄に計算してる感が否めないので、
せめてこの半分くらいにはしたい。

FlashPlayer の 10 が正式リリースされたけども
今のところ、一番厄介なのは、おそらく Vector クラスの使用じゃないかと思うわけです。

バージョン 9 でも AS3 は使っているわけですが、9 には Vector クラスは対応していないので、 10 対応で作成したクラスを 9 でも使用したくなったときに、Vector クラスはかなりネックになってしまうんじゃないかと思うわけです。

クライアントから古いバージョンを指定されることはよくあることだと思います。

で、こんな風にすると、一応 Vector と Array をプレイヤーの状況によって使い分けれるんじゃないかなあ と、思ってみたわけです。

function getArrayOrVector(T:Class):Class
{
    var theClass:Class;
    try 
    {
        var classPath:String = getQualifiedClassName(T);
        classPath = classPath.replace("::", ".");
        theClass = getDefinitionByName
            ("Vector.<" + classPath + ">") as Class;
    }
    catch (error:Error)
    {
        theClass = Array;
    }
    
    return theClass;
}

var theClass:Class = getArrayOrVector(int);
var a:Object = new theClass();
trace(getQualifiedClassName(a));

これだと、FlashPlayer のバージョンが 9 の場合は
Array
と出力され、バージョンが 10 だと
__AS3__.vec::Vector.<int>
と出力されます。

ただ、これだと変数の型指定は Object になっちゃうので、
実際どれほどの効果があるのかは謎です。
誰か検証してくれないかなあ。

追記 ----
この記事の内容より有効な方法がタロタローグ ブログさんで掲載されています。
FlashDevelopでFlash Player 10用のswfファイルを作成する方法(最短2秒)
<補足>
playerglobal.swc ファイルは FlexSDK だと
flex_sdk_3/frameworks/libs/player/10
に入ってます。
---- 追記(ここまで)


たぶんだけど現状では Vector クラスのコードヒントは使えるけど、その他のFP10で実装されたクラスやメソッドが使えない。

FlashDevelop は Library ディレクトリ内にクラス定義がされてるんだけども
ここに新しいクラス群が追加されていないためだと思う。

なので、Shader クラスや Graphics.beginShaderFill() メソッドでもコードヒントが出るように、定義ファイルを作ってみました。

もしかしたら、すでに誰か作ってるかもしれませんがアップしときます。
AS3_for_FlashDevelop.zip

ダウンロードして解凍すると、中に"intrinsic"というディレクトリが入っているので、それを
FlashDevelop のインストールされているディレクトリ、
Program Files\FlashDevelop\Library\AS3\
の中の同名のディレクトリに上書きするとコードヒントが使えるようになります。
import とかも補完されます。


内容
display
  • ColorCorrection
  • ColorCorrectionSupport
  • Graphics
  • GraphicsBitmapFill
  • GraphicsEndFill
  • GraphicsGradientFill
  • GraphicsPath
  • GraphicsPathCommand
  • GraphicsPathWinding
  • GraphicsShaderFill
  • GraphicsSolidFill
  • GraphicsStroke
  • GraphicsTrianglePath
  • IGraphicsData
  • IGraphicsFill
  • IGraphicsPath
  • IGraphicsStroke
  • Shader
  • ShaderData
  • ShaderInput
  • ShaderJob
  • ShaderParameter
  • ShaderParameterType
  • ShaderPrecision
  • TriangleCulling

events
  • ShaderEvent

filters
  • ShaderFilter

---追記(2008.10.17)---
desktop
  • Clipboard
  • ClipboardFormats
  • ClipboardTransferMode

net
  • FileReference


ASDoc を参考に、おもいっきり手作業で作ってますので、なんか間違ってるとことかあったらすいません。
ご利用はあくまで自己責任でお願いします。

きっと、近いうちにFlashDevelop 自体、アップデートされるでしょうから
それまでの気休めぐらいに使っていただければと思います。


エラーの意味が分からず四苦八苦してしまったのでメモ。

FlashDevelop + FlexSDK で AIR を作成する際、
error while loading initial content

というエラーが出たときは、 application.xml 内の以下を確認する。(デフォルトでは2行目)

<application xmlns="http://ns.adobe.com/air/application/1.0">

ここで指定する URL は AIR(adl.exe)のバージョンによって異なる。
adl.exe のバージョンは Windows XP だと adl.exe を右クリックして
「プロパティ」→「バージョン情報」
で確認できる。



今回の場合は 1.5 が入っていたので
<application xmlns="http://ns.adobe.com/air/application/1.5">
にすることで正常に書き出された。

ちなみに、この XML ファイルのテンプレートは (FlexSDK)/templates/air に入ってる。

まずはデモから。

デモ

Progression ではURLを指定してシーンを変更できるので、 Flash はビデオプレイヤーのみを実装しておいて、 あとは URL でビデオの再生位置や flv のパスを指定してやる。 ってこともありだと思った。

デモの FLV はキューポイントを3箇所設定している。 で、onCuePoint のイベントを受け取ってシーンを変更すれば ブラウザの「戻る」「進む」で再生位置を変更するとかもできる。
何気にタイトルも変えてみたり。

デモでは一応Flash内にボタンを設置しているけど、 これも場合によってはなくてもいい。

今回はキューポイントの指定だけども、URLで 直接時間指定することもできる。

要は SceneObject で URL の変化が受け取れるわけだから
これにあわせていろんなことができますね。って話。


--- 追記
直接 #page3 とかに飛ぶとビデオが読み込めてなくて、
最初から再生になってますが、デモだから。という言い訳。