LoginSignup
7
6

More than 5 years have passed since last update.

[追記]swf2jsでActionScriptをJavaScriptに置き換える。

Last updated at Posted at 2015-08-10

まずはActionScriptの実行順番を把握する。

ActionScriptは深度の上から順番に実行される。
MovieClipのアクションは表示される深度の下から実行される。

下記のようなタイムラインの場合

|深度|フレーム|名前|
| 7 | a | [as1] |
| 6 | ● | [MC1] |
| 5 | a | [as2] |
| 4 | a | [as3] |
| 3 | ● | [MC3] |
| 2 | ● | [MC2] |
| 1 | a | [as4] |

次のように実行される

as1
as2
as3
as4
MC2のアクション
 => MC2内のMovieClipのアクション
MC3のアクション
 => MC3内のMovieClipのアクション
MC1のアクション
 => MC1内のMovieClipのアクション

MovieClipの中のアクションも同じように実行されていく。

はまったところ

MC2でMC1のフレームを移動してもMC1の移動する前のアクションは実行される。

MC2のアクション

trace("mc2");
MC1.gotoAndPlay(2);

MC1のフレームとアクション

フレーム1のアクション
stop();
trace("frame1");

フレーム2のアクション
trace("frame2");

とした場合

mc2;
frame1;
frame2;
frame1;

と出力される。

JavaScriptだと
まずはフレームのアクションを実行して
深度の低いMovieClipのアクションを実行。

この際にフレーム移動先でアクションがある場合は
その度に別の配列に格納しておいて最初のアクションの実行が完了したら
次は配列に格納されたアクションを実行する
これを繰り返す事で動いた。


    MovieClip.prototype.addActions = function()
    {
        var _this = this;

        // メインのアクション
        if (_this.isAction) {
            var frame = _this.getFrame();
            var as = _this.getActions(frame);
            if (as != undefined) {
                var player = _this.player;
                var actions = player.actions;
                var queue = player.queue;
                var obj = { as: as, mc: _this };
                if (queue == null) {
                    actions[actions.length] = obj;
                } else {
                    queue[queue.length] = obj;
                }
            }
            _this.isAction = false;
        }

        // 深度の若い順番にアクションを実行
        var tags = _this.getTags();
        var _addActions = _this.addActions;
        var _btnCallback = _this.btnCallback;
        var length = tags.length;
        for (var depth = 1; depth < length; depth++) {
            if (!(depth in tags)) {
                continue;
            }

            var tag = tags[depth];
            // loadMovieでよばれた別swfは形式を合わせる
            if (tag instanceof Player)
                tag = tag.getParent();

            if (tag instanceof MovieClip) {
                _addActions.call(tag);
            } else if (tag.characters instanceof Array) {
                // ボタンの状態でアクションを実行
                _btnCallback.call(_this, tag, _addActions);
            }
        }
    };

後は、queueにデータがあればひたすら実行


while(actions.length) {
    queue = [];

    // アクションを実行
    for (var i = 0; i < actions.length; i++) {
        action[i].execute();
    }

    actions = queue;
}

よしよし。
これで問題ないはず。

と思ったが、フレーム移動があった場合のアクションの順番は
このルールに当てはまらないorz

フレーム移動の際のアクションの順番

レンダリング後、フレーム移動して移動先にアクションがある場合
(新規のMovieClipやフレーム終了したMovieClipは先の条件で呼ばれる)
最後にレンダリングされたMovieClipのアクションから実行される。

root
|a|a|
|●|●|MC2
|●|●|MC1

MC1
|a|a|

MC2
|a|a|

とした場合


1フレーム
root_frame1
mc1_frame_1
mc2_frame_1
ここは最初のルールが適用

2フレーム
mc2_frame_2
mc1_frame_2
root_frame2

2回目の1フレーム
mc2_frame_1
mc1_frame_1
root_frame1

2回目の2フレーム
mc2_frame_2
mc1_frame_2
root_frame2

ルールは二つ

  • 初回アクション実行時とアクションでフレーム移動があった場合
  • レンダリング後、フレーム移動した場合

こんどこそできたorz

完成品

ienaga/swf2js

ベースはこれでできたので、次はSWF5,SWF6で使う
onClipEventを調べてみよう。

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6