2007年7月15日日曜日

マウスの方向転換を検知する(失敗作)

マウスジェスチャーを実装する第一歩として、マウスの方向転換を検知するスクリプトを試作。残念ながら正確な検知まで到達できませんでしたが、話のタネに晒しておきます。
基本的な流れは

  1. マウスの位置を配列に記録しておく(古いものは削除される)
  2. マウスの進行方向も算出して配列に記録
  3. 過去数フレームと進行方向を比較し、その差が一定の範囲内に収まっていれば方向を転換したとみなす
わざわざ配列を利用したのはある程度ゆっくりでも判定できるようにとの配慮だったのですが、バグの温床ともなってしまったようです。機会があればまた挑戦してみます。#const HISTORY_MAX 3
#const PI          3.1415
#module
#defcfunc dist2d int a, int b
    return sqrt(a * a + b * b)
#global

*init
    dim  historyX, HISTORY_MAX  // X座標の履歴
    dim  historyY, HISTORY_MAX  // Y座標の履歴
    ddim historyA, HISTORY_MAX  // 進行方向の履歴
    gosub *resetCounter

*main
    gosub *calc
    wait 2
    goto *main

*resetCounter
    counter = HISTORY_MAX       // 配列変数history~が一新されるまで判定しない
    return

*calc
    // クリックでデバッグウィンドウ表示
    getkey leftClick, 1 : assert (leftClick == 0)

    // 方向転換後ある程度時間が経っており、マウスが動いているときに限り判定
    if (counter == 0) {
        title ""
        if (0.0 < dist2d(mouseY - historyY(0), mouseX - historyX(0))) {
            ang = atan(mouseY - historyY(0), mouseX - historyX(0))
            repeat HISTORY_MAX
                if (dist2d(mouseY - historyY(cnt), mouseX - historyX(cnt)) < 5.0) {
                    // 距離が短い場合、判定しない
                    continue
                }
                // 角度変化をtに代入
                t = ang - historyA(cnt)
                while (t < -PI) : t += PI * 2 : wend
                while (PI < t)  : t -= PI * 2 : wend

                // 一定の角度内に収まっていれば、方向転換したとみなす
                if ((0.5 < absf(t)) & (absf(t) < 2.5)) {
                    pset mousexmousey
                    if (t < 0.0) : title "turn left"
                    if (0.0 < t) : title "turn right"
                    gosub *resetCounter
                    break
                }
            loop
        }
    }
    if (counter > 0) {
            ang = historyA(0)
            counter--
    }

    // 配列変数history~を1ずつシフトさせる
    repeat HISTORY_MAX - 11
        historyX(HISTORY_MAX - cnt) = historyX(HISTORY_MAX - cnt - 1)
        historyY(HISTORY_MAX - cnt) = historyY(HISTORY_MAX - cnt - 1)
        historyA(HISTORY_MAX - cnt) = historyA(HISTORY_MAX - cnt - 1)
    loop
    historyX(0) = mouseX
    historyY(0) = mouseY
    historyA(0) = ang
    return

0 件のコメント: