Multi-touch acting strange on iOS

So I’ve looked at the multitouchTest.cpp file to make this code. It gets 2 touch points and creates a lighting bolt between them. It works perfectly on Android. But on iOS, it acts weird. When pressing 2 fingers on the screen at the same time, it looses track of everything. It seems that this isn’t the correct way to handle multi-touch on iOS. Am I missing something?

void HelloWorld::ccTouchesBegan(CCSet* touches, CCEvent* event)
{
//grunt~~>setPosition.x+1,grunt~~>getPosition().y));

if(powerObj.energy >=.5)
{
//lightningOn = true;
CCSetIterator iter = touches~~>begin;
for ; iter++)
{
CCTouch* touchPoint = ;
if0)
{
CCLog(“TOUCH_1”);
location1 = touchPoint->getLocationInView();
location1 = CCDirector::sharedDirector()->convertToGL(location1);

            }

            else if(touchPoint-\>getID()1)

{

CCLog;
location2 = touchPoint~~>getLocationInView();
location2 = CCDirector::sharedDirector()>convertToGL;
CCSprite* lightning = CCSprite::create;
lightning
>setScale(.4);
lightning~~>setPosition/2,/2));
lightning~~>setScaleX(ccpDistance(location1,location2)/1920);
this~~>addChild;

float angleRad = atanf/);
float angleDeg = CC_RADIANS_TO_DEGREES;
lightning~~>setRotation(angleDeg);
CCAction* removeChild = CCCallFuncN::create);
CCAction* fadeAway = CCFadeOut::create;
lightning
>runAction(CCSequence::create(animInt.lightningAnimation(), removeChild ,NULL));

lightning->runAction(fadeAway);

}

}

}

}

I did not analyze your code but maybe you just did not enabled multitouch (it is disabled on ios by default). See http://www.cocos2d-x.org/projects/cocos2d-x/wiki/How_to_Enable_Multi-Touch

Leszek X wrote:

I did not analyze your code but maybe you just did not enabled multitouch (it is disabled on ios by default). See http://www.cocos2d-x.org/projects/cocos2d-x/wiki/How_to_Enable_Multi-Touch

Thank you for the response and yes, I have
[__glView setMultipleTouchEnabled:YES];
in my appController.mm

If I hold down the first touch and slowly press the second touch it works. So I know multi-touch is working.
Anyone know what might be wrong? It still acts weird.

Have you just upgraded your Cocos2d-x to a new version?

Gav GMTDev wrote:

Have you just upgraded your Cocos2d-x to a new version?

I’m using 2.1.1.

Yeah I went to V2 a while ago and found the same thing, kinda forgot about it after doing a little hack in my Cocos2d-x myself. I found ……
was wrong, checked with latest build - see below.

Gav GMTDev wrote:

Yeah I went to V2 a while ago and found the same thing, kinda forgot about it after doing a little hack in my Cocos2d-x myself. I found that the “getID()” value from CCTouch is not being saved, or is being overwritten by another id value; I didn’t check to see if this was on purpose so for a quick fix I simply added a second “id” to the CCTouch class.
>
See if this fixes it and if it does then it is probably an issue with Cocos2d-x that needs a fix.
>

  1. If you do a search on “setTouchInfo”. You should find 6 calls in CCEGLViewProtocol.cpp and one in CCTouch.h
  2. Look at the CCTouch.h and add a second “m_nId2” and an “getID2()” function so the code looks like below
    […]
    >
  3. Now go through all the “setTouchInfo” calls in the CCEGLViewProtocol.cpp file, you will need to change them in the following order. Note the last parameter (for the id2) is the addition:-
    […]
    >
    Note: in the above I think the problem comes from the ID we want (originally nUnusedIndex) is being overwritten by “pIndex~~>getValue" in the third and subsequent setTouchInfo calls. Hence the fix is to pass on the previously stored ID in our added parameter "pTouch~~>getID2()”.
    >
  4. In your own code, replace your “getID()” calls with “getID2()”.
  5. That’s all.
    >
    If that works, then I think the problem is as I described above. Maybe the “pIndex->getValue()” value in the setTouchInfo’s is the problem and just needs replacing. If we were to do this it would need testing and confirming by the person who wrote it.
    Thanks for the response. I’ve seen you a lot on the forums here and decided to check out your Arrow Mania game. Looks pretty cool! I’ll be sure to buy it when it’s out on Android :slight_smile:
    As for your code adjustments. I can only find 3 calls for setTouchInfo but I changed them like you said, adjusted CCTouch.h, and it still acts up. :confused:

