android multitouch cant move 2 pointers at same time

旧巷老猫 提交于 2019-12-13 04:28:27

问题


I have a weird problem in my game. I'm using 2 joysticks, one for shooting/aiming and one for moving my character. For some reason my multitouch method only registers one movement at a time. The second pointer gets registered when I press down, but my ACTION_MOVE only works for the first pointer. This is weird cus this means it does take more then one pointer, but it cant move more then one pointer at the same time. Ive asked this on gamedev.stackexchange and its been active for about a week, gotten a couple of answer but nothing that makes it work 100%. And I've tried for hours on my own.

Code for 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;

    }

If I print actionString and pid it shows that when moving, it only checks pid=0, but when i press down ( ACTION_POINTER_DOWN ) I can see that it does register another pid, this is whats really confusing me.

Just to make it more clear, when I press the second pointer down on for example my shooting-stick, it takes the position of where I pressed, even if I'm moving the other joystick at the same time, but it stays there until I let go of the other joystick. Furhter proof that it does register more then 1 touch and more then 1 pid.

Please let me know if you need any further explenation.


回答1:


I've made a couple of changes to your code, that I believe should solve the problem. Al least it works fine for me ...

    //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; 

} 

The reason for this is that on some devices de pointer id may change when you release one finger. For example, first finger receives pointer id 1, then you press second finger which receives pointer id 2, and if then you release finger 1, pointer id from finger 2 may become 1. It may sound a bit confusing, but you should avoid the issue with this finger id above.

good luck.




回答2:


Pointers have two different properties available to identify them:

  • index: it ranges from 0 to one less than the value returned by getPointerCount(). It is only valid during the processing of the current event.

  • id: this property uniquely identifies the pointer, and is guaranted to stay the same for the pointer during its whole lifetime.

In your code you are not correctly retrieving the index and id info. Basically you are using the index to identify the pointer across several events, something that is completely wrong, as the index may vary, which is what you are experiencing in your app. In short, you should be using the id to identify the pointer.

As I mentioned, they way you are retrieving index and id is wrong. The correct way to retrieve those properties would be:

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);

You can refer here for more info: MotionEvent | Android Developers




回答3:


private int movePointerId = -1; and private int shootingPointerId = -1;, shouldn't them have different values? i dont know really but once i had it a problem then i changed the values and it worked.



来源:https://stackoverflow.com/questions/12590738/android-multitouch-cant-move-2-pointers-at-same-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!