Understanding MotionEvent to implement a virtual DPad and Buttons on Android (Multitouch)

Posted by Fabio Gomes on Game Development See other posts from Game Development or by Fabio Gomes
Published on 2011-02-17T15:00:29Z Indexed on 2011/02/17 15:34 UTC
Read the original article Hit count: 708

Filed under:
|
|
|

I once implemented a DPad in XNA and now I'm trying to port it to android, put, I still don't get how the touch events work in android, the more I read the more confused I get.

Here is the code I wrote so far, it works, but guess that it will only handle one touch point.

public boolean onTouchEvent(MotionEvent event)
    {
        if (event.getPointerCount() == 0) 
            return true;

        int touchX = -1;
        int touchY = -1;

        pressedDirection = DPadDirection.None;
        int actionCode = event.getAction() & MotionEvent.ACTION_MASK;
            if (actionCode == MotionEvent.ACTION_UP)
            {
                if (event.getPointerId(0) == idDPad)
                {
                    pressedDirection = DPadDirection.None;
                    idDPad = -1;
                }
            }
            else if (actionCode == MotionEvent.ACTION_DOWN || actionCode == MotionEvent.ACTION_MOVE)
            {                                     
                touchX = (int)event.getX();
                touchY = (int)event.getY();


                if (rightRect.contains(touchX, touchY))
                    pressedDirection = DPadDirection.Right;
                else if (leftRect.contains(touchX, touchY))
                    pressedDirection = DPadDirection.Left;
                else if (upRect.contains(touchX, touchY))
                    pressedDirection = DPadDirection.Up;
                else if (downRect.contains(touchX, touchY))
                    pressedDirection = DPadDirection.Down;

                if (pressedDirection != DPadDirection.None)
                    idDPad = event.getPointerId(0);

            }              

        return true;
    }

The logic is:

Test if there is a "DOWN" or "MOVED" event, then if one of this events collides with one of the 4 rectangles of my DPad, I set the pressedDirectin variable to the side of the touch event, then I read the DPad actual pressed direction in my Update() event on another class.

The thing I'm not sure, is how do I get track of the touch points, I store the ID of the touch point which generated the diretion that is being stored (last one), so when this ID is released I set the Direction to None, but I'm really confused about how to handle this in android, here is the code I had in XNA:

 public override void Update(GameTime gameTime)
        {
            PressedDirection = DpadDirection.None;
            foreach (TouchLocation _touchLocation in TouchPanel.GetState())
            {
                if (_touchLocation.State == TouchLocationState.Released)
                {
                    if (_touchLocation.Id == _idDPad)
                    {
                        PressedDirection = DpadDirection.None;
                        _idDPad = -1;
                    }
                }
                else if (_touchLocation.State == TouchLocationState.Pressed || _touchLocation.State == TouchLocationState.Moved)
                {                                     
                    _intersectRect.X = (int)_touchLocation.Position.X;
                    _intersectRect.Y = (int)_touchLocation.Position.Y;
                    _intersectRect.Width = 1;
                    _intersectRect.Height = 1;

                    if (_intersectRect.Intersects(_rightRect))
                        PressedDirection = DpadDirection.Right;
                    else if (_intersectRect.Intersects(_leftRect))
                        PressedDirection = DpadDirection.Left;
                    else if (_intersectRect.Intersects(_upRect))
                        PressedDirection = DpadDirection.Up;
                    else if (_intersectRect.Intersects(_downRect))
                        PressedDirection = DpadDirection.Down;

                    if (PressedDirection != DpadDirection.None)
                    {
                        _idDPad = _touchLocation.Id;
                        continue;
                    }

                }              
            }

            base.Update(gameTime);            
        }

So, first of all: Am I doing this correctly? if not, why?

I don't want my DPad to handle multiple directions, but I still didn't get how to handle the multiple touch points, is the event called for every touch point, or all touch points comes in a single call? I still don't get it.

© Game Development or respective owner

Related posts about java

Related posts about android