Some tips:
1. Use MotionEvent.getActionMasked() and MotionEvent.getActionIndex()
to retrieve the masked action and changed pointer id respectively.
This will remove the need for your own masking and shifting code,
which is currently using deprecated constants.
2. Your code for ACTION_MOVE contains: "ptrId =
event.getPointerId( index ); if ( ptrId>= 0 ) { ...} ". The pointer
id returned by getPointerId will always be >= 0 so you can omit this
condition.
3. You need to be more careful in your handling of ACTION_CANCEL.
When ACTION_CANCEL is received, you should reset the state for *all*
of the pointers you think are down. So you should keep track of which
pointers you think are down, loop over them and cancel them all.
4. Before handling ACTION_DOWN, you should do the work of canceling
all pointers you think are down. If everything is working properly,
then there shouldn't be any pointers down. However, if your code did
not receive the matching ACTION_UP or ACTION_CANCEL from a previous
gesture, it's possible that some pointers got *stuck* down. So you
want to clear those out before you start handling the new pointers.
5. The sleep() is entirely unnecessary. It is just making the input
latency of your game worse. Remove it. The framework already
throttles move events for you.
Jeff.
On May 18, 8:40 am, Leigh McRae <[email protected]>
wrote:
> The blog
> posthttp://android-developers.blogspot.com/2010/06/making-sense-of-multit...
> was a good read but oddly enough it doesn't really covermulti-touch
> IMHO. It covers tracking a single touch where another touch could
> follow. My game needs to track one touch for the game pad and then at
> least another for the fire buttons.
>
> Currently my game is broken on the Xoom and I'm assuming it's because
> of the same problem this thread talks about. I can make the changes as
> others have suggested by mapping but I still have some issues. I'm not
> sure if I handle Cancel correctly. It's a really large concern as my
> game captures pointers so I know whether the finger was over the button
> it pressed when it was released. I really need to get matching events
> or buttons will get stuck. It's not so bad when IDs are 0 or 1 but when
> they cycle to 15 it will be harsh.
>
> As you can see I have added some sleep code below but I'm not sure if
> it's needed. It's really hard to know what to do here as people
> complain about unresponsive controls but they work fine on my phone and
> I just don;t have the funds to be buy 3-4 other phones.
>
> Here is my code I use to inject pointer events into my game engine.
>
> @Override
>
> public boolean onTouch( View v, MotionEvent event )
>
> {
>
> int action = event.getAction();
>
> int numPointers = event.getPointerCount();
>
> int ptrIndex = (numPointers> 1) ? (action&
> MotionEvent.ACTION_POINTER_ID_MASK)>> MotionEvent.ACTION_POINTER_ID_SHIFT :
> 0;
>
> int ptrId = event.getPointerId( ptrIndex );
>
> PointerEvent pe = null;
>
> switch( action& MotionEvent.ACTION_MASK )
>
> {
>
> case MotionEvent.ACTION_DOWN:
>
> case MotionEvent.ACTION_POINTER_DOWN:
>
> pe = (PointerEvent)m_PointerEvents.alloc();
>
> if ( pe != null )
>
> {
>
> pe.owner = m_PointerEvents;
>
> pe.action = PointerEvent.ACTION_DOWN;
>
> pe.id = ptrId;
>
> pe.x = (int)event.getX( ptrIndex );
>
> pe.y = (int)event.getY( ptrIndex );
>
> m_App.getGame().postUIEvent( pe );
>
> //m_App.getLogger().verbose( pe.toString() );
>
> }
>
> break;
>
> case MotionEvent.ACTION_UP:
>
> case MotionEvent.ACTION_POINTER_UP:
>
> case MotionEvent.ACTION_CANCEL:
>
> pe = (PointerEvent)m_PointerEvents.alloc();
>
> if ( pe != null )
>
> {
>
> pe.owner = m_PointerEvents;
>
> pe.action = PointerEvent.ACTION_UP;
>
> pe.id = ptrId;
>
> pe.x = (int)event.getX( ptrIndex );
>
> pe.y = (int)event.getY( ptrIndex );
>
> m_App.getGame().postUIEvent( pe );
>
> //Log.v( "POINTER", te.toString() );
>
> }
>
> break;
>
> case MotionEvent.ACTION_MOVE:
>
> {
>
> // There are reports that move touch evens can flood the
> system. The suggested
>
> // solution is to sleep after a move. I don't want to
> sleep unless I have to
>
> // since it could cause controls to be unresponsive. So
> instead I will only sleep
>
> // if we get more than one move event within a 60Hrz
> frame and then I will only
>
> // sleep as much as I need. It's very much along the
> lines of a update loop.
>
> long currentTime = System.currentTimeMillis();
>
> long elapsed = currentTime -
> m_LastMoveEventTime;
>
> if ( elapsed< 16L )
>
> {
>
> try
>
> {
>
> Thread.sleep( Math.max( 0, 16L - elapsed ) );
>
> }
>
> catch( InterruptedException e )
>
> {
>
> Thread.currentThread().interrupt();
>
> }
>
> break;
>
> }
>
> for( int index = 0; index< numPointers; ++index )
>
> {
>
> ptrId = event.getPointerId( index );
>
> if ( ptrId>= 0 )
>
> {
>
> pe = (PointerEvent)m_PointerEvents.alloc();
>
> if ( pe != null )
>
> {
>
> pe.owner = m_PointerEvents;
>
> pe.action = PointerEvent.ACTION_DRAG;
>
> pe.id = ptrId;
>
> pe.x = (int)event.getX( index );
>
> pe.y = (int)event.getY( index );
>
> m_App.getGame().postUIEvent( pe );
>
> //Log.v( "POINTER", te.toString() );
>
> }
>
> }
>
> }
>
> m_LastMoveEventTime = currentTime;
>
> }
>
> break;
>
> }
>
> return true;
>
> }
>
> Leigh
>
> On 5/17/2011 2:01 AM, Jeffrey Brown wrote:
>
>
>
>
>
>
>
>
>
> > Pointer IDs are arbitrary integers. The only guarantee is that they
> > will be unique for a given finger as long as that finger remains down.
> > Once the finger goes up, the id may be reused for a different finger,
> > or it may not. It really depends.
>
> > The problem with spurious ACTION_DOWN events is strictly a software
> > issue, not hardware. It happens when applications filter or modify
> > the stream of touch events in a manner that causes them to become
> > incomplete or inconsistent. The bugs can be quite subtle.
>
> > Jeff.
>
> > On Mon, May 16, 2011 at 3:56 PM, MichaelEGR<[email protected]> wrote:
> >> ugh! Thanks for posting this message as this is a gnarly one and an
> >> example of ODM fragmentation if pointed IDs are not indexing correctly
> >> to the proper point data at least. I never was impressed by the
> >>multitouchAPI and always thought it wasn't thought out well and
> >> simply just tacked onto MotionEvent. Dirty as you say it is correct. I
> >> also wasn't pleased with the lack of documentation and unclear
> >> contract. Perhaps this lack of documentation led to this potential ODM
> >> fault. As for spurious ACTION_DOWN events this could be from varied
> >> quality of touchscreen hardware too.
>
> >> So from my reading of your post you are saying that pointer IDs are
> >> not recycled and that the data of subsequent pointer IDs is not
> >> correct at the specified array index?
>
> >> Not looking forward to coming up with a solution for my platform /
> >> middleware / custom event system and certainly am not excited if I
> >> need to buy an Experia Play just for this, but w/ talking with Robert
> >> G. it sounds like button support on this device is a bit wacky too. If
> >> I understand correctly button presses don't generate key events? Hrm;
> >> I hope that is not the case as I hate to have to waste $500+ to fix
> >> these kinds of issues. Likely I'll pick one up, fix the issues, then
> >> sell it.
>
> >> Regards,
> >> --Mike
>
> >> On May 16, 12:58 pm, Mario Zechner<[email protected]> wrote:
> >>> A user reported an ArrayIndexOutOfBoundsException today in ourmulti->>>
> >>> touchhandler. We store x/y/touchState on a per pointer id basis in an
> >>> array. Dirty? Yes, but it worked on all devices so far. Usually
> >>> pointer ids are handed out like this:
> >> --
> >> You received this message because you are subscribed to the Google
> >> Groups "Android Developers" group.
> >> To post to this group, send email to [email protected]
> >> To unsubscribe from this group, send email to
> >> [email protected]
> >> For more options, visit this group at
> >>http://groups.google.com/group/android-developers?hl=en
>
> --
> Leigh McRaehttp://www.lonedwarfgames.com/
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en