android multitouch cant move 2 pointers at same time
Asked Answered
P

3

0

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.

Plier answered 25/9, 2012 at 20:44 Comment(1)
I replaced the constants ID by INDEX as the previous are deprecated.Rintoul
R
2

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.

Rintoul answered 26/9, 2012 at 0:22 Comment(0)
S
1

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

Swithin answered 14/12, 2013 at 18:0 Comment(0)
D
0

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.

Disarmament answered 25/9, 2012 at 20:52 Comment(2)
I dont think so, no. since Im setting them =pid as soon as I use them. And they get values 0 and 1 for first and second pointer.Plier
this is more suited as a comment then an answer btw.Plier

© 2022 - 2024 — McMap. All rights reserved.