Understanding MotionEvent to implement a virtual DPad and Buttons on Android (Multitouch)
- by Fabio Gomes
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.