ccTouchesBegan always get only 1 touch point when doing multitouch

Hi,

I added the ccTouchesBegan on android in the sample helloworld as below:

If I touched 2 points , this method will return 2 touches by calling ccTouchesBegan twice and each calling only has 1 touch point information.
How can I get 2 or more touch information by calling this method only once?

void HelloWorld::ccTouchesBegan(CCSet* pTouches,CCEvent* pEvent)
{
LOGD (“the touch count is %d”,pTouches->count());
CCSetIterator iter=pTouches->begin();

for (;iter!=pTouches->end();iter++){

CCTouch* touch=(CCTouch*)(*iter);
LOGD (“ccTouch id is %d”,touch->getID());
}
}

Thanks.

Afaik there is no way to set ccTouchesBegan and similar methods in such way to get 2 or more touches at once always. Sometimes you will get 2 sometimes you get only one touch even if there are more active touches, sorry. If you need to have information about more active touches at once for example to process them together in ccTouchesMoved then probably you will need to write your own solution for this. A workaround could be to save information about touches somewhere when ccTouchesBegan came in and delete the information in ccTouchesEnded. For example you could create some simple structure:

typedef struct TouchInfo
{
    int id;
    CCPoint point;
    CCPoint prevPoint;
} TouchInfo;

and a variable std::vector mTouches; and save information about touches in it to have an access to information about all touches when you need them.

As you say, ccTouchesBegan will be called once for each touch.

In my code, I store the address of the touch event.

CCTouch* touch;
touch = (CCTouch*)touches->anyObject();

if(touchid == 0){
  touchid = (int)touch;
}
else if(touchid2 == 0)
{
  touchid2 = (int)touch;
}

In ccTouchesMoved you get an array of the touches each time, I loop round the array and handle each one individually.

CCSetIterator it = touches->begin();

for(int i=0; icount(); i++){
  handleTouchMove((CCTouch*)(*it));
  it++;
}

In handleTouchMove I compare the (int)touch to the touchid and touchid2 and then do whatever I need to do with each touch.
In my case I move the start point, end point and rotation of a sprite to follow the fingers.

In ccTouchesEnded I set touchid and touchid back to 0.

This might not be the best way to handle multi touch but works for me.

You can use touch->getID() instead of casting pointer to CCTouch to int to distinguish touches.

I read somewhere that getID() didn’t work (or returned 0 or something) but can’t remember the details and it was a while ago.
Have you used getID and can confirm it works?

I also read this somewhere but it seems that it is fixed and is working in v2.0.4. I’m using it and I did not noticed any problems.

To explain the practical reason : there is no way a human user is going to tap 2 (or more) fingers at exactly the same time (less than a loop time, about 1/60 sec).

It also depends on the implementation : on iOS, the begin method will be called for each touch (since it notify per touch, not with an array). Batching the touch begins would introduce an unecessary delay.

Adam Reed wrote:

I read somewhere that getID() didn’t work (or returned 0 or something) but can’t remember the details and it was a while ago.
Have you used getID and can confirm it works?

Yes. I tested the getID and it works .

But I still wonder if ccTouchesBegan can return the multi touch by called once .

I found the java code to return touch event in class Cocos2dxGLSurfaceView in src/org/cocos2dx/lib/Cocos2dxGLSurfaceView.java

Can I modify the code directly to make the ccTouchesBegan able to get all the multi touch for only 1 called?

Why does cocos2d-x’s ccTouchesBegan return each touch for each call?

Fan Wang wrote:

But I still wonder if ccTouchesBegan can return the multi touch by called once .

Probably not and even if you cound set this then as François said user would have to touch te screen with both fingers at 1/60sec = 16ms delay which is almost impossible and would give a fail if you would rely on this. It would be much better if there was a method in cocos2d-x that can return all active touches (for fingers that are currenty on screen) but I did not see something like that. Also it would be useful if CCTouch had information about time when touch began but also this feature is not available.

Leszek Leszek wrote:

Fan Wang wrote:
> But I still wonder if ccTouchesBegan can return the multi touch by called once .
>
Probably not and even if you cound set this then as François said user would have to touch te screen with both fingers at 1/60sec = 16ms delay which is almost impossible and would give a fail if you would rely on this. It would be much better if there was a method in cocos2d-x that can return all active touches (for fingers that are currenty on screen) but I did not see something like that. Also it would be useful if CCTouch had information about time when touch began but also this feature is not available.

But the android sdk can return all touches at 1 time. and if the cocos2d implements the touch by JNI , the cocos2d should be able to do it too.

François ,

Indeed the 2 touches is not at the exactly same time, And it will cause 1 problem by using current ccTouchesBegan: There will be touchesMoved between the 1st and 2nd touch even if I actually want to do multi touch. unless remembering the touches’ time as Leszek said, how to recognize the 1st moved is an actual move or just a meaningless move ?

Fan Wang wrote:

But the android sdk can return all touches at 1 time. and if the cocos2d implements the touch by JNI , the cocos2d should be able to do it too.

cocos2d doesn’t implement everything the native implementations allows, for various reasons (doesn’t really fit in, can’t be done on other platforms etc…). If you have a specific need, by all mean implement it yourself. It’s pretty straightforward, from begin and end events, to reconstruct an array of active touches.

>

François ,
>
Indeed the 2 touches is not at the exactly same time, And it will cause 1 problem by using current ccTouchesBegan: There will be touchesMoved between the 1st and 2nd touch even if I actually want to do multi touch. unless remembering the touches’ time as Leszek said, how to recognize the 1st moved is an actual move or just a meaningless move ?

There are 2 variables you should check if you want to detect “2 tap at the same time” : the time at which the touch did begin, and the total movement since the beginning. You’ll have to do that yourself, since cocos2d, as far as I know, doesn’t have any gesture recognizer.

For the total movement, I advise to add ccpDistance(position, previousPosition) to a distance counter associated to the touch. Some good values would be a maximum of 0.5 sec and a maximum of 50 pixels total movement after which a touch is discarded as a possible tap.

Hope this helps.

Btw. is there any way to convert pixels to real physical distance on screen? For example if I want to know if user moved a finger 1 centimeter or 1 inch but I have only pixel values then is there any method to convert this?

Thank everyone.

Leszek Leszek wrote:

Btw. is there any way to convert pixels to real physical distance on screen? For example if I want to know if user moved a finger 1 centimeter or 1 inch but I have only pixel values then is there any method to convert this?

How about to get the screen’s DPI and calculate?

How can I get DPI? Is there any method available in cocos2d-x for this?