Hey, yeah I just downloaded the latest cocos2d-2.1rc0-x-2.1.2 and it seems to be fine, ignore what I wrote above.

I did check it by adding multi touch to the HelloCpp sample, you can download it here: http://www.gmtdev.com/files/HelloCpp-2.1.2-multitouch.zip
The output goes to the Output window - looks fine to me, try it yourself, one finger, two fingers, three, let one up, etc.

Thanks for the compliments on Arrow Mania! Android version should be out in about a week, been putting off finishing it too long, will let you know!

Gav GMTDev wrote:

Hey, yeah I just downloaded the latest cocos2d-2.1rc0-x-2.1.2 and it seems to be fine, ignore what I wrote above.
>
I did check it by adding multi touch to the HelloCpp sample, you can download it here: http://www.gmtdev.com/files/HelloCpp-2.1.2-multitouch.zip
The output goes to the Output window - looks fine to me, try it yourself, one finger, two fingers, three, let one up, etc.
>
Thanks for the compliments on Arrow Mania! Android version should be out in about a week, been putting off finishing it too long, will let you know!

I upgraded it and it still acts strange. Multitouch in general seems to work. It always has. It’s just when I press at the same time, I think it’s recognizing it as one touch. My log still says
Touch1
Touch 2
Touch 2
Touch 1

Have two ‘2’ in a row should be impossible. It’s almost like it’s not fast enough to realize that both fingers have been lifted and pressed again. I try to reproduce the glitch, but it’s pretty random.

Yeah it shouldn’t do that.

Try my download: http://www.gmtdev.com/files/HelloCpp-2.1.2-multitouch.zip

It should give you output like my screen capture attached.

Gav GMTDev wrote:

Yeah it shouldn’t do that.
>
Try my download: http://www.gmtdev.com/files/HelloCpp-2.1.2-multitouch.zip
>
It should give you output like my screen capture attached.

Could you briefly explain how to import/run it through Xcode?

Sure, I built it from the HelloCPP sample so download the zip file and move it to the folder “/cocos2d-2.1rc0-x-2.1.2/samples/Cpp/HelloCpp-2.1.2-multitouch.zip”. Unzip it, it will probably end up in a folder called “HelloCpp 2”.

Open the project file “HelloCpp 2/proj.ios/HelloCpp.xcodeproj” (just double click it, that should open it in XCode).

Run it.

Gav GMTDev wrote:

Yeah it shouldn’t do that.
>
Try my download: http://www.gmtdev.com/files/HelloCpp-2.1.2-multitouch.zip
>
It should give you output like my screen capture attached.

If you look at the file I’ve attached. I’ve highlighted 3 lines of output
Line1: Touch1 has ended
Line2: Touch0 has ended
At this point, no fingers are on the screen according to the log.
Line3: Touch1 has begun
This is my issue. How could Touch1 begin without Touch0 begining first?

David Small wrote:

This is my issue. How could Touch1 begin without Touch0 begining first?

I assume you are tapping the screen with two fingers at the same time?

My explanation (guess) would be one of these, take your pick:

  1. The system is message based, the sender is sending messages and, two arrived at the same time and that is just the order they got processed.
  2. Google “Concurrent programming”. (I did it for you: http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html)
  3. I could be wrong - it could be broken like you think.

The fact that one had id1 and the other id0 shouldn’t make any difference to you. You can’t rely on the same finger having the same ID number (if that is what you are talking about). It’s the same as someone putting 5 fingers down and lifting two fingers off and putting them back down in different orders - you can’t know what ID number they will get or assign an ID number to that finger just because it had that ID before. Confused? Me too!

Gav GMTDev wrote:

