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 がシングルスレッドでイベント処理をどう表現しているのかを
* 私は全く知りませんが、こう考えれば説明がつきそうです。
/**
* 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);
}
}
}