In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: MOUSE_MOVEはどの位の間隔でとれるの?

MOUSE_MOVEの実験
* @author エスケイ
*
* MOUSE_MOVEがいったいどのくらいの間隔でとれるのかの実験。
*
* ■分かったこと
* ・15msか16msくらいでとれることが多い。(約60fps相当)
* ・3回に一階くらい0msでとれてる。どういうことなの?検証方法間違ってる?1ms未満で取得できてるの?
* ・取得頻度は実行FPSにはよらない。
*
* ■疑問
* ・取得頻度はなにで決まってるの?どこかに仕様が書いてある?
* ・0msで取得できるときはなにが起こってるの?
* 
* ==== matacat ============
* 仕様があるのかどうかは調べていませんが、おそらく Flash Player は
* OS から通知されたマウスイベント(をブラウザが仲介したもの)を単に
* 垂れ流しているだけだと思われます(マウスポインタの位置を一定の
* 時間間隔でチェックするのではなく)。
* よって重めの Flash でもサクサク動くような PC なら、より高頻度で
* 受け取れるのではないかと思います。あとは、マウス自体の種類や性能・
* 接続の規格・ドライバの出来によるのではないでしょうか。
* 
* 「 0ms 現象」については、こちらでは確認できませんでした。
* おそらくリスナー関数内の処理が煩雑で、マウスイベントを捌ききれなかった
* からではないでしょうか。
* 
* 1. 一回目の関数呼び出しが完了する前に二、三回目の呼び出しがかかる
* 2. 三回目の呼び出しで "currentTime = new Date().time;" が実行される
* 3. 一回目、 "lastTime = currentTime;" 実行
* 4. 二回目、 "(currentTime-lastTime).toString()" 実行
* 5. "0ms" と表示される
* 
* Flash Player がシングルスレッドでイベント処理をどう表現しているのかを
* 私は全く知りませんが、こう考えれば説明がつきそうです。
Get Adobe Flash player
by matacat 29 Apr 2010

    Talk

    esukei at 06 May 2010 08:22
    0ms問題はやっぱりイベントがさばき切れてないというのが濃厚のようですね… こちらの環境では500samples中、0msが数回から20回程度とれることがありました。 そもそもの頻度はその辺りを勘案しても、環境次第、ということのようですね。 検証ありがとうございました!
    tsu_droid at 08 Jan 2013 16:41
    CS4のPlayer10.0で試したところ、こっちでも経過0msecが出た。 でもそれ以外は大体15か16msecだった。
    Embed
/**
 * Copyright matacat ( http://wonderfl.net/user/matacat )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/phje
 */

// forked from esukei's MOUSE_MOVEはどの位の間隔でとれるの?
/**
 * MOUSE_MOVEの実験
 * @author エスケイ
 *
 * MOUSE_MOVEがいったいどのくらいの間隔でとれるのかの実験。
 *
 * ■分かったこと
 * ・15msか16msくらいでとれることが多い。(約60fps相当)
 * ・3回に一階くらい0msでとれてる。どういうことなの?検証方法間違ってる?1ms未満で取得できてるの?
 * ・取得頻度は実行FPSにはよらない。
 *
 * ■疑問
 * ・取得頻度はなにで決まってるの?どこかに仕様が書いてある?
 * ・0msで取得できるときはなにが起こってるの?
 * 
 * ==== matacat ============
 * 仕様があるのかどうかは調べていませんが、おそらく Flash Player は
 * OS から通知されたマウスイベント(をブラウザが仲介したもの)を単に
 * 垂れ流しているだけだと思われます(マウスポインタの位置を一定の
 * 時間間隔でチェックするのではなく)。
 * よって重めの Flash でもサクサク動くような PC なら、より高頻度で
 * 受け取れるのではないかと思います。あとは、マウス自体の種類や性能・
 * 接続の規格・ドライバの出来によるのではないでしょうか。
 * 
 * 「 0ms 現象」については、こちらでは確認できませんでした。
 * おそらくリスナー関数内の処理が煩雑で、マウスイベントを捌ききれなかった
 * からではないでしょうか。
 * 
 * 1. 一回目の関数呼び出しが完了する前に二、三回目の呼び出しがかかる
 * 2. 三回目の呼び出しで "currentTime = new Date().time;" が実行される
 * 3. 一回目、 "lastTime = currentTime;" 実行
 * 4. 二回目、 "(currentTime-lastTime).toString()" 実行
 * 5. "0ms" と表示される
 * 
 * Flash Player がシングルスレッドでイベント処理をどう表現しているのかを
 * 私は全く知りませんが、こう考えれば説明がつきそうです。
 */