David Small wrote:
> This is my issue. How could Touch1 begin without Touch0 begining first?
>
I assume you are tapping the screen with two fingers at the same time?
>
My explanation (guess) would be one of these, take your pick:
>

  1. The system is message based, the sender is sending messages and, two arrived at the same time and that is just the order they got processed.
  2. Google “Concurrent programming”. (I did it for you: http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html)
  3. I could be wrong - it could be broken like you think.
    >
    The fact that one had id1 and the other id0 shouldn’t make any difference to you. You can’t rely on the same finger having the same ID number (if that is what you are talking about). It’s the same as someone putting 5 fingers down and lifting two fingers off and putting them back down in different orders - you can’t know what ID number they will get or assign an ID number to that finger just because it had that ID before. Confused? Me too!

Sorry about the long response. College is getting the best of me. I’ve added a link to a youtube video that demonstrates the problem. It’s almost like one of the touches doesn’t end correctly. I touch the screen with 2 fingers 3 times. The 3rd double tap is what is messing up. It’s not always the 3rd tap though.

Gav GMTDev wrote:

David Small wrote:
> This is my issue. How could Touch1 begin without Touch0 begining first?
>
I assume you are tapping the screen with two fingers at the same time?
>
My explanation (guess) would be one of these, take your pick:
>

  1. The system is message based, the sender is sending messages and, two arrived at the same time and that is just the order they got processed.
  2. Google “Concurrent programming”. (I did it for you: http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html)
  3. I could be wrong - it could be broken like you think.
    >
    The fact that one had id1 and the other id0 shouldn’t make any difference to you. You can’t rely on the same finger having the same ID number (if that is what you are talking about). It’s the same as someone putting 5 fingers down and lifting two fingers off and putting them back down in different orders - you can’t know what ID number they will get or assign an ID number to that finger just because it had that ID before. Confused? Me too!

Hey did you take a look at my video, any suggestions? Oh and how’s Arrow Mania coming along? :slight_smile:

