最后的MotionEvent有奇怪的坐标

时间:2014-03-16 17:13:10

标签: android android-ndk

我们有益智游戏Fruit Dating已经有一段时间了。现在我们得到了一位玩家的报告,他无法触摸菜单中的任何项目。我们通过屏幕调试向他发送了特殊版本。我们专注于接触,他将结果归还给我们:

touch events  拦截了每一个触摸事件。我为图片中的每一个“游戏触摸”分割了一组触摸事件,左边是红线。每个游戏触摸事件都是这样的:向下 - (一个或多个拖动) - 向上。奇怪的是,在触摸之前,触摸拖动事件的触摸坐标总是有很大的跳跃。

我认为大多数拖拽事件只是弹跳但总是至少有一个将坐标跳到左下角。然后使用这些不正确的坐标跟踪事件。当我们检查玩家是否在接触时开始在同一区域(参见区域参数),然后没有任何匹配,玩家感觉游戏卡住了。

报告错误的玩家有THL W200手机。我们以前在许多不同的物理设备上进行了测试,但从未遇到过这个问题......

有没有人知道为什么有这样一个奇怪的坐标的运动事件(拖动)?你们有没有遇到过它?

我们的游戏是具有瘦Java层的JNI。 Motionevents从这样的视图发送到c ++:

@Override
public boolean onTouchEvent(final MotionEvent aEvent) 
{
    final int action = aEvent.getAction();

    queueEvent(new Runnable()
    {
        int motionEvent = -1;

        public void run()
        {
            if (action == MotionEvent.ACTION_DOWN)
            {
                motionEvent = ANDROID_TOUCH_ACTION_DOWN;
            }
            else if (action == MotionEvent.ACTION_UP)
            {
                motionEvent = ANDROID_TOUCH_ACTION_UP;
            }
            else if (action == MotionEvent.ACTION_MOVE)
            {
                motionEvent = ANDROID_TOUCH_ACTION_MOVE;
            }

            SBCEngine.engine_on_touch((int) aEvent.getX(), (int) aEvent.getY(), motionEvent);
        }
    });
    return true;
}

1 个答案:

答案 0 :(得分:0)

终于找到了解决方案,所以如果有人有兴趣......

以上代码不安全。在处理事件之前,引用的事件对象可能会更改。该代码取自关于将Doom和Quake移植到Android的书籍,您可能会在网上找到类似的代码。直到昨天,它一直在所有测试设备上运行它在THL W200设备上失败了。

我将代码更改为:

@Override
public boolean onTouchEvent(final MotionEvent aEvent) 
{
    // get masked (not specific to a pointer) action
    int maskedAction = aEvent.getActionMasked();

    switch (maskedAction)
    {

    case MotionEvent.ACTION_DOWN:
    case MotionEvent.ACTION_POINTER_DOWN:
    {
        // get pointer index from the event object
        int pointerIndex = aEvent.getActionIndex();
        // get pointer ID
        int pointerId = aEvent.getPointerId(pointerIndex);

        //Log.d("POINTER", "pointer down: ID = " + pointerId + " x=" + aEvent.getX(pointerIndex) + ", y = " + aEvent.getY(pointerIndex));
        queueEvent(new MotionEventRunnable(pointerId, maskedAction,
                        (int) aEvent.getX(pointerIndex),
                        (int) aEvent.getY(pointerIndex)));
        break;
    }

    case MotionEvent.ACTION_MOVE:
    { 
        // a pointer was moved
        int size = aEvent.getPointerCount();

        for (int i = 0; i < size; i++)
        {
            // Get the pointer ID and index
            int pointerId = aEvent.getPointerId(i);
            int pointerIndex = aEvent.findPointerIndex(pointerId);

            //Log.d("POINTER", "pointer move: ID = " + pointerId + " x=" + aEvent.getX(pointerIndex) + ", y = " + aEvent.getY(pointerIndex));
            queueEvent(new MotionEventRunnable(pointerId, maskedAction,
                    (int) aEvent.getX(pointerIndex),
                    (int) aEvent.getY(pointerIndex)));
        }
        break;
    }

    case MotionEvent.ACTION_UP:
    case MotionEvent.ACTION_POINTER_UP:
    case MotionEvent.ACTION_CANCEL:
    {
        // get pointer index from the event object
        int pointerIndex = aEvent.getActionIndex();
        // get pointer ID
        int pointerId = aEvent.getPointerId(pointerIndex);

        //Log.d("POINTER", "pointer up: ID = " + pointerId + " x=" + aEvent.getX(pointerIndex) + ", y = " + aEvent.getY(pointerIndex));
        queueEvent(new MotionEventRunnable(pointerId, maskedAction,
                (int) aEvent.getX(pointerIndex),
                (int) aEvent.getY(pointerIndex)));
        break;
    }
    }

    return true;
}

使用MotionEventRunnable类:

class MotionEventRunnable implements Runnable
{
    private int mPointerID;
    private int mActionID;
    private int mX, mY;

  //-----------------------------------------------------
    public MotionEventRunnable(int aPointerID, int aActionID, int aX, int aY)
    {
        mPointerID = aPointerID;
        mActionID = aActionID;
        mX = aX;
        mY = aY;
    }

  //-----------------------------------------------------
    @Override
    public void run()
    {
        // send to native
        SBCEngine.engine_on_touch(mPointerID, mX, mY, mActionID);
    }
}

代码更复杂,因为它也处理多点触控,但关键是我缓存了所有必需的值:指针id,动作,x和y。它解决了我的问题。

相关问题