android multitouch不能同时移动2个指针

时间:2012-09-25 20:44:16

标签: android multi-touch

我的游戏中有一个奇怪的问题。我正在使用2个操纵杆,一个用于射击/瞄准,一个用于移动我的角色。出于某种原因,我的多点触控方法一次只能记录一个动作。当我按下时,第二个指针被注册,但我的ACTION_MOVE仅适用于第一个指针。这是奇怪的cus,这意味着它确实需要多于一个指针,但它不能同时移动多个指针。我已经在gamedev.stackexchange上问了这个问题并且它已经活动了大约一个星期,得到了几个答案,但没有任何让它100%工作的东西。我自己试了几个小时。

onTouch-method的代码:

    //global variables
    private int movePointerId = -1;
    private int shootingPointerId = -1;

public void update(MotionEvent event) {

    if (event == null && lastEvent == null) {
        return;
    } else if (event == null && lastEvent != null) {
        event = lastEvent;
    } else {
        lastEvent = event;
    }   

    // grab the pointer id 
    int action = event.getAction();
    int actionCode = action & MotionEvent.ACTION_MASK;
    int actionIndex = event.getActionIndex();
    int pid = action >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
    int x = (int) event.getX(pid);
    int y = (int) event.getY(pid); 
    String actionString = null;


    switch (actionCode)
    {
        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_POINTER_DOWN:

            actionString = "DOWN";
            try{
                if(x > 0 && x < steeringxMesh + (joystick.get_joystickBg().getWidth() * 2)
                   && y > yMesh - (joystick.get_joystickBg().getHeight()) && y < panel.getHeight()){
                        movingPoint.x = x;
                        movingPoint.y = y;
                        movePointerId = pid;
                        dragging = true;
                        //checks if Im pressing the joystick used for moving
                    }
                 else if(x > shootingxMesh - (joystick.get_joystickBg().getWidth()) && x < panel.getWidth()
                         && y > yMesh - (joystick.get_joystickBg().getHeight()) && y < panel.getHeight()){
                        shootingPoint.x = x;
                        shootingPoint.y = y;
                        shootingPointerId = pid;
                        shooting=true;
                        //checks if Im pressing the joystick used for shooting
                    }
                }catch(Exception e){

                }
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_POINTER_UP:
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_OUTSIDE:

           if( pid == movePointerId ){
              movePointerId = -1;
              dragging = false;
              }
           else if( pid == shootingPointerId ){
              shootingPointerId = -1;
              shooting=false;
              }
            actionString = "UP";
            break;  
        case MotionEvent.ACTION_MOVE: // this is where my problem is

          if( pid == movePointerId ) {
                        movingPoint.x = x;
                        movingPoint.y = y;
          } else if( pid == shootingPointerId ) {
                        shootingPoint.x = x;
                        shootingPoint.y = y;
          }
                actionString = "MOVE";
                break;

    }

如果我打印actionStringpid,则表示在移动时,它只检查pid=0,但是当我按下(ACTION_POINTER_DOWN)时,我可以看到它确实注册另一个pid,这真的让我感到困惑。

为了让它更清晰,当我按下第二个指针时,例如我的射击棒,它会占据我按下的位置,即使我同时移动另一个操纵杆,但它呆在那里,直到我放开另一个操纵杆。更确切地说,它确实注册了超过1次触摸,然后超过1 pid

如果您需要进一步的解释,请告诉我。

3 个答案:

答案 0 :(得分:2)

我对您的代码进行了一些更改,我认为应该可以解决问题。至少它对我来说很好......

    //global variables 
private int movePointerId = -1; 
private int shootingPointerId = -1; 

public void update(MotionEvent event) { 

if (event == null && lastEvent == null) { 
    return; 
} else if (event == null && lastEvent != null) { 
    event = lastEvent; 
} else { 
    lastEvent = event; 
}    

// grab the pointer id  
int action = event.getAction(); 
int actionCode = action & MotionEvent.ACTION_MASK; 
int pid = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
int fingerid = event.getPointerId(pid);

//int actionIndex = event.getActionIndex(); 
//int pid = action >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 
int x = (int) event.getX(pid); 
int y = (int) event.getY(pid);  
String actionString = null; 


switch (actionCode) 
{ 
    case MotionEvent.ACTION_DOWN: 
    case MotionEvent.ACTION_POINTER_DOWN: 

        actionString = "DOWN"; 
        try{ 
            if(x > 0 && x < steeringxMesh + (joystick.get_joystickBg().getWidth() * 2) 
               && y > yMesh - (joystick.get_joystickBg().getHeight()) && y < panel.getHeight()){ 
                    movingPoint.x = x; 
                    movingPoint.y = y; 
                    //movePointerId = pid; 
                    movePointerId = fingerid; 
                    dragging = true; 
                    //checks if Im pressing the joystick used for moving 
                } 
             else if(x > shootingxMesh - (joystick.get_joystickBg().getWidth()) && x < panel.getWidth() 
                     && y > yMesh - (joystick.get_joystickBg().getHeight()) && y < panel.getHeight()){ 
                    shootingPoint.x = x; 
                    shootingPoint.y = y; 
                    //shootingPointerId = pid; 
                    shootingPointerId = fingerid; 
                    shooting=true; 
                    //checks if Im pressing the joystick used for shooting 
                } 
            }catch(Exception e){ 

            } 
        break; 
    case MotionEvent.ACTION_UP: 
    case MotionEvent.ACTION_POINTER_UP: 
    case MotionEvent.ACTION_CANCEL: 
    case MotionEvent.ACTION_OUTSIDE: 

       if( fingerid == movePointerId ){  //changed this line
          movePointerId = -1; 
          dragging = false; 
          } 
       else if( fingerid == shootingPointerId ){  //changed this line
          shootingPointerId = -1; 
          shooting=false; 
          } 
        actionString = "UP"; 
        break;   
    case MotionEvent.ACTION_MOVE: // this is where my problem is 

      if( fingerid == movePointerId ) { //changed this line
                    movingPoint.x = x; 
                    movingPoint.y = y; 
      } else if( fingerid == shootingPointerId ) { //changed this line
                    shootingPoint.x = x; 
                    shootingPoint.y = y; 
      } 
            actionString = "MOVE"; 
            break; 

} 

原因是在某些设备上,当您释放一根手指时,指针ID可能会发生变化。例如,第一个手指接收指针ID 1,然后按下接收指针ID 2的第二个手指,如果然后释放手指1,手指2的指针ID可能变为1.听起来有点令人困惑,但你应该避免上面这个手指的问题。

祝你好运。

答案 1 :(得分:1)

指针有两种不同的属性可用于识别它们:

  • index :它的范围是0到1,小于 getPointerCount()返回的值。 仅在处理当前事件期间有效

  • id :此属性唯一标识指针,并保证指针在整个生命周期内保持不变

在您的代码中,您无法正确检索索引 ID 信息。基本上,您使用索引来识别跨多个事件的指针,这是完全错误的,因为索引可能会有所不同,这正是您在应用中遇到的情况。简而言之,你应该使用id来识别指针

正如我所提到的,他们检索索引 id 的方法是错误的。检索这些属性的正确方法是:

int action = event.getAction();
int actionCode = action & MotionEvent.ACTION_MASK;
int index = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
             MotionEvent.ACTION_POINTER_INDEX_SHIFT;
int pid = event.getPointerId(index);

您可以在此处参阅更多信息:MotionEvent | Android Developers

答案 2 :(得分:0)

private int movePointerId = -1;private int shootingPointerId = -1;,他们不应该有不同的价值观吗?我真的不知道但是一旦我遇到了问题,那么我就改变了价值观并且有效。