David in the screenshot that you have attached (http://www.cocos2d-x.org/attachments/1913/Screen%20Shot%202013-04-04%20at%203.09.24%20PM.png) after two ccTouchesEnded that you have highlighted there are two ccTouchesBegan for two fingers. The first one has id=1 and the second has id=0 so it looks like you are receiving events for all touches correctly. Just do not rely on the ID to determine which ID was pressed first and everything should work fine. You should assume that ID can be a random value for each touch.

Leszek S wrote:

David in the screenshot that you have attached (http://www.cocos2d-x.org/attachments/1913/Screen%20Shot%202013-04-04%20at%203.09.24%20PM.png) after two ccTouchesEnded that you have highlighted there are two ccTouchesBegan for two fingers. The first one has id=1 and the second has id=0 so it looks like you are receiving events for all touches correctly. Just do not rely on the ID to determine which ID was pressed first and everything should work fine. You should assume that ID can be a random value for each touch.

So that leaves the question, how do you tell which touch was first and which was second?

David Small wrote:

Leszek S wrote:
> David in the screenshot that you have attached (http://www.cocos2d-x.org/attachments/1913/Screen%20Shot%202013-04-04%20at%203.09.24%20PM.png) after two ccTouchesEnded that you have highlighted there are two ccTouchesBegan for two fingers. The first one has id=1 and the second has id=0 so it looks like you are receiving events for all touches correctly. Just do not rely on the ID to determine which ID was pressed first and everything should work fine. You should assume that ID can be a random value for each touch.
>
So that leaves the question, how do you tell which touch was first and which was second?

You record the ID in your touchesbegan handler, store it and look for that ID in the moves and ends.

Say you had a class called Finger with an int for the ID and a CCPoint for the touch coordingates.

Following code is pseucode off the top of my head, untested and :

class Finger
{
   bool inUse;
   int touchID;
   CCPoint currentTouchPoint;
};

void HelloWorld::ccTouchesBegan(CCSet* touches, CCEvent* event)
{
    CCSetIterator it = touches->begin();

    // looking at all touches recieved
    for( int iTouchCount = 0; iTouchCount < touches->count(); iTouchCount++ )
    {
        CCTouch* touch = (CCTouch*)(*it);

        // Find a "m_finger" which has inUse set to false, then:
        int i=0;
        while( m_finger[i].inUse==true && i < 5 )
            i++;

        if( m_finger[i].inUse==false )
        {
            // We found a free slot to store this touch in
            m_finger[iFoundFinger].inUse = true;
            m_finger[iFoundFinger].touchID = touch->id();
            m_finger[iFoundFinger].currentTouchPoint = touch->getLocationInView();
        }

        it++;

    }
}

void HelloWorld::ccTouchesMoved(CCSet* touches, CCEvent* event)
{
    CCSetIterator it = touches->begin();

    // looking at all touches recieved
    for( int iTouchCount = 0; iTouchCount < touches->count(); iTouchCount++ )
    {
        CCTouch* touch = (CCTouch*)(*it);

        // See if the touchID of this touch matches any of our m_fingers (it should match one)
        // Find a "m_finger" which has inUse set to true and is the same ID, then:
        int i=0;
        for( int iFoundFinger=0; iFoundFinger < 5; iFoundFinger++ )
        {
            if( m_finger[iFoundFinger].inUse && m_finger[iFoundFinger].touchID == touch->id())
            {
                // This is the finger with ID that matches this touch ID, update its position
                m_finger[iFoundFinger].currentTouchPoint = touch->getLocationInView();
            }
            i++;
        }

        it++;
    }
}

void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
    CCSetIterator it = touches->begin();

    // looking at all touches recieved - find which finger has moved where
    for( int iTouchCount = 0; iTouchCount < touches->count(); iTouchCount++ )
    {
        CCTouch* touch = (CCTouch*)(*it);

        // See if the touchID of this touch matches any of our m_fingers (it should match one)
        // Find a "m_finger" which has inUse set to true and has the same ID, then:
        int i=0;
        for( int iFoundFinger=0; iFoundFinger < 5; iFoundFinger++ )
        {
            if( m_finger[iFoundFinger].inUse && m_finger[iFoundFinger].touchID == touch->id())
            {
                // This is the finger with ID that matches this touch ID, update its position
                m_finger[iFoundFinger].currentTouchPoint = touch->getLocationInView();
            }
            i++;
        }

        it++;
    }
}

P.S. In answer to your question about Arrow Mania android - nearly finished, I went and changed the main character (to a bow), taken longer than I thought and also means I now have to update the screenshots and titles and all promo material…. whoops! Oh well, should be out within 7 days.

Gav GMTDev wrote:

David Small wrote:
> Leszek S wrote:
> > David in the screenshot that you have attached (http://www.cocos2d-x.org/attachments/1913/Screen%20Shot%202013-04-04%20at%203.09.24%20PM.png) after two ccTouchesEnded that you have highlighted there are two ccTouchesBegan for two fingers. The first one has id=1 and the second has id=0 so it looks like you are receiving events for all touches correctly. Just do not rely on the ID to determine which ID was pressed first and everything should work fine. You should assume that ID can be a random value for each touch.
>
> So that leaves the question, how do you tell which touch was first and which was second?
>
You record the ID in your touchesbegan handler, store it and look for that ID in the moves and ends.
>
Say you had a class called Finger with an int for the ID and a CCPoint for the touch coordingates.
>
Following code is pseucode off the top of my head, untested and :
[…]
>
>
P.S. In answer to your question about Arrow Mania android - nearly finished, I went and changed the main character (to a bow), taken longer than I thought and also means I now have to update the screenshots and titles and all promo material…. whoops! Oh well, should be out within 7 days.

Wow, Thanks for the quick and extremely detailed reply!
but actually I fixed it with this little piece of code

currentTouch++;
if(touchPoint~~>getID != currentTouch-1)
touchPoint~~>setTouchInfo(currentTouch-1,touchPoint~~>getLocation.x,touchPoint~~>getLocationInView().y);

It forces the ID to be what I want it to be if necessary. I also added a simple currentTouch—; to the Touchended method.
It works perfectly now!
Thanks everyone for your help!