Category Archives: Proton SDK

Relating to my C++ mobile focused open source cross platform development framework

How to get rock solid multi-touch input finger tracking on iOS

So I’ve got this game prototype idea I wanted to try but I needed better multi-touch input support (accurate and comprehensive fingerID tracking) to make it happen.

The new test in RTSimpleApp: You can't see it in the shot, but each square has a fingerID # on it as well

It works great and has been added to the Proton SDK svn along with a new “Multitouch input test” option in RTSimpleApp.

Some stuff I noticed:

  • Tracks 11 fingers on an iPad
  • Tracks 4 fingers on an iPod Touch G1 (5 sort of.. but not reliably..)
  • Tracks 5 fingers on an iPhone4
  • Impossible to confuse it with fast movement, sliding off the screen or fast button mashing.  Solid!
  • Tracks 1.5 fingers on a Google Nexus One (It’s the HW’s fault.  Curious to see the results from a Tab or other new devices though)

For those interested, here is the relevant tracking code to get the “finger id”:  (yeah, I could have done it a more Obj-C way, but meh.. also, you may need your file named .mm, not .m for this code to work…)

[php]

const int MAX_TOUCHES= 11; //Oops, it can handle 11, not 10. Thanks @Bob_at_BH

class TouchTrack
{
public:

TouchTrack()
{
m_touchPointer = NULL;
}

void *m_touchPointer;
};

TouchTrack g_touchTracker[MAX_TOUCHES];

int GetFingerTrackIDByTouch(void* touch)
{
for (int i=0; i < MAX_TOUCHES; i++)
{
if (g_touchTracker[i].m_touchPointer == touch)
{
return i;
}
}

//LogMsg("Can’t locate fingerID by touch %d", touch);
return -1;
}

int AddNewTouch(void* touch)
{
for (int i=0; i < MAX_TOUCHES; i++)
{
if (!g_touchTracker[i].m_touchPointer)
{
//hey, an empty slot, yay
g_touchTracker[i].m_touchPointer = touch;
return i;
}
}

LogMsg("Can’t add new fingerID");
return -1;
}

int GetTouchesActive()
{
int count = 0;

for (int i=0; i < MAX_TOUCHES; i++)
{
if (g_touchTracker[i].m_touchPointer)
{
count++;
}
}
return count;
}

// Handles the start of a touch
– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// Enumerate through all the touch objects.

for (UITouch *touch in touches)
{
//found a touch. Is it already on our list?
int fingerID = GetFingerTrackIDByTouch(touch);

if (fingerID == -1)
{
//add it to our list
fingerID = AddNewTouch(touch);
} else
{
//already on the list. Don’t send this
//LogMsg("Ignoring touch %d", fingerID);
continue;
}

CGPoint pt =[touch locationInView:self];
ConvertCoordinatesIfRequired(pt.x, pt.y);
GetMessageManager()->SendGUIEx(MESSAGE_TYPE_GUI_CLICK_START,pt.x, pt.y,fingerID);
}

#ifdef _DEBUG
//LogMsg("%d touches active", GetTouchesActive());
#endif
}

– (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
// Enumerate through all the touch objects.
for (UITouch *touch in touches)
{
//found a touch. Is it already on our list?
int fingerID = GetFingerTrackIDByTouch(touch);
if (fingerID != -1)
{
g_touchTracker[fingerID].m_touchPointer = NULL; //clear it
} else
{
//wasn’t on our list
continue;
}

CGPoint pt =[touch locationInView:self];
ConvertCoordinatesIfRequired(pt.x, pt.y);
GetMessageManager()->SendGUIEx(MESSAGE_TYPE_GUI_CLICK_END,pt.x, pt.y, fingerID);
}
}

– (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
// Enumerate through all the touch objects.
for (UITouch *touch in touches)
{
//found a touch. Is it already on our list?
int fingerID = GetFingerTrackIDByTouch(touch);
if (fingerID != -1)
{
g_touchTracker[fingerID].m_touchPointer = NULL; //clear it
} else
{
//wasn’t on our list
continue;
}

CGPoint pt =[touch locationInView:self];
ConvertCoordinatesIfRequired(pt.x, pt.y);
GetMessageManager()->SendGUIEx(MESSAGE_TYPE_GUI_CLICK_END,pt.x, pt.y, fingerID);
}
}

– (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
// Enumerate through all the touch objects.
for (UITouch *touch in touches)
{

//found a touch. Is it already on our list?
int fingerID = GetFingerTrackIDByTouch(touch);
if (fingerID != -1)
{
//found it
} else
{
//wasn’t on our list?!
continue;
}

CGPoint pt =[touch locationInView:self];
ConvertCoordinatesIfRequired(pt.x, pt.y);
GetMessageManager()->SendGUIEx(MESSAGE_TYPE_GUI_CLICK_MOVE,pt.x, pt.y, fingerID);
}
}

[/php]

Looney Ladders for Win/OSX for the #ld48

Made a game over the weekend for LD.. it came out.. well, just ok.  Gameplay is sort of iffy, graphics are horrible, but it’s sort of cool how it builds random apartment buildings each level.

I plan to clean it up and place the source on the Proton svn (EDIT: It’s there now).  Also, at very low framerates the player doesn’t move right, I’d better fix that as well.

WindowsOSX

If anybody wants to donate time to redo the graphics so this Proton example can look less crappy, lemmie know and I can send them to you!

I did the music 30 minutes before the deadline so don’t expect much there either.. :)

Theme was Discovery.  I “discovered” how lame my art skills are

Proton SDK now supports Mac OS X as a target – just in time for LD

Yep, you can now compile a native OS X app of your p+ project!

This is a feature I’ve been wanting for a while because I:

  • Can release a proper native Dink HD for Mac – (will be free)
  • Can release things  to the new Mac App Store.. not Dink because of problems with in-game DMOD downloading and their submission rules, but other things.
  • Can create Mac versions of my ludumdare 48 entries to allow more people to play it.  Yeah, LD is almost here already and I hope to be able to participate.

It looked a bit too hacky to try to support OS X and iOS builds in the same xCode project so I did them separately – but because you can drag and drop project items between them it’s very quick to setup.

I’ve added OS X xCode projects in  the OSX subdir of RTSimpleApp and RTBareBones on svn.