Thank you for taking the time for such a great reply. I have couple of comments still though.

On 5/19/2011 3:35 AM, Jeffrey Brown wrote:
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.
I'm targeting min sdk of 7 (5 actually it it seems to have been misplaced) and this is level 8.
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.
Something should be added to the docs about this then.
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.
I get a down event for one finger, say it lands on my virtual gamepad. The user holds that finger down and slides the control around to make their unit move. Now they put another finger down on a fire button while the previous finger is still on the gamepad. At this point I think you're suggesting I clear the first finger on the gamepad. It doesn't sound right.
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.
I'm all for this but every game engine I have found for Android does this, even Replica Island. How sure are you of this? Keep in mind that my game needs to run on older 2.0 that might suffer from this problem.

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

--
Leigh McRae
http://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

Reply via email to