Tag/Thread

Theme-2やったよ!感想とか

Entacl Develop的な

Theme-2 が完成したよ! 今回はかなり気合い入ってる。と思ってる :-D 若干内容がカブってるけど、ちょっと説明とかをつらつらと。

成果物はコチラソースはコチラ に転がっております。 初めて使ったライブラリがほとんどだったので、 ソースはぐじゃぐじゃになっちゃいました。

今回使用したLibrary群

ThreadPapervision3D は初めて使ってみたよ。 tweener は少し前からお世話になっております。

Thread

慣れるまでは少しクセがあるものの、 まだコーディングスタイルが決ってない自分にとって、 ロジックとプレゼンテーションの分離を考える良い機会とヒントをくれた。 現状スレッドの中でしかスレッドを立ち上げれないって制限はあるけど、 がっちりハマれば素晴らしい威力を見せてくれる。 同じように定期的にトリガーする事で駆動する部分では、 Papervision3D とはかなり相性が良い気がしたよ。 cacheError の差し込み方が、まだイマイチ理解出来てないので、 そこらへんをもうちょっと調べてみる必要がある。

まだ色々変更がかかる予定とかもあるみたいなので、 そこらへんにも期待大 :-)

Papervision3D

憧れの 3次元レンダリング を行ってくれる!! 適応範囲がものっすごい広いため、まだ殆ど理解出来てない。 materialsobjects なパッケージは、 基本的な部分はある程度把握出来たけど、 scenecamera はどれをどのタイミングで使えば良いのか、 未だに全く理解出来てない。 たぶんココらへんを理解出来てくると、 カッコいい3次元アニメーションとかも作れるようになると信じてる。

tweener

普段出くわすアニメーションなら、 コレ使えば簡単に実装出来ちゃうよ。 常時動き続けるアニメーションや、 駆動中にカットインしてくるイベントを反映させるのは少し苦手なイメージがあるんだけども、 そこらへんを上手く処理する方法ってあるのかな? 今回 Papervision3D と一緒に使ってみたら、 少し相性は悪い氣がした。 Papervision3D のレンダリングのタイミングと、 tweener の処理のタイミングが上手い事合わないからかな?って勝手に憶測。

たぶん、コレからもお世話になる事は間違いないモノのひとつ。

Theme-2のまとめとか

結果的にソースは全然イケてないけども、 考え方や捉え方をかなり学べたので、 強引にでも試してみて良かったと思う。 派手ってだけで Papervision3D を使った部分が大きいので、 これからはもっと使いどころを考えていけたら良いっすね :-)

それとタイムラインの使い方も、もう少しちゃんと覚えないとなぁ。 じゃないと、どうしてもスクリプトな方向によってしまって、 デザイナーさんと一緒に作業する時とかに固まってしまいそう。

まだまだ若輩者ですが、 かなり良い感じの刺激とプレッシャーをもらった課題でした :-D

Posted at: 
2008/03/01 04:12:42
3 Comments
0 TrackBacks
Tags: 
ActionScript
Flash
memo
Papervision3D
Thread
Tweener
Trackback: 
http://humming.via-kitchen.com/2008/03/01/impression-of-entacldevelop-theme2/trackback/

AS3Threadを試してみたよ。

AS3でのコーディングスタイルが全然定まらないで、 かなりヤキモキしている訳なのですが、 BeInteractive! さんの スレッドによる非同期処理はこんな感じ にインスパイアされて 早速 AS3Thread を試してみたよ!

使い方は至って簡単。 Snippets - Spark projectサンプル を見れば分かると思うのですが、 Thread なクラスを継承して、 以下のメソッドを必要に応じてオーバーライドしていく。

  • initialize ... 初期化時に一度だけ呼ばれる。
  • execute ... ロジックを実行する。
  • catchError ... エラーがあった場合に呼ばれる。
  • finalize ... 後片付け。terminateした後に一度だけ呼ばれる。
  • toString ... 誰か分かるように。オーバーライドしないと親の名前になる。

なので、基本形はこんな感じになる。

package
{
    import org.libspark.thread.Thread;

    public class ExampleThread extends Thread
    {
        protected override function initialize():void
        {
            //  初期化コードを書く。
        }

        protected override function execute():void
        {
            //  実際のロジックを書く。
        }

        protected override function finalize():void
        {
            //  後片付けコードを書く。
        }

        public override function toString():void
        {
            //  スレッドの名前を返す。
            return '[ExampleThread]';
        }
    }
}

で、実際にガリガリ書いてみたのですが、 かなり非同期部分を隠蔽出来るよ! デフォルトで LoaderThread なクラスや URLLoaderThread なクラスが用意されてるので、 すぐに試して感動出来たりします! こういうの、ホントにありがたい。

で、何も気にせずコードを書いていたんですが、 ちょっとしたところで壁にブチ当たった。

最初の一連の作業が終わった後、 クリックでSpriteを消してやろうと思って、 それをスレッドにして作ってたんですが、 イベントを受け取ったタイミングで begin しても動かない。 ってか、エラー吐いちゃうよ?なハプニングに遭遇。

一人コードリーディング祭りの結果、 スレッドの処理内じゃないと begin 出来ないっぽい。 begin の中身を見てみるとこうなってて、