package
{
    import flash.display.Sprite;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.filters.DropShadowFilter;
    import flash.text.TextField;
    import flash.ui.Keyboard;
    import flash.utils.getTimer;
    
    import net.hires.debug.Stats;
    
    [SWF(frameRate = 15, backgroundColor = 0xC0C0C0)]
    
    public class FlashTest extends Sprite
    {
        private const B:Number = 10;
        private const N:String = "\n";
        
        private var textField:TextField;
        private var samples:Vector.<int>;
        private var sampleAmount:int;
        private var moveCount:int;
        
        public function FlashTest()
        {
            Wonderfl.capture_delay(10);
            
            stage.mouseChildren = false;
            
            filters = [new DropShadowFilter(2, 225, 0, 1, 8, 8)];
            
            textField            = stage.addChild(new TextField()) as TextField;
            textField.background = true;
            textField.alpha      = 0.75;
            textField.autoSize   = "left";
            textField.x          = B;
            textField.y          = B;
            
            samples      = new Vector.<int>();
            sampleAmount = 500;
            moveCount    = 0;
            
            //FPS変化チェック用
            stage.addChild(new Stats()).x = stage.stageWidth - 70;
            
            init(null);
        }
        
        private function init(e:KeyboardEvent):void
        {
            stage.removeEventListener(KeyboardEvent.KEY_DOWN, init);
            
            graphics.clear();
            graphics.lineStyle(B, 0xFF4040);
            graphics.drawRect(B * 0.5, B * 0.5, stage.stageWidth - B, stage.stageHeight - B);
            
            describe();
            
            stage.addEventListener(KeyboardEvent.KEY_DOWN, config);
        }
        
        private function describe():void
        {
            textField.text
            = "RESOLUTION TEST of MouseEvent.MOUSE_MOVE" + N
            + N
            + "Adjust total amount of samples will be sampled in this test" + N
            + "and frame rate with arrow keys." + N
            + "When you're ready to start, hit space key." + N
            + N
            + "Sample Amount: " + sampleAmount + N
            + "Frame Rate: " + stage.frameRate;
        }
        
        private function config(e:KeyboardEvent):void
        {
            if (e.keyCode == Keyboard.SPACE) {
                stage.removeEventListener(KeyboardEvent.KEY_DOWN, config);
                
                samples.fixed  = false;
                samples.length = sampleAmount + 1;
                samples.fixed  = true;
                for (var i:int = 0; i < sampleAmount + 1; i++) samples[i] = 0;
                moveCount = 0;
                
                textField.text = "Keep your mouse moving continuously and smoothly.";
                
                stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
            } else {
                switch (e.keyCode) {
                    case Keyboard.UP:
                        if (sampleAmount < 10000) sampleAmount += 10;
                    break;
                    
                    case Keyboard.DOWN:
                        if (sampleAmount > 10) sampleAmount -= 10;
                    break;
                    
                    case Keyboard.RIGHT:
                        if (stage.frameRate < 120) stage.frameRate++;
                    break;
                    
                    case Keyboard.LEFT:
                        if (stage.frameRate > 1) stage.frameRate--;
                    break;
                }
                
                describe();
            }
        }
        
        private function mouseMove(e:MouseEvent):void
        {
            if (moveCount < sampleAmount + 1) {
                samples[moveCount] = getTimer();
                moveCount++;
            } else {
                stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
                finish();
            }
        }
        
        private function finish():void
        {
            var histogram:Array = [];
            var sum:int         = 0;
            var longest:int     = -1;
            var shortest:int    = 0x7FFFFFFF;
            var maxTimes:int    = -1;
            var mostAppear:int  = -1;
            var zero:int        = 0;
            
            for (var i:int = 0; i < sampleAmount; i++) {
                var interval:int = samples[i + 1] - samples[i];
                if (interval <= 0) {
                    interval = 0;
                    zero++;
                } else {
                    if (interval > longest)  longest  = interval;
                    if (interval < shortest) shortest = interval;
                }
                if (!histogram[interval]) histogram[interval] = 0;
                histogram[interval]++;
                sum += interval;
                if (histogram[interval] >  maxTimes) {
                    maxTimes   = histogram[interval];
                    mostAppear = interval;
                }
            }
            
            var thickness:Number = (stage.stageWidth - B * 2) / (longest - shortest + 1);
            var offset:Number    = B + thickness * 0.5;
            var bottom:Number    = stage.stageHeight - B;
            var unit:Number      = (stage.stageHeight - B * 2) / maxTimes;
            
            graphics.lineStyle(thickness, 0x40FFFF, 1, false, "normal", "none");
            histogram.forEach(function(times:*, itv:int, a:Array):void
            {
                if (!times) return;
                
                var xx:Number = (itv - shortest) * thickness + offset;
                graphics.moveTo(xx, bottom);
                graphics.lineTo(xx, bottom - unit * times);
            }, this);
            
            textField.text
            = "==RESULT==" + N
            + "Total Sample: "             + sampleAmount                    + "samples" + N
            + "Shortest interval: "        + shortest                        + "ms" + N
            + "Longest interval: "         + longest                         + "ms" + N
            + "Appeared most frequently: " + mostAppear                      + "ms" + N
            + "Average interval: "         + (sum / sampleAmount).toFixed(3) + "ms" + N
            + 'Total "0ms": '              + zero                            + "times" + N
            + N
            + "Hit any key to retry...";
            
            stage.addEventListener(KeyboardEvent.KEY_DOWN, init);
        }
    }
}