6

私はゲームで作業しており、コントローラーを作成しようとしていますが、それほど複雑ではありません。これを行うには、2 つの入力 (指) を追跡する必要があります。右)

これが問題です: 指 1 が下にあり、指 2 が下にあり、指 1 が 2 だと思って上がり、次に指 2 が 1 だと思って上がります。

D/Controlls(18849): Action Down 1
D/Controlls(18849): Coordinates 267.7908 415.24274
D/Controlls(18849): Action Pointer Down 2
D/Controlls(18849): Coordinates 281.11423 417.23993
D/Controlls(18849): Action Pointer UP 1
D/Controlls(18849): Coordinates 272.7869 419.23718
D/Controlls(18849): Action UP 2
D/Controlls(18849): Coordinates 1148.103 439.20947

これは、2 つの入力を処理する OnTouchEvent のコードです。

@Override
public boolean onTouchEvent(MotionEvent event) {
    int index = event.getActionIndex();
    int pointerId = event.getPointerId(index);
    int action = event.getActionMasked();

    int oldX, oldY;

    switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
        {
            hero.moveControlls((int)event.getX(), (int)event.getY());
            Log.d("Controlls", "Action Down "+ pointerId);
            Log.d("Controlls", "Coordinates "+ event.getX() + " "+ event.getY());
            break;
        }

        case MotionEvent.ACTION_UP:
        {
            hero.setScreenTouching(false);
            Log.d("Controlls", "Action UP "+ pointerId);
            Log.d("Controlls", "Coordinates "+ event.getX() + " "+ event.getY());
            break;
        }

        case MotionEvent.ACTION_POINTER_DOWN:
        {
            Log.d("Controlls", "Action Pointer Down "+ pointerId);
            Log.d("Controlls", "Coordinates "+ event.getX() + " "+ event.getY());                   
            break;
        }

        case MotionEvent.ACTION_POINTER_UP:
        {
            Log.d("Controlls", "Action Pointer UP "+ pointerId);
            Log.d("Controlls", "Coordinates "+ event.getX() + " "+  event.getY());
            break;
        }
    }
    return true;
}

今、例を調べましたが、理解できませんでした。API で MotionEvent を調べたところ、使用方法がわからない $ACTION_POINTER_INDEX_SHIFT$ を使用するように指示されています。これを行う方法について何か助けはありますか?

4

3 に答える 3

13

ACTION_POINTER_DOWN と ACTION_POINTER_UP は、セカンダリ ポインターがダウンまたはアップするたびに発生します。画面上に既にポインターがあり、新しいポインターがダウンした場合、ACTION_DOWN の代わりに ACTION_POINTER_DOWN を受け取ります。ポインタが上に上がっても、少なくとも 1 つが画面に触れている場合、ACTION_UP ではなく ACTION_POINTER_UP が返されます。

ACTION_POINTER_DOWN および ACTION_POINTER_UP イベントは、アクション値に追加情報をエンコードします。MotionEvent.ACTION_MASK との AND を取るとアクション定数が得られ、ACTION_POINTER_INDEX_MASK との AND を取ると上昇または下降したポインターのインデックスが得られます。

タッチ センサーを離れたポインターのインデックスを抽出する最良の方法。

int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;

以下のように、それに応じてコードを変更します。

case MotionEvent.ACTION_POINTER_UP:
{
    int index = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
    int pointId = event.getPointerId(index);
    Log.d("Controlls", "Action Pointer UP "+ pointerId);
    Log.d("Controlls", "Coordinates "+ event.getX(index) + " "+  event.getY(index));
    break;
}
于 2013-02-22T17:50:50.783 に答える
2

getX()混乱は、メソッドとメソッドgetY()が常にプライマリポインターの座標を返すことである可能性があると思います(最初/唯一のダウン)。したがって、ログのフィンガー 1 の最初の 3 つのイベントがプライマリであり、最後のフィンガー 2 だけが残っているため、それがプライマリになります。

両方の指のイベントを適切に追跡したい場合は、 and を使用する必要がありgetX(int)ますgetY(int)。各イベントの各指の座標を個別に取得できるように、ポインター インデックスをパラメーターとして受け取るバージョン。各指のインデックスは、異なる順序で上下する場合に変更される可能性がありますが、特定の指は常に同じポインター ID を持つことに注意してください。

適切なアプローチは、各イベントのポインターの数を確認することです (例: getPointerCount())。1 本の指では、インデックス 0 が有効です。2 本の指では、インデックス 0 と 1 が有効です。有効な各ポインターの座標を取得し、 を使用getPointerId()して、各座標ペアを一致させる必要がある指を見つけます。

編集

正しいポインターの座標を返すように投稿したソース コードの最も簡単な変更は、次のように、セカンダリ ポインターのパラメーターにインデックスを追加することです。

int index = event.getActionIndex();
int pointerId = event.getPointerId(index);
int action = event.getActionMasked();

int oldX, oldY;

switch (event.getActionMasked()) {
    case MotionEvent.ACTION_DOWN:
    {
        hero.moveControlls((int)event.getX(), (int)event.getY());
        Log.d("Controlls", "Action Down " + pointerId);
        Log.d("Controlls", "Coordinates "+ event.getX() + " "+ event.getY());
        break;
    }

    case MotionEvent.ACTION_UP:
    {
        hero.setScreenTouching(false);
        Log.d("Controlls", "Action UP "+ pointerId);
        Log.d("Controlls", "Coordinates "+ event.getX() + " "+ event.getY());
        break;
    }

    case MotionEvent.ACTION_POINTER_DOWN:
    {
        Log.d("Controlls", "Action Pointer Down "+ pointerId);
        Log.d("Controlls", "Coordinates "+ event.getX(index) + " "+ event.getY(index));
        break;
    }

    case MotionEvent.ACTION_POINTER_UP:
    {
        Log.d("Controlls", "Action Pointer UP "+ pointerId);
        Log.d("Controlls", "Coordinates "+ event.getX(index) + " "+  event.getY(index));
        break;
    }
}

これにより、期待していたものとよりインラインでデータがログに記録されるはずです。

于 2013-01-18T03:32:49.977 に答える