//  Thread.as@98行目あたり
public function begin():void
{
    if (isRunning) {
        return;
    }
    //  ココでエラー吐く。
    (_parent = _currentThread).addChild(this);

    _runHandler = execute;
    _executeHandler = beginHandler;
}

null的なやつがどうの。ってエラー吐く。 この _currentThread ってプロパティがnull以外の時しか begin 出来ない事になる訳ですが、 そうなるタイミングってのが、探した限りだと internalExecute の中の処理が走る時だけ。

//  Thread.as@208行目あたり
internal function internalExecute():void
{
    //  ちょっと省略
    try {
        _currentThread = this;  //  ココで自分を入れる。
        _executeHandler.apply(this);
    }
    catch (e2:Error) {
        handleError(e2);
    }
    finally {
        _currentThread = null;  //  処理が終わればnullになる。
    }
}

疑似スレッドがゆえに、「スレッドの外」が存在してるのかぁ。 とか、勝手に理解(合ってるかは不明)。 yossy さんとかはどうやって実装してるんだろ? ものっすごい気になる。 強引にでもスレッドの中に処理を持って行くのかな? うーん、それって果たしてどうなんだろう。

でも、ここで終わらないのが スルー力 の無さ! 「スレッドの外」って事は、「メインスレッド上の出来事である。」として、ソースを書き換えてみる。 メインスレッドのインスタンスは MasterThread なクラスが保持しているので、 まずはそれを Thread から参照出来るようにする。

Index: MasterThread.as
===================================================================
--- MasterThread.as     (revision 259)
+++ MasterThread.as     (working copy)
@@ -11,9 +11,14 @@
                        _debugView = debugView;
                }

-               private var _main:Thread;
+               private static var _main:Thread;
                private var _debugView:Sprite;

+               internal static function get main():Thread
+               {
+                   return _main;
+               }
+
                public function executeActiveThreads():void
                {
                        internalExecute();

これで同一パッケージ内からメインスレッドのインスタンスが参照出来るようになった。

次に、エラー吐いてたところで、 _currentThread がnullだった場合、 メインスレッドを渡してやるようにする。

Index: Thread.as
===================================================================
--- Thread.as   (revision 259)
+++ Thread.as   (working copy)
@@ -101,7 +101,7 @@
                                return;
                        }

-                       (_parent = _currentThread).addChild(this);
+                       (_parent = (_currentThread||MasterThread.main)).addChild(this);

                        _runHandler = execute;
                        _executeHandler = beginHandler;

これで _currentThread がnullの場合はメインスレッドを使ってスレッドが起動される。

こうする事で、スレッドの処理の外で begin された場合はメインスレッドにぶら下がる形で実行されるよ。 って言っても、実はこれも完璧ではなくて、リスクもちゃんと認識しております。 ちょうど良いタイミングで begin しちゃって、 _currentThread がnullじゃなかったら、問答無用で全然関係ないスレッドにぶら下がります。 が、それを認識した上で、それでもこうあるべきじゃ?って思ってます(実装ではなく挙動として)。 実装はコミッターの方々が、もっと洗練された形でやってのけてくれる事に期待大!

この話題、どこかで yossy さんにあったら是非とも聞いてみたい!

ps. もうちょっと詳しい使い方はリクエストがあれば書いたり書かなかったり。

Posted at: 
2008/02/27 03:13:57
0 Comments
0 TrackBacks
Tags: 
ActionScript
Flash
Thread
Trackback: 
http://humming.via-kitchen.com/2008/02/27/tried-using-thread-on-as3/trackback/

threadの動作の違うよ。

Python でスレッドまわりを勉強してて、未解決メモ。

3つのスレッドが、それぞれ0から9まで数え上げるって言う、 簡単なものなのですが、 こんな感じで実装すると、 シェルから叩いた時には全部数え上げる前に終了してしまう。

#!/usr/bin/env python2.5
# vim: encoding=utf-8 :

import time
import thread

def run():
    for i in range(10):
        print i
        time.sleep(1)

def main():
    for i in range(3):
        thread.start_new_thread(run, ())
        time.sleep(1)

if __name__ == '__main__':
    main()

でも、この実装だとちゃんと数え上げられた数字が全て表示される。

#!/usr/bin/env python2.5
# vim: encoding=utf-8 :

import time
from threading import Thread

class CountThread(Thread):
    def run(self):
        for i in range(10):
            print i
            time.sleep(1)

def main():
    for i in range(3):
        CountThread().start()
        time.sleep(1)

if __name__ == '__main__':
    main()

この挙動の違いはどうなってるんだろう?

本当に途中で終わっているのかテストしてみようと、 数え上げている数字をファイルに書き出してみると、 上の方だと、 Bus error とかエラー吐いて終了する。 どうやら、ホントに途中で終わってるっぽい。

threading.Thread の方が高水準なインターフェイスらしいので、 何か知らない処理が挟まっているんだろうと推測。 まだまだ勉強が必要ですな。

ちなみに、 threading.Thread のコンストラクタに target を渡すやり方で起動しても、 run をオーバライドした時と同じ動作をしてくれた。 ので、今のところは後者を使っていきたいと思います。

Posted at: 
2008/01/06 23:00:56
0 Comments
1 TrackBack
Tags: 
Python
Thread
Trackback: 
http://humming.via-kitchen.com/2008/01/06/2-threads-have-different-motion/trackback/

Categories

Archives