<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mobile Perspectives &#187; multi-touch</title>
	<atom:link href="http://www.BluMtnWerx.com/blog/tag/multi-touch/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.BluMtnWerx.com/blog</link>
	<description>Computing at the Edge!</description>
	<lastBuildDate>Fri, 19 Aug 2011 00:29:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.4</generator>
		<item>
		<title>Taming Touch / Multi-Touch on the iPhone</title>
		<link>http://www.BluMtnWerx.com/blog/2009/06/taming-touch-multi-touch-on-the-iphone/</link>
		<comments>http://www.BluMtnWerx.com/blog/2009/06/taming-touch-multi-touch-on-the-iphone/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 06:14:25 +0000</pubDate>
		<dc:creator>deans</dc:creator>
				<category><![CDATA[Resources]]></category>
		<category><![CDATA[iPhone SDK]]></category>
		<category><![CDATA[multi-touch]]></category>
		<category><![CDATA[touch]]></category>

		<guid isPermaLink="false">http://www.BluMtnWerx.com/blog/?p=178</guid>
		<description><![CDATA[It seemed so simple at the time.&#160;  I wanted to manifest a different behavior when dragging the player sprite in iPuck with two fingers, instead of just one finger.&#160;  Not so fast, Skippy.&#160;  The solution is buried in the documentation, but most of the touch code samples that I've seen don't implement it.]]></description>
			<content:encoded><![CDATA[<p>Gameplay in <a href="http://www.blumtnwerx.com/iPuck.html" title="iPuck Product Page">iPuck</a> <em><a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=314153461&#038;mt=8" title="iPuck on the App Store">(App Store)</a></em>  is straightforward.&nbsp;  The player manipulates his/her sprite to knock the puck into the opponent’s goal, while guarding their own goal.&nbsp;  When I transitioned to <a href="http://wiki.slembcke.net/main/published/Chipmunk" title="Chipmunk 2D Physics Main Page">Chipmunk</a> for the 2D physics modeling, I had an opportunity to manifest two different behaviors as the player sprite is dragged.&nbsp;  &#8220;Great,&#8221; I thought, &#8220;I&#8217;ll have it behave one way when the player is dragging with one finger, and the other way when dragging with two fingers.&#8221;&nbsp;  Sounds good, right?</p>
<p>Unfortunately, it didn&#8217;t work.&nbsp;  I ended up writing a bunch of needlessly complex code that sort of emulated the behavior that I wanted.&nbsp;  I almost decided to abandon the functionality because I couldn&#8217;t get it to work reliably in all situations.&nbsp;  I knew that there had to be a better way to solve this problem.</p>
<p>Some of the challenges include:</p>
<ul>
<li>First, <span STYLE="font-family:Courier;">touchesBegan:withEvent:</span> gets called every time a finger touches the screen.&nbsp;  Thus, if the second finger touches just a tiny bit later than the first, <span STYLE="font-family:Courier;">touchesBegan:withEvent:</span> actually gets called with two separate single <span STYLE="font-family:Courier;">touchesBegan</span> events.&nbsp;  It&#8217;s easy enough to have a test to see whether the app is already processing a touch, but there are potential reliability issues with this because I have to guarantee that the touch state will always be cleaned up, or I might not be able recognize a legitimate <span STYLE="font-family:Courier;">touchesBegan:withEvent:</span> call.<br />
&nbsp;  </li>
<li>Second, when the set of touches is presented to <span STYLE="font-family:Courier;">touchesMoved:withEvent:</span>, a given set may contain a touch point from either finger, or both fingers.&nbsp;  If I get touches for both fingers, the order is predictable (first finger&#8217;s touch in element 0, second finger&#8217;s touch in element 1), within the scope of a single touch sequence (<em>down, move, up</em>).&nbsp;  However, if I only get one touch point, it could be from either finger, so I thought that my code had to try to sort out whether it could process the point, or not, by filtering for an &#8220;acceptable&#8221; delta (<em>I saw this technique in some sample code</em>).&nbsp;  I could use a heuristic technique to do this, but it&#8217;s really just a best guess.&nbsp;  Of course, this filtering can make for confusing gameplay, because the user thinks that they&#8217;re moving their the puck sprite, but if the &#8220;master&#8221; finger isn&#8217;t moving as fast as the &#8220;secondary&#8221; finger, the sprite may not behave as they are expecting.<br />
&nbsp;  </li>
<li>Finally, each time the player lifts either, or both, finger(s), <span STYLE="font-family:Courier;">touchesEnded:withEvent:</span> gets called, and I had to figure out which finger had actually lifted so that I could take the appropriate action.</li>
</ul>
<p>After stewing about the problem overnight, I dug into Apple&#8217;s documentation and found the answer.&nbsp;  Unfortunately, the code samples that I referenced when I wrote iPuck completely ignore this method.&nbsp;  In the discussion below, I&#8217;m focusing on two fingered multi-touches, because that&#8217;s the simplest scenario.&nbsp;  Everything that I say, however, extends completely to <em>n</em> finger touches.</p>
<p>Most of the sample code running around  handled single touches in a fashion something like this:</p>
<p><strong>NOTE:</strong>  <em>THIS ONLY WORKS RELIABLY IF YOUR VIEW DOES NOT HAVE MULTITOUCH ENABLED</em></p>
<p><span STYLE="font-family:Courier;background-color:#CCFFFF;font-size:x-small"><br />
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {<br />
&nbsp;  &nbsp;  // get the first touch<br />
&nbsp;  &nbsp;  UITouch *touch = [touches anyObject];<br />
&nbsp;  &nbsp;  if ([touch view] == myView) {<br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  CGPoint touchPt = [[touches anyObject] locationInView:myView];<br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  // do something with the point </span> &hellip; <span STYLE="font-family:Courier;background-color:#CCFFFF;font-size:x-small"><br />
&nbsp;  &nbsp;  }<br />
}</span><br />
<span STYLE="font-family:Courier;background-color:#CCFFFF;font-size:x-small"><br />
- (void)touchesMoved: (NSSet*)touches withEvent: (UIEvent*)event {<br />
&nbsp;  &nbsp;  // drag the sprite object along.<br />
&nbsp;  &nbsp;  CGPoint pt = [[touches anyObject] locationInView:myView];<br />
&nbsp;  &nbsp;  // do something with the new pt.<br />
}</span></p>
<p><span STYLE="font-family:Courier;background-color:#CCFFFF;font-size:x-small"><br />
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {<br />
&nbsp;  &nbsp;  // If the touch was in myView, handle it.<br />
&nbsp;  &nbsp;  UITouch *touch = [touches anyObject];<br />
&nbsp;  &nbsp;  if ([touch view] == myView) {<br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  // clean up<br />
&nbsp;  &nbsp;  }<br />
}</span></p>
<p><span STYLE="font-family:Courier;background-color:#CCFFFF;font-size:x-small"><br />
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {<br />
&nbsp;  &nbsp;  // If the touch was in the myView, handle it.<br />
&nbsp;  &nbsp;  UITouch *touch = [touches anyObject];<br />
&nbsp;  &nbsp;  if ([touch view] == myView) {<br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  // clean up<br />
&nbsp;  &nbsp;  }<br />
}</span></p>
<p>My first effort, as described above, was to simply convert the set of <span STYLE="font-family:Courier;">touches</span> into an array and try to figure out what I was getting.</p>
<p><strong>&hellip;</strong><span STYLE="font-family:Courier;background-color:#CCFFFF;font-size:x-small"><br />
&nbsp;  &nbsp;  NSArray *touchArr = [touches allObjects];<br />
&nbsp;  &nbsp;  NSInteger touchCnt = [touchArr count];<br />
&nbsp;  &nbsp;  UITouch *newTouch;<br />
&nbsp;  &nbsp;  CGPoint pt;<br />
&nbsp;  &nbsp;  if (touchCnt >= 1) {<br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  newTouch = [touchArr objectAtIndex:0];<br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  pt1 = [newTouch locationInView:myView];<br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  // do something with pt1<br />
&nbsp;  &nbsp;  }</span><br />
<strong>&hellip;</strong></p>
<p>Sadly, this didn&#8217;t work very well, so I went to Apple&#8217;s excellent documentation.&nbsp;  The answer to my problem is right there, in the <a href="http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UITouch_Class/Reference/Reference.html#//apple_ref/occ/cl/UITouch" title="UITouch Class Reference manual">UITouch Class Reference</a> document:</p>
<blockquote><p><em>A <span STYLE="font-family:Courier;">UITouch</span> object is persistent throughout a multi-touch sequence.</em></p></blockquote>
<p><strong>That&#8217;s it!</strong></p>
<p>I quickly changed my code to keep track of the specific <span STYLE="font-family:Courier;">UITouch</span> objects.&nbsp;  We can organize these touch objects in a number of ways, including static module variables, an array of <span STYLE="font-family:Courier;">UITouch*</span>&#8216;s or an <span STYLE="font-family:Courier;"><a href="http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSMutableDictionary_Class/Reference/Reference.html" title="NSMutableDictionary Class Reference">NSMutableDictionary</a></span> (<em>indexed by the touch objects&#8217; IDs</em>), depending on the specific requirement of the situation.</p>
<p>This allows me to do things like</p>
<p><strong>&hellip;</strong><br />
<span STYLE="font-family:Courier;background-color:#CCFFFF;font-size:x-small">static UITouch *g_firstTouch = nil;</span><br />
<strong>&hellip;</strong><br />
<span STYLE="font-family:Courier;background-color:#CCFFFF;font-size:x-small"><br />
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {<br />
&nbsp;  &nbsp;  // get the first touch<br />
&nbsp;  &nbsp;  NSArray *touchArr = [touches allObjects];<br />
&nbsp;  &nbsp;  NSInteger touchCnt = [touchArr count];<br />
&nbsp;  &nbsp;  UITouch *aTouch = [touchArr objectAtIndex:0];</span><br />
<strong>&hellip;</strong><br />
<span STYLE="font-family:Courier;background-color:#CCFFFF;font-size:x-small">&nbsp;  &nbsp;  &nbsp;  &nbsp;  if (([aTouch view] == myView) &#038;&#038; (g_firstTouch == nil)) {<br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  // keep track of the first touch object in the view.<br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  // this touch will represent this finger for the duration<br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  // of the sequence<br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  g_firstTouch = aTouch;<br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  // more stuff.</span><br />
<strong>&hellip;</strong> <em>code to loop through the touchArr doing other processing not shown</em> <strong>&hellip;</strong><br />
<span STYLE="font-family:Courier;background-color:#CCFFFF;font-size:x-small"><br />
- (void)touchesMoved: (NSSet*)touches withEvent: (UIEvent*)event {</span><br />
<strong>&hellip;</strong> <em>looping code not shown</em> <strong>&hellip;</strong><span STYLE="font-family:Courier;background-color:#CCFFFF;font-size:x-small"><br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  if (aTouch == g_firstTouch) {<br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  //do something apppropriate</span><br />
&hellip;<strong>or</strong>&hellip;<span STYLE="font-family:Courier;background-color:#CCFFFF;font-size:x-small"><br />
&nbsp;  &nbsp;  if (firstTouchNotInSet) {<br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  // the touchesMoved method was called, but our first touch<br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  // wasn&#8217;t in the set, use its current data<br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  CGPoint pt1 = [g_firstTouch locationInView:myView];<br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  // do something with pt1</span><br />
<strong>&hellip;</strong><br />
<span STYLE="font-family:Courier;background-color:#CCFFFF;font-size:x-small"><br />
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {</span><br />
<strong>&hellip;</strong> <em>looping code not shown</em> <strong>&hellip;</strong><span STYLE="font-family:Courier;background-color:#CCFFFF;font-size:x-small"><br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  if (aTouch == g_firstTouch) {<br />
&nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  // the first touch is over, do something appropriate.</span><br />
<strong>&hellip;</strong></p>
<p>&nbsp;<br />
<strong>Notes:</strong></p>
<ul>
<li>I extracted this code from our apps, and tried to make it generic to illustrate the points.&nbsp;  I didn&#8217;t recompile/retest the extracted code, so I may have botched the process a little bit &#8211; apologies in advance</li>
<li>Don&#8217;t forget that you have to enable multi-touch, it&#8217;s disabled by default.&nbsp;  You&#8217;ll need to set the multipleTouchEnabled property:&nbsp;  <span STYLE="font-family:Courier;background-color:#CCFFFF;font-size:x-small">[myView  setMultipleTouchEnabled:Yes];</span></li>
<li>The <span STYLE="font-family:Courier;">timestamp</span> property of <span STYLE="font-family:Courier;">UIEvent</span> can provide another way to organize your app&#8217;s events</li>
<li>For sprite movement, I typically have to apply deltas to the previous sprite location, I&#8217;ve always kept track of the previous touch point within my touchesMoved:withEvent method.&nbsp;  It turns out that this isn&#8217;t strictly necessary, as <span STYLE="font-family:Courier;">UITouch</span> has the<br />
<span STYLE="font-family:Courier;background-color:#CCFFFF;font-size:x-small">- (CGPoint)previousLocationInView:(UIView *)view</span><br />
method, which provides the exact same functionality &#8211; I haven&#8217;t verified the performance impact, but it could simplify your code.</li>
<li>After all of this, I decided that I didn&#8217;t like two-finger dragging for controlling the player sprite.  Multi-touch is great for swipes and gestures, but it doesn&#8217;t seem to lend itself to the quick movements and rapid direction changes needed to play the game, so I came up with a completely different interface implementation for v1.1 of iPuck.
</li>
</ul>
<p>&nbsp;<br />
<strong>Bottom Line:</strong></p>
<p>We can take advantage of the fact that each specific <span STYLE="font-family:Courier;">UITouch</span> object spans the duration of a down / drag / up operation to unambiguously identify each touch and track it from <span STYLE="font-family:Courier;">touchesBegan:</span> through <span STYLE="font-family:Courier;">touchesMoved:</span> and take appropriate action at <span STYLE="font-family:Courier;">touchesEnded:</span>.&nbsp;  This allows us to reliably track the movement of each individual finger through the touch sequence and to respond appropriately to calls when not all of the fingers are represented in the touch set.</p>
<p>&nbsp;<br />
&#8212;&#8212;&#8211;<br />
Technorati Tags:&nbsp; <a href="http://technorati.com/tag/iPhone" rel="tag">iPhone</a>, <a href="http://technorati.com/tag/iPod+Touch" rel="tag">iPod Touch</a>, <a href="http://technorati.com/tag/Apple" rel="tag">Apple</a>, <a href="http://technorati.com/tag/mobile" rel="tag">mobile</a>, <a href="http://technorati.com/tag/multi-touch" rel="tag">multi-touch</a>, <a href="http://technorati.com/tag/iPuck" rel="tag">iPuck</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.BluMtnWerx.com/blog/2009/06/taming-touch-multi-touch-on-the-iphone/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

