<?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>Mystery Coconut. Resident Alien</title>
	<atom:link href="http://mysterycoconut.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://mysterycoconut.com</link>
	<description>Where Game Development Hits the Fruit Stand</description>
	<lastBuildDate>Thu, 01 Dec 2011 01:48:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Parallax Scrolling (Core Animation Games 4)</title>
		<link>http://mysterycoconut.com/blog/2011/09/cag4/</link>
		<comments>http://mysterycoconut.com/blog/2011/09/cag4/#comments</comments>
		<pubDate>Wed, 21 Sep 2011 22:45:27 +0000</pubDate>
		<dc:creator>Miguel A. Friginal</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Core Animation Games]]></category>
		<category><![CDATA[idevblogaday]]></category>

		<guid isPermaLink="false">http://mysterycoconut.com/?p=1048</guid>
		<description><![CDATA[Parallax scrolling is the protagonist in a new episode of the Core Animation Games series. I know, you are not that interested into Core Animation… what about some general performance tips then? And did I say I also got flying cupcakes already?]]></description>
			<content:encoded><![CDATA[<p>It has been quite a while since I wrote the last article in the Core Animation Games series. If you remember, in it I complained bitterly about the CA scrolling classes, and how none of them filled the ticket. To recapitulate, these are the 3 things I needed:</p>
<ol>
<li>A window into a coordinate system plane populated by &#8220;objects&#8221;…</li>
<li>that smoothly moves through it by remapping how its borders map to that underlying plane…</li>
<li>and loads the objects to be displayed as they are needed, while keeping memory requirements in check.</li>
</ol>
<p>So let’s explain how to do that with Core Animation, and as a bonus we will do <a href="http://en.wikipedia.org/wiki/Parallax_scrolling">parallax scrolling</a>, talk about some graphic optimizations, and show you flying cupcakes.</p>
<p><span id="more-1048"></span><br />
<h3>Recycling</h3>
<p>Point 3 above requires some explanation. The last thing you want to do in the middle of your game loop is allocate memory, since it will totally kill performance. We also need to use the minimum amount of memory possible, since iOS devices don’t have much. To do just that we initialize the tiles that make up our background at the beginning of the game. We will use a separate CALayer for each tile and put them in an array. How many do you need?</p>
<p class='imgCenter'><img src='http://mysterycoconut.com/wp-content/uploads/2011/09/ScrollingTiles.gif' alt='' border='0' width='422' height='382' />Example of scrolling to the right.</p>
<p>In this image the red line is the view in the screen, slowly moving over a grid of tiles making up the world (grey lines). Only the blue and green tiles are in memory at any time though. We used as many as needed to cover the whole screen, plus a 1-tile wide border around the whole thing so we always have tiles under our view during the scroll (depending on the scrolling speed you may need more than 1).</p>
<p>When the view scrolls to a point where it needs to show more tiles to continue, the farthest tiles (in green) are moved to the required new position, and their contents recalculated by looking up in the world map what graphic tile goes with that position (or similar). If you have ever used <code>UITableView</code>s and <code>dequeueReusableCellWithIdentifier:</code>, is the same concept but in two dimensions instead of just one.</p>
<h3>No <i>Core</i> Animation</h3>
<p>If our game was an infinite scroller, say something like Jetpack Joyride, we could use Core Animation to create a <code>CABasicAnimation</code> at the beginning of the game, set a speed, and let it run indefinitely. The problem is that, <a href='/blog/2011/02/cag3/'>as I explained in the latest article</a>, getting notifications when the tiles need to be refreshed is not easy. But usually you will need more control over the scrolling anyway, modifying its direction or speed according to user interaction, events during play like the player dying or being stuck on an obstacle, difficulty increasing with time, etc. What we need is a more traditional game loop, in which at every frame we can modify the view position in the world.</p>
<div class="scgeshi-container"><div class="objc scgeshi"><span class="sy0">-</span> <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>play;<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>displayLink <span class="sy0">==</span> <span class="kw2">nil</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; displayLink <span class="sy0">=</span> <span class="br0">&#91;</span>CADisplayLink displayLinkWithTarget<span class="sy0">:</span>self selector<span class="sy0">:</span><span class="kw1">@selector</span><span class="br0">&#40;</span>update<span class="sy0">:</span><span class="br0">&#41;</span><span class="br0">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span class="br0">&#91;</span>displayLink addToRunLoop<span class="sy0">:</span><span class="br0">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSRunLoop_Class/"><span class="kw5">NSRunLoop</span></a> currentRunLoop<span class="br0">&#93;</span> forMode<span class="sy0">:</span>NSDefaultRunLoopMode<span class="br0">&#93;</span>;<br />
<span class="br0">&#125;</span><br />
<br />
<span class="sy0">-</span> <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>update<span class="sy0">:</span><span class="br0">&#40;</span>CADisplayLink<span class="sy0">*</span><span class="br0">&#41;</span>sender;<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">static</span> <span class="kw4">const</span> CFTimeInterval maxElapsedTime <span class="sy0">=</span> <span class="nu0">1</span> <span class="sy0">/</span> 20.0f;<br />
&nbsp; &nbsp; <span class="kw4">static</span> CFTimeInterval lastTimestamp <span class="sy0">=</span> <span class="nu0">0</span>;<br />
<br />
&nbsp; &nbsp; <span class="kw4">const</span> CFTimeInterval currentTime <span class="sy0">=</span> CACurrentMediaTime<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; CFTimeInterval elapsedTime <span class="sy0">=</span> currentTime <span class="sy0">-</span> lastTimestamp;<br />
&nbsp; &nbsp; lastTimestamp <span class="sy0">=</span> currentTime;<br />
<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>elapsedTime &gt; maxElapsedTime<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; elapsedTime <span class="sy0">=</span> maxElapsedTime;<br />
<br />
&nbsp; &nbsp; <span class="br0">&#91;</span>CATransaction begin<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#91;</span>CATransaction setDisableActions<span class="sy0">:</span><span class="kw2">YES</span><span class="br0">&#93;</span>;<br />
<br />
&nbsp; &nbsp; <span class="co2">// Use elapsedTime to update stuff here, calculate how much we need </span><br />
&nbsp; &nbsp; <span class="co2">// to scroll, update tiles, etc.</span><br />
<br />
&nbsp; &nbsp; <span class="br0">&#91;</span>CATransaction commit<span class="br0">&#93;</span>;<br />
<span class="br0">&#125;</span></div></div>
<p>That’s a basic <code>CADisplayLink</code> loop, except for the <code>CATransaction</code> part. Since we don’t want any of <a href='2011/01/cag1/#implicit'>those pesky implicit animations</a> when we change the properties of the <code>CALayer</code>s, we wrap everything into a transaction and disable them. This has two side-effects though.</p>
<p>First the positive one. When we need to read the current state of a layer, say its position, we usually do the following to get what’s on the screen (instead of what an animation started or will end with):</p>
<div class="scgeshi-container"><div class="objc scgeshi"><span class="co2">// tile is a CALayer</span><br />
CGPoint currentPos <span class="sy0">=</span> <span class="br0">&#91;</span><span class="br0">&#91;</span>tile presentationLayer<span class="br0">&#93;</span> position<span class="br0">&#93;</span>;</div></div>
<p>However, since we are skipping animations the changes to properties are way faster, so after the transaction is committed we will have the same value in the layer properties than what we see on the screen. Ergo, we can do this instead.</p>
<div class="scgeshi-container"><div class="objc scgeshi">CGPoint currentPos <span class="sy0">=</span> tile.position;</div></div>
<p>Why is this any good? Every time you call <code>presentationLayer</code> a <b>new copy of the layer is created</b>. Every time you call that method, a new object is allocated<small><sup>1</sup></small> and returned. And as we said before, allocating memory mid-loop is a Very Bad Thing™. That’s why in other cases, when you really need to use the presentation layer, it is probably better you do this…</p>
<div class="scgeshi-container"><div class="objc scgeshi">CALayer <span class="sy0">*</span>currentTile &nbsp; <span class="sy0">=</span> <span class="br0">&#40;</span>CALayer<span class="sy0">*</span><span class="br0">&#41;</span><span class="br0">&#91;</span>tile presentationLayer<span class="br0">&#93;</span>;<br />
CGRect theBoundsRect &nbsp; <span class="sy0">=</span> currentTile.bounds;<br />
CGRect theContentsRect <span class="sy0">=</span> currentTile.contentsRect;</div></div>
<p>rather than this:</p>
<div class="scgeshi-container"><div class="objc scgeshi">CGRect theBoundsRect &nbsp; <span class="sy0">=</span> <span class="br0">&#91;</span><span class="br0">&#91;</span>tile presentationLayer<span class="br0">&#93;</span> bounds<span class="br0">&#93;</span>;<br />
CGRect theContentsRect <span class="sy0">=</span> <span class="br0">&#91;</span><span class="br0">&#91;</span>tile presentationLayer<span class="br0">&#93;</span> contentsRect<span class="br0">&#93;</span>;</div></div>
<p>The second side-effect is not that good. When Core Animation is in charge it runs its calculations and updates properties on a different thread, then it shows the results on the screen at the next screen refresh. This, unless you run lots of simultaneous animations or other calculations, gives you a smooth 60 Hz refresh rate. But by making changes to layer properties by hand we are basically bypassing all that. The <code>CADisplayLayer</code> will call your code at a multiple of the refresh rate on the main thread (again, unless you are limited by other calculations). Then you will update the properties of the layers, but is not until the <code>[CATransaction commit]</code> that those numbers actually change in the presentation layer or the private render-tree. The next time around the runloop, whenever that happens, the new values should be visible, but they still may need to wait for the screen to refresh. When before we had a smooth 60Hz animation now we are limited by the <code>CADisplayLink</code>’s <code>frameInterval</code>, and by whatever else we are doing on the main thread. Performance is going to suffer because we are fighting, rather than using, Core Animation. Why use Core Animation at all then? I guess I will have to talk about that in the next article in the series.</p>
<h3>Apple Land of Flying Cupcakes</h3>
<p>Now that we know what we are doing, why we are doing it, and what are the consequences, let‘s jump into some sample code. We are going to be modeling the following:</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/09/Parallax.jpg" alt="" border="0" width="480" height="320" />Don’t know what I had for breakfast the day I drew this :/</p>
<p>We have, from front to back:</p>
<ol>
<li>A floor of dirt with grass.</li>
<li>Some yellow blocks, in a repeating pattern for the example.</li>
<li>Some kind of robot head.</li>
<li>Apple-shaped hills.</li>
<li>Clouds.</li>
<li>A flying cupcake.</li>
<li>And the sky.</li>
</ol>
<p>Of all those only the apples, blocks, and grass are going to be separate tiled layers moving at different speeds. The sky is just a fixed background, and since they are more like individual elements, we will deal with the clouds, cupcake, and robot head later.</p>
<p>We are going to create a <code>CALayer</code> subclass to take care of all our tiling needs. You can check the <code>MCParallaxLayer</code> class in the sample code at the end of the article. As part of its initialization we pass the size (in points) of the tiles (they need to be all the same size). Then we can calculate how many tiles we need like this:</p>
<div class="scgeshi-container"><div class="objc scgeshi"><span class="co2">// tileSize is the size of one tile in points</span><br />
tilesWide <span class="sy0">=</span> ceilf<span class="br0">&#40;</span>self.bounds.size.width <span class="sy0">/</span> tileSize.width<span class="br0">&#41;</span> <span class="sy0">+</span> <span class="nu0">2</span>;<br />
tilesHigh <span class="sy0">=</span> ceilf<span class="br0">&#40;</span>self.bounds.size.height <span class="sy0">/</span> tileSize.height<span class="br0">&#41;</span>;<br />
<br />
<span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>horizontal<span class="br0">&#41;</span> <br />
&nbsp; &nbsp; tilesHigh <span class="sy0">+=</span> <span class="nu0">2</span>;<br />
<br />
numTiles <span class="sy0">=</span> tilesWide <span class="sy0">*</span> tilesHigh;<br />
<br />
tiles <span class="sy0">=</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/calloc.html"><span class="kw3">calloc</span></a><span class="br0">&#40;</span><a href="http://www.opengroup.org/onlinepubs/009695399/functions/sizeof.html"><span class="kw3">sizeof</span></a><span class="br0">&#40;</span>CALayer<span class="sy0">*</span><span class="br0">&#41;</span>, numTiles<span class="br0">&#41;</span>;</div></div>
<p>So each tile (the ones in memory, the blue ones in the diagram), is a separate <code>CALayer</code> that we save in an array. We need enough tiles to cover the whole <code>bounds</code> of our <code>MCParallaxLayer</code> plus one more at each side. If we make this layer the size of our view, we would be covering the whole thing (what you will do for the terrain of an RPG, for example). But if we make it smaller that our view we can restrict the drawing area and save some memory. For example, instead of needing this many tiles for our yellow blocks…</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/09/BlocksGrid1.jpg" alt="" border="0" width="480" height="320" /></p>
<p>…we only need this many doing it this way. Notice how, since we are never going to scroll vertically (<code>horizontal == YES</code>), we are not creating extra rows of tiles on top and bottom.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/09/BlocksGrid2.jpg" alt="" border="0" width="480" height="320" /></p>
<p>Once we have allocated memory for our array of tiles we need to initialize them:</p>
<div class="scgeshi-container"><div class="objc scgeshi"><span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i<span class="sy0">=</span><span class="nu0">0</span>; i&lt;numTiles; <span class="sy0">++</span>i<span class="br0">&#41;</span> <br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; tiles<span class="br0">&#91;</span>i<span class="br0">&#93;</span> <span class="sy0">=</span> <span class="br0">&#91;</span><span class="br0">&#91;</span>CALayer layer<span class="br0">&#93;</span> retain<span class="br0">&#93;</span>;<br />
<br />
&nbsp; &nbsp; tiles<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.anchorPoint <span class="sy0">=</span> CGPointZero;<br />
&nbsp; &nbsp; tiles<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.bounds <span class="sy0">=</span> CGRectMake<span class="br0">&#40;</span><span class="nu0">0</span>, <span class="nu0">0</span>, tileSize.width, tileSize.height<span class="br0">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span class="co2">// img is a CGImageRef to our atlas</span><br />
&nbsp; &nbsp; tiles<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.contents <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">id</span><span class="br0">&#41;</span>img;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="br0">&#91;</span>self addSublayer<span class="sy0">:</span>tiles<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#93;</span>;<br />
<span class="br0">&#125;</span></div></div>
<p>We just allocate and initialize some <code>CALayers</code>, set their size, the anchor point to make them easier to position, and assign the image atlas. Then we add them as a child of our <code>MCParallaxLayer</code>. Notice there are two things missing there: we are not setting the correct <code>position</code> of each tile, and we are not setting the <code>contentsRect</code> (that would identify <a href='/blog/2011/01/cag1/#atlas'>what part of the atlas to show</a>).</p>
<h3>Scrolling and Blurry Pixels</h3>
<p>There are a couple things I added to <code>MCParallaxLayer</code> to make things a bit easier. The first one is the <code>TileCoords</code> type, to measure position in tiles (integers) instead of points (floats). A couple methods convert between CGPoints and TileCoords and back using the <code>tileSize</code>.</p>
<div class="scgeshi-container"><div class="objc scgeshi"><span class="kw4">typedef</span> <span class="kw4">struct</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">int</span> x;<br />
&nbsp; &nbsp; <span class="kw4">int</span> y;<br />
<span class="br0">&#125;</span> TileCoords;<br />
<br />
<span class="sy0">-</span> <span class="br0">&#40;</span>CGPoint<span class="br0">&#41;</span>tileCoordsToPoint<span class="sy0">:</span><span class="br0">&#40;</span>TileCoords<span class="br0">&#41;</span>coords;<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> CGPointMake<span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span>coords.x <span class="sy0">*</span> tileSize.width, <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span>coords.y <span class="sy0">*</span> tileSize.height<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
<br />
<br />
<span class="sy0">-</span> <span class="br0">&#40;</span>TileCoords<span class="br0">&#41;</span>pointToTileCoords<span class="sy0">:</span><span class="br0">&#40;</span>CGPoint<span class="br0">&#41;</span>pt;<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>TileCoords<span class="br0">&#41;</span><span class="br0">&#123;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>floorf<span class="br0">&#40;</span>0.5f <span class="sy0">+</span> pt.x<span class="sy0">/</span>tileSize.width<span class="br0">&#41;</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>floorf<span class="br0">&#40;</span>0.5f <span class="sy0">+</span> pt.y<span class="sy0">/</span>tileSize.height<span class="br0">&#41;</span> <span class="br0">&#125;</span>;<br />
<span class="br0">&#125;</span></div></div>
<p>The second is a <i>provider</i>, that works as kind of a delegate supplying what section of the atlas to draw for a specific tile coordinate. Usually it will be an object that has access to the level’s layout, and can answer questions like <i>‘what do I draw in tile (13, 24)?’</i>. In our sample code, we are just using the view controller as the provider for all our layers.</p>
<div class="scgeshi-container"><div class="objc scgeshi"><span class="kw1">@protocol</span> MCParallaxLayerContentProvider &lt;NSObject&gt;<br />
<br />
<span class="sy0">-</span> <span class="br0">&#40;</span>CGImageRef<span class="br0">&#41;</span>atlasFor<span class="sy0">:</span><span class="br0">&#40;</span>MCParallaxLayer<span class="sy0">*</span><span class="br0">&#41;</span>sender;<br />
<span class="sy0">-</span> <span class="br0">&#40;</span>CGRect<span class="br0">&#41;</span>tileAt<span class="sy0">:</span><span class="br0">&#40;</span>TileCoords<span class="br0">&#41;</span>pos <span class="kw1">for</span><span class="sy0">:</span><span class="br0">&#40;</span>MCParallaxLayer<span class="sy0">*</span><span class="br0">&#41;</span>sender;<br />
<br />
<span class="kw1">@end</span></div></div>
<p>So with that said, this is how we calculate the <code>position</code> and <code>contentsRect</code> of the initial tiles.</p>
<div class="scgeshi-container"><div class="objc scgeshi">prevOriginTileCoords <span class="sy0">=</span> <span class="br0">&#91;</span>self pointToTileCoords<span class="sy0">:</span>self.bounds.origin<span class="br0">&#93;</span>;<br />
prevOriginTileCoords.x <span class="sy0">-=</span> <span class="nu0">1</span>;<br />
<span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>horizontal<span class="br0">&#41;</span><br />
&nbsp; &nbsp; prevOriginTileCoords.y <span class="sy0">-=</span> <span class="nu0">1</span>; &nbsp; &nbsp; &nbsp; &nbsp;<br />
<br />
<span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span>; i &lt; numTiles; <span class="sy0">++</span>i<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">const</span> TileCoords coords <span class="sy0">=</span> <span class="br0">&#40;</span>TileCoords<span class="br0">&#41;</span><span class="br0">&#123;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; prevOriginTileCoords.x <span class="sy0">+</span> i <span class="sy0">%</span> tilesWide, <br />
&nbsp; &nbsp; &nbsp; &nbsp; prevOriginTileCoords.y <span class="sy0">+</span> i <span class="sy0">/</span> tilesWide <span class="br0">&#125;</span>;<br />
<br />
&nbsp; &nbsp; tiles<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.position <span class="sy0">=</span> <span class="br0">&#91;</span>self tileCoordsToPoint<span class="sy0">:</span>coords<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; tiles<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.contentsRect <span class="sy0">=</span> <span class="br0">&#91;</span>provider tileAt<span class="sy0">:</span>coords <span class="kw1">for</span><span class="sy0">:</span>self<span class="br0">&#93;</span>;<br />
<span class="br0">&#125;</span></div></div>
<p>How do we scroll then? The same way <code>CAScrollLayer</code> does, by changing the bounds of the <code>MCParallaxLayer</code>. We have to do it carefully though.</p>
<div class="scgeshi-container"><div class="objc scgeshi"><span class="sy0">-</span> <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>scrollTiles<span class="sy0">:</span><span class="br0">&#40;</span>CGPoint<span class="br0">&#41;</span>diff;<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="co2">//scrollLeftover is an CGPoint ivar</span><br />
&nbsp; &nbsp; scrollLeftover.x <span class="sy0">+=</span> diff.x;<br />
&nbsp; &nbsp; scrollLeftover.y <span class="sy0">+=</span> diff.y;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; CGRect currentBounds <span class="sy0">=</span> self.bounds;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; self.bounds <span class="sy0">=</span> CGRectMake<span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; floorf<span class="br0">&#40;</span>currentBounds.origin.x <span class="sy0">+</span> scrollLeftover.x<span class="br0">&#41;</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; floorf<span class="br0">&#40;</span>currentBounds.origin.y <span class="sy0">+</span> &nbsp;scrollLeftover.y<span class="br0">&#41;</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; currentBounds.size.width, <br />
&nbsp; &nbsp; &nbsp; &nbsp; currentBounds.size.height<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; scrollLeftover.x <span class="sy0">-=</span> floorf<span class="br0">&#40;</span>scrollLeftover.x<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; scrollLeftover.y <span class="sy0">-=</span> floorf<span class="br0">&#40;</span>scrollLeftover.y<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></div></div>
<p>What&#8217;s with all thosee <code>floorf()</code> and <code>scrollLeftover</code>s? The thing is if we just add any decimal amount to the bounds position, the tiles will not be rendered aligned to pixels. They will be antialiased, and performance will suffer (there is a reason the Core Animation Instrument has an option to warn you about ‘Misaligned Images’). So the <code>floorf()</code> helps with that. But what happens if, for example, we scroll 0.6 points every frame. If we don’t keep track of the remainder we will be scrolling 0 pixels every frame! So that’s why we do, so 2 frames moving 0.6 actually scrolls 1 point.</p>
<p>You may have noticed that I keep talking about points, not pixels. This method could actually be improved to take into account double resolution devices like the iPhone 4, since those would actually accept scrolling in half points (half a point * 2 point per pixel = 1 pixel). The truth is those are some really small pixels and, at least for me, the difference is minimal.</p>
<h3>Recycling Implemented</h3>
<p>This is already running really long, so let’s get to the meat of the scrolling, the implementation of the recycling method shown in the first figure. Almost the most important question is, where do we implement this? What gets called every time we change the layer’s <code>bounds</code> even when <code>needsDisplayOnBoundsChange</code> is <code>NO</code>? Since we have all our tiles as sublayers, <code>layoutSublayers</code> does.</p>
<div class="scgeshi-container"><div class="objc scgeshi"><span class="sy0">-</span> <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>layoutSublayers;<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">const</span> TileCoords pos <span class="sy0">=</span> <span class="br0">&#91;</span>self pointToTileCoords<span class="sy0">:</span>self.bounds.origin<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; TileCoords topLeftTile <span class="sy0">=</span> <span class="br0">&#123;</span> pos.x <span class="sy0">-</span> <span class="nu0">1</span>, pos.y <span class="sy0">-</span> <span class="nu0">1</span> <span class="br0">&#125;</span>;<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>horizontal<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; topLeftTile.y <span class="sy0">=</span> pos.y;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="co2">// 1 = new col to the right; 0 = no change; -1 = new col to the left</span><br />
&nbsp; &nbsp; <span class="kw4">int</span> xDir <span class="sy0">=</span> topLeftTile.x <span class="sy0">-</span> prevOriginTileCoords.x; <br />
&nbsp; &nbsp; <span class="co2">// 1 = new row at bottom; 0 = no change; -1 = new row at top</span><br />
&nbsp; &nbsp; <span class="kw4">int</span> yDir <span class="sy0">=</span> topLeftTile.y <span class="sy0">-</span> prevOriginTileCoords.y; <br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; NSAssert<span class="br0">&#40;</span>xDir &lt;<span class="sy0">=</span> <span class="nu0">1</span> <span class="sy0">&amp;&amp;</span> xDir &gt;<span class="sy0">=</span> <span class="sy0">-</span><span class="nu0">1</span> <span class="sy0">&amp;&amp;</span> yDir &lt;<span class="sy0">=</span> <span class="nu0">1</span> <span class="sy0">&amp;&amp;</span> yDir &gt;<span class="sy0">=</span> <span class="sy0">-</span><span class="nu0">1</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co3">@</span><span class="st0">&quot;Scrolling too fast&quot;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>xDir <span class="sy0">==</span> <span class="nu0">0</span> <span class="sy0">&amp;&amp;</span> yDir <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; prevOriginTileCoords <span class="sy0">=</span> topLeftTile;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw4">int</span> affectedColumn, affectedRow;<br />
&nbsp; &nbsp; <span class="kw4">float</span> xDiff, yDiff;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; xDiff <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span>xDir <span class="sy0">*</span> tilesWide <span class="sy0">*</span> tileSize.width;<br />
&nbsp; &nbsp; affectedColumn <span class="sy0">=</span> <span class="br0">&#40;</span>xDir <span class="sy0">==</span> <span class="nu0">1</span><span class="br0">&#41;</span> ? <br />
&nbsp; &nbsp; &nbsp; &nbsp; topLeftTile.x <span class="sy0">-</span> <span class="nu0">1</span> <span class="sy0">:</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; topLeftTile.x <span class="sy0">+</span> tilesWide;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; yDiff <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span>yDir <span class="sy0">*</span> tilesHigh <span class="sy0">*</span> tileSize.height;<br />
&nbsp; &nbsp; affectedRow <span class="sy0">=</span> <span class="br0">&#40;</span>yDir <span class="sy0">==</span> <span class="nu0">1</span><span class="br0">&#41;</span> ? <br />
&nbsp; &nbsp; &nbsp; &nbsp; topLeftTile.y <span class="sy0">-</span> <span class="nu0">1</span> <span class="sy0">:</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; topLeftTile.y <span class="sy0">+</span> tilesHigh;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; TileCoords tilePos;<br />
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span>; i &lt; numTiles; <span class="sy0">++</span>i<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">BOOL</span> changed <span class="sy0">=</span> <span class="kw2">NO</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; tilePos <span class="sy0">=</span> <span class="br0">&#91;</span>self pointToTileCoords<span class="sy0">:</span>tiles<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.position<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>xDir <span class="sy0">&amp;&amp;</span> tilePos.x <span class="sy0">==</span> affectedColumn<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tiles<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.position <span class="sy0">=</span> CGPointMake<span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tiles<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.position.x <span class="sy0">+</span> xDiff, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tiles<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.position.y<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; changed <span class="sy0">=</span> <span class="kw2">YES</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>yDir <span class="sy0">&amp;&amp;</span> tilePos.y <span class="sy0">==</span> affectedRow<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tiles<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.position <span class="sy0">=</span> CGPointMake<span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tiles<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.position.x, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tiles<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.position.y <span class="sy0">+</span> yDiff<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; changed <span class="sy0">=</span> <span class="kw2">YES</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>changed<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tiles<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.contentsRect <span class="sy0">=</span> <span class="br0">&#91;</span>provider tileAt<span class="sy0">:</span>tilePos <span class="kw1">for</span><span class="sy0">:</span>self<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div></div>
<p>The code is pretty self explanatory. We figure out what are the tile coordinates of our most upper left tile by checking the <code>bounds origin</code> and if we are only scrolling horizontally. Then we compare it with the previous value, that we had stored in the <code>prevOriginTileCoords</code> ivar. If the coordinates are the same, we don&#8217;t need to recycle anything yet, so we return.</p>
<p>If the coordinates are not the same, we find what row and/or column is going to be recycled. Then we loop through all our tiles (since at this point they can be in the array in any order), and we move each one that matches an affected column and/or row to the other side of grid; horizontally for matching columns, vertically for matching rows. Then we ask our provider for the new section of our atlas (<code>contentsRect</code>) for the new tile coordinate. That’s it. Tiled layer with infinite scrolling without spending extra memory.</p>
<h3>Odds and Ends</h3>
<p>So what do we need to extend this and make it into a parallax scrolling example? Not much. Basically we can create multiple <code>MCParallaxLayer</code>s with different tile sizes and images, add them all to the same view, and then scroll them at different speeds. To make things easier, I just added a <code>multiplier</code> ivar to use in the first lines of the <code>scrollTiles:</code> method.</p>
<div class="scgeshi-container"><div class="objc scgeshi">scrollLeftover.x <span class="sy0">+=</span> diff.x <span class="sy0">*</span> scrollMultiplier;<br />
scrollLeftover.y <span class="sy0">+=</span> diff.y <span class="sy0">*</span> scrollMultiplier;</div></div>
<p>So what about the clouds, and the rest? The three clouds are not the same size, and there is lots of blank space in-between, so they don’t really fit our <code>MCParallaxLayer</code>. The thing is our class is still a normal <code>CALayer</code>, so we can add individual sublayers to them and they will scroll along with the rest when we change its bounds. Check the sample code to see how we use that for the clouds, the robot head, and the flying cupcake.</p>
<h3>Opaque or not Opaque</h3>
<p>The moment you start to pile layers one on top of another, performance is going to take a hit, specially so if they have transparent or translucent pixels that need to be combined. That’s why <code>UIView</code>s and <code>CALayer</code>s have the <code>opaque</code> property, so you can signal UIKit that it is OK to forget about what’s underneath, because you are covering that whole section of the screen.</p>
<p>What I didn’t knew though, is that <b>the <code>opaque</code> property is completely ignored if the image being rendered has an alpha channel</b> (like, you know, if you have that <i>Transparency</i> checkbox checked when exporting PNGs from Photoshop), even if all the pixels inside the layer are actually solid. That’s the reason the sample code uses two different atlases, one with an alpha channel for clouds, the robot head or the grass, the other one without for the sky or the apples. This improves performance a tad, so remember to use solid images whenever possible.</p>
<div class="sampleCode">
<h3>Parallax Scrolling with Core Animation</h3>
<p><img class="alignleft" src="http://mysterycoconut.com/wp-content/uploads/2011/09/ThumbCode.jpg" border="0" alt="" width="190" height="290"> As always the code is not a drag and drop black box to use as is, but for you to check out and play with.</p>
<p>Have fun experimenting!</p>
<p class="download"><a href="/examplecode/Parallax.zip">Download Parallax project</a></p>
</div>
<p class='footnote' style='margin-top: 3em'><sup>1</sup> To be honest, I don&#8217;t know if it is allocated or it comes from a pool or what happens behind the scenes. A new object is initialized and returned each time, so the advice still stands.</p>
]]></content:encoded>
			<wfw:commentRss>http://mysterycoconut.com/blog/2011/09/cag4/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Designing Casey&#8217;s Contraptions, Part 3: iPad to iPhone</title>
		<link>http://mysterycoconut.com/blog/2011/08/designing-casey-3/</link>
		<comments>http://mysterycoconut.com/blog/2011/08/designing-casey-3/#comments</comments>
		<pubDate>Thu, 25 Aug 2011 03:28:54 +0000</pubDate>
		<dc:creator>Miguel A. Friginal</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Designing Casey's Contraptions]]></category>
		<category><![CDATA[idevblogaday]]></category>

		<guid isPermaLink="false">http://mysterycoconut.com/?p=1028</guid>
		<description><![CDATA[<p>Are you ready for a ridiculous amount of screenshots and details about the boring task of porting an iPad game to the iPhone? Well, keep reading then!</p>]]></description>
			<content:encoded><![CDATA[<p>It is a sunny (for once), beautiful summer in the Pacific Northwest and, as usual since <a href='http://mysterycoconut.com/blog/2010/09/going-indie/'>you went indie</a>, you are sitting at home working. Any other day you would be cranky at this hour of the day, jealously looking out the window at the joggers running around the park. They are all slender and happy, their long hair moves in slow-motion, their immaculate iPods probably playing something from the Mamas and the Papas; you can see they are enjoying themselves. There is not even one of the Jell-o wobbly ones left; those all gave up last month and by now are probably eating s&#8217;mores, sitting in the shade of their RV in some beautiful locale. Oh, how you hate them all.</p>
<p><span id="more-1028"></span>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/08/51875048-65c0-4580-98d1-24a79d667372.Medium.jpg" alt="51875048 65c0 4580 98d1 24a79d667372 Medium" title="51875048-65c0-4580-98d1-24a79d667372.Medium.jpg" border="0" width="440" height="246" /></p>
<p>But not today. Today you are so smug you are fogging the windows, because an hour ago your email pinged and you were happy to read that <b>&#8216;Your Application is now In Review&#8217;</b>. So happy indeed that you had to make sexy Fiona, Lion&#8217;s Scottish Standard English voice (and the only girl you have talked with for weeks), read the whole damn thing, including the legal text, 2 or 3 times. How long has this latest endeavor taken anyway? It was an update after all, not even a whole new game!</p>
<p>Casey&#8217;s Contraptions came out for iPad only in May. Since then, you and your partner in crime have been working on making it run on the iPhone. That&#8217;s 3 months for those of you counting. So what has taken this long? Wasn&#8217;t it a straight port? Lots of shared code? Just shrink the images and go? Well…</p>
<h3>Reducing the Number of Choices</h3>
<p>People nowadays are not that much into reading, and to tell the truth, I had to create a whole <a href="http://idevblogaday.com/">support group</a> just to get myself in the mood of writing, so let&#8217;s just cut to the chase and show you some graphic examples (click on the iPad screens to see them at full resolution):</p>
<p class='imgCenter'><a rel='lightbox' href='http://mysterycoconut.com/wp-content/uploads/2011/08/CaseyMainMenu_iPad.png'><img src='http://mysterycoconut.com/wp-content/uploads/2011/08/CaseyMainMenu_iPad-516x387.png' width='516' height='387' alt='' /></a><br />Casey&#8217;s Contraptions Main Menu on the iPad.</p>
<p class='imgCenter'><img src='http://mysterycoconut.com/wp-content/uploads/2011/08/CaseyMainMenu_iPadphone.png' width='480' height='320' alt='' /><br />Casey&#8217;s Contraptions Main Menu from the iPad, reduced to iPhone size.</p>
<p>So that&#8217;s not looking so bad… oh wait, I forgot to show you the finger. Sorry about that.</p>
<p class='imgCenter'><img src='http://mysterycoconut.com/wp-content/uploads/2011/08/CaseyMainMenu_iPadphoneHand2.png' width='516' height='405' alt='' /><br />Oops. And that&#8217;s a small hand right there.</p>
<p>So not so great. The thing is on the iPad screen there are plenty of actions that the user can take, but they are all big, spread out, and graphically different enough, that they don&#8217;t compete with each other (too much) for the user&#8217;s attention. Let&#8217;s count how many actions are possible in this screen. The user can:</p>
<ol>
<li>Play the Classroom tutorial levels.</li>
<li>Play the Backyard levels.</li>
<li>Play the Bedroom levels.</li>
<li>Play the new Tree House levels.</li>
<li>Go to the Sandbox.</li>
<li>Scroll the locations to have better access to the Sandbox, Tree House, and beyond.</li>
<li>Open the credits screen.</li>
<li>Check the game news.</li>
<li>Or open the game settings.</li>
</ol>
<p>When we cram all that info into a smaller space, we are changing the mood from a relaxed exploration of possibilities, to a much more stressful one of trying to identify what is what. But really, how do we get rid of options here? Everything seems pretty much necessary, unless we rearrange screens and put access to the credits in some other place. Guess what? Doing that we will just be cramming some other screen, and I can tell you they are already as busy as the main menu.</p>
<p>There is one thing we can do though. The normal action for a user on this screen is to continue playing where he left. If he is playing the Classroom levels, that&#8217;s the button that should be more prominent, in the middle of the screen. You should still be able to scroll to the other locations, and with a paged scroll view they can all snap to the middle of the screen as you do it. We just converted those five first actions in our list to only one. The result:</p>
<p class='imgCenter'><img src='http://mysterycoconut.com/wp-content/uploads/2011/08/CaseyMainMenu_iPhone.png' width='480' height='320' alt='' /></p>
<h3>Sizing issues</h3>
<p>An iPad&#8217;s screen is 1024&#215;768 pixels, or a ratio of 4:3. An iPhone 3GS is 480&#215;320, and an iPhone 4 is double that or 960&#215;640. That&#8217;s a screen ratio of 3:2. So to make the iPad game area fit the iPhone screen we needed to either fit it vertically and have vertical bands on the sides, or horizontally and crop top and/or bottom. Luckily for us not all the screen is used in the game when the simulation is running; there is a nice chunk underneath the floor level that is just decorative.</p>
<p class='imgCenter'><img src='http://mysterycoconut.com/wp-content/uploads/2011/08/CaseyBackground_iPadphone.png' alt='' width='480' height='360' /><br />The red line represents what we can show in the iPhone when fitting the location background to the width of the screen.</p>
<p>That was convenient… but what goes there on the iPad again? Ah yes, the toolbox with all the items you get to solve each level!</p>
<p class='imgCenter'><a rel='lightbox' href='http://mysterycoconut.com/wp-content/uploads/2011/08/CaseyToolbox_iPad.png'><img src='http://mysterycoconut.com/wp-content/uploads/2011/08/CaseyToolbox_iPad-516x387.png' width='516' height='387' alt='' /></a><br />Yeah, I think we may need that…</p>
<p><a href="http://gamesfromwithin.com/good-things-take-time">Noel already wrote about all the details</a> that went into implementing a retractable toolbox, something that seems easy enough until you try to use it and implement it. The result looks like this:</p>
<p class='imgCenter'><img src='http://mysterycoconut.com/wp-content/uploads/2011/08/CaseyToolboxClosed_iPhone.png' width='480' height='320' alt='' /><br />Closed…</p>
<p class='imgCenter'><img src='http://mysterycoconut.com/wp-content/uploads/2011/08/CaseyToolboxOpen_iPhone.png' width='480' height='320' alt='' /><br />…and open.</p>
<p>What happens when you get an object, let&#8217;s say the soccer ball, out of the toolbox? The toolbox not only closes so you have access to the bottom of the screen, all the buttons fade out while you drag the object so you have a clear view of the whole play area.</p>
<p class='imgCenter'><img src='http://mysterycoconut.com/wp-content/uploads/2011/08/CaseyToolboxObject_iPhone.png' width='480' height='320' alt='' /><br />Details, details…</p>
<h3>Too many fingers</h3>
<p>On the iPad we use gestures that feel pretty natural for interacting with the objects. You can drag them, double-tap to flip them, and rotate them with 2 fingers. Rotating was the gesture that gave us the most trouble on the iPad; we went through many refinements to take into account how different people put the fingers on the screen. On the iPhone, as Noel has said more than once before, you need to make your game playable with just your thumbs, even only with one hand. But unless you have evolved more fingers than the average person, holding the phone and rotating with 2 fingers of the same hand is going to be tricky.</p>
<p>As a staunch supporter of direct manipulation in games I was totally against selection widgets, those things with buttons that appear around an object and that you tap or drag to interact with it indirectly, on the iPad. Rotation on the iPhone was a different beast though, so this is what happens when you either tap, or finish dragging an object.</p>
<p class='imgCenter'><img src='http://mysterycoconut.com/wp-content/uploads/2011/08/CaseyRotation_iPhone.png' width='480' height='320' alt='' /></p>
<p>By touching anywhere in the blue arrows (that rock back and forth in the game) you can rotate the object with only one finger. Does that mean we got rid of all 2-finger gestures? No, we needed one that everybody is going to try when they see how small the 8-balls are on that screen!</p>
<p class='imgCenter'><img src='http://mysterycoconut.com/wp-content/uploads/2011/08/CaseyZoom.png' width='480' height='320' alt='' /><br />Just like a Mazda Miata.</p>
<h3>About Features</h3>
<p>We put lots of effort into having the iPhone version of Casey be as feature-full as the iPad one. One of the things we talked about removing from the very beginning was the level editor, but as you can see in the screenshots above that finally made it! Yes, is nicer on the bigger screen of the iPad; but you will be surprised how well the editor works even in the small screen.</p>
<p>The only feature that didn&#8217;t actually made the cut was another case of too many options in the screen. Take a look:</p>
<p class='imgCenter'><a rel='lightbox' href='http://mysterycoconut.com/wp-content/uploads/2011/08/CaseySettings_iPad.png'><img src='http://mysterycoconut.com/wp-content/uploads/2011/08/CaseySettings_iPad-516x387.png' width='516' height='387' alt='' /></a></p>
<p>The multiple player profiles were one of the most requested features from families with kids (mind you, not because the kids wanted it, but because the parents didn&#8217;t wanted to play through the already unlocked levels of their mentally superior offspring. But when trying to pack all this info into the iPhone it became apparent we would need to divide it into multiple screens and create some kind of navigation between them. Then we realized iPhones and iPods are a more personal item. Is far more common for a family to have only one iPad, and multiple iPods, than to share an iPhone between everybody. So we got rid of it, and the result is a simplified Settings screen.</p>
<p class='imgCenter'><img src='http://mysterycoconut.com/wp-content/uploads/2011/08/CaseySettings_iPhone.png' width='480' height='320' alt='' /></p>
<p>Many other screens had to be divided in two though, and I was not too happy about that at first. Take a look at the sandbox menu, for example:</p>
<p class='imgCenter'><img src='http://mysterycoconut.com/wp-content/uploads/2011/08/CaseySandbox_iPhone.png' width='480' height='320' alt='' /><br />One, …</p>
<p class='imgCenter'><img src='http://mysterycoconut.com/wp-content/uploads/2011/08/CaseySandboxFriends_iPhone.png' width='480' height='320' alt='' /><br />… two.</p>
<p>But at the end it helped make things more clear. Again, less options on each screen means less confusion. And the nice sliding animations between them help know what&#8217;s going on.</p>
<p>Anyway, I am sure you are sick of reading all the ridiculous details, so that&#8217;s it. It took 3 months, but we are sure the result will shine. Look for it on the App Store in a couple weeks!</p>
]]></content:encoded>
			<wfw:commentRss>http://mysterycoconut.com/blog/2011/08/designing-casey-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>iDevBlogADay (and 3)</title>
		<link>http://mysterycoconut.com/blog/2011/07/idevblogaday4/</link>
		<comments>http://mysterycoconut.com/blog/2011/07/idevblogaday4/#comments</comments>
		<pubDate>Tue, 26 Jul 2011 20:13:18 +0000</pubDate>
		<dc:creator>Miguel A. Friginal</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://mysterycoconut.com/?p=992</guid>
		<description><![CDATA[Last blog post got quite a few comments, all related to the future of iDevBlogADay and the quality, or lack thereof, of my taste for telefilms. Since I was way more interested in hearing about this second subject, serve this as the last you will ever heard of iDevBlogADay in this blog. Have I then [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://mysterycoconut.com/blog/2011/07/recap/">Last blog post</a> got quite a few comments, all related to the future of iDevBlogADay and the quality, or lack thereof, of my taste for telefilms. Since I was way more interested in hearing about this second subject, serve this as the last you will ever heard of iDevBlogADay in this blog.</p>
<p><span id="more-992"></span></p>
<p>Have I then decided to finally get rid of iDev? Not at all. I am excited to announce a new phase for it has started that will hopefully boldly bring iDevBlogADay where no BlogADay has gone before… well, except for <a href='http://altdevblogaday.com'>AltDevBlogADay</a>, whose awesomeness we are going to shameless copy as much as necessary.</p>
<p><img src="http://mysterycoconut.com/wp-content/uploads/2011/07/google-groups-logo-260x260.jpg" alt="" width="260" height="260" class="alignright size-medium wp-image-993" />To that effect, I have created an <a href='http://groups.google.com/group/idevauthors'>iDevAuthors Google Group</a> where we are currently discussing the upcoming changes. <a href='http://groups.google.com/group/idevauthors/subscribe?note=1'>You should join</a> if you want to write for iDevBlogADay in the future (and yes, that includes current iDev authors and people in the waiting list; if you don&#8217;t join the group, you will be skipped when we roll out the changes). </p>
<p>Some of the proposed changes are:</p>
<ul>
<li>No waiting list. We divide everybody in the normal 2 weeks, so we will have as many posts per day as necessary instead of just two.</li>
<li>Since there is no waiting list, we will not kick out anybody, even if they forget to post in their day. We will still remove anybody that continuously skips his turn though.</li>
<li>More information about each author.</li>
<li>Archive of past posts, and search.</li>
</ul>
<p>If you have additional ideas you want to see, and want to help making it happen, join the Google Group. Cheers!</p>
]]></content:encoded>
			<wfw:commentRss>http://mysterycoconut.com/blog/2011/07/idevblogaday4/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Recap</title>
		<link>http://mysterycoconut.com/blog/2011/07/recap/</link>
		<comments>http://mysterycoconut.com/blog/2011/07/recap/#comments</comments>
		<pubDate>Mon, 18 Jul 2011 15:00:46 +0000</pubDate>
		<dc:creator>Miguel A. Friginal</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://mysterycoconut.com/?p=778</guid>
		<description><![CDATA[Hey, it&#8217;s July already! Does time fly or what? I guess is time for a status update and see if I pick up blogging again (didn&#8217;t I create something to help with this? So much for that, is not going to be my turn in ages!). In any case what better way to talk about [...]]]></description>
			<content:encoded><![CDATA[<p>Hey, it&#8217;s July already! Does time fly or what? I guess is time for a status update and see if I pick up blogging again (didn&#8217;t I create <a href='http://idevblogaday.com'>something to help with this</a>? So much for that, is not going to be my turn in ages!).</p>
<p>In any case what better way to talk about the last 5 months than to do a quick recap of my old <a href='/blog/2011/01/cookies-2/'>list of evil projects</a>.</p>
<p><span id="more-778"></span></p>
<h3 class='noclear'>The Ones That Got Done</h3>
<p>You are looking at one of the projects that I got (kind of) done: the <b>new design for the site</b>.</p>
<p>In case you are wondering how it used to be, here you have a couple screenshots:</p>
<div class='horizontal'>

<a href='http://mysterycoconut.com/?attachment_id=907' title='Design1Home'><img width="100" height="100" src="http://mysterycoconut.com/wp-content/uploads/2011/07/Design1Home-100x100.jpg" class="attachment-thumbnail" alt="Design1Home" title="Design1Home" /></a>
<a href='http://mysterycoconut.com/?attachment_id=908' title='Design1Blog'><img width="100" height="100" src="http://mysterycoconut.com/wp-content/uploads/2011/07/Design1Blog-100x100.jpg" class="attachment-thumbnail" alt="Design1Blog" title="Design1Blog" /></a>

</div>
<p>There were a few things I wanted to attain with the redesign, but the important ones were improving readability (too many people complained about the white text on dark background), and featuring the multiple apps and projects I am involved in. That it took me this long to have a site that actually supports multiple projects just goes to show how confident I was on finishing more than one.</p>
<p>In any case, I made it live today with some parts missing. I will be adding stuff as time passes and, even through is not my turn in <a href='http://idevblogaday.com'>#iDevBlogADay</a>, I mean to write more often in this blog; maybe I should go for the old<i> ‘every Wednesday’</i>.</p>
<hr />
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/07/TopiPadApps-516x224.jpg" alt="" width="516" height="224" class="alignnone size-large wp-image-928" /></p>
<p>Of course the big (and old, since it happened more than a month ago) news is we finished <b><a href='http://mysterycoconut.com/casey/'>Casey’s Contraptions</a></b>, it was featured by Apple as Game of the Week across the world on its first week, got fantastic reviews, and shoot up all the way to number 2 in the US apps chart. Some articles:</p>
<ul>
<li>Games From Within: <a href='http://gamesfromwithin.com/caseys-contraptions-on-the-media'>Casey’s Contraptions on the Media</a></li>
<li>Pocket Gamer: <a href='http://www.pocketgamer.biz/r/PG%2EBiz/Casey%27s+Contraptions/feature.asp?c=30643'>The Making of Casey’s Contraptions</a></li>
<li>Gamasutra: <a href='http://www.gamasutra.com/view/feature/6412/postmortem_llopis_and_friginals_.php'>Postmortem: Llopis &#038; Friginal’s Casey’s Contraptions</a></li>
<li>IGN: <a href='http://wireless.ign.com/articles/117/1170838p1.html'>Casey’s Contraptions Review</a></li>
<li>Kill Screen: <a href='http://killscreendaily.com/articles/reviews/review-caseys-contraptions'>Review: Casey’s Contraptions</a></li>
</ul>
<p>Since then it has maintained a pretty good position in the charts, although sales have slowed down considerably. We have been working on the next version for a while now. The plan is to convert the current iPad-only game into a Universal version, and also sell an iPhone-only cheaper one. <a href='http://gamesfromwithin.com/good-things-take-time'>Is taking a while</a> since we are recreating each one of the screens so it&#8217;s usable on a small screen, and boy, we have <em>lots</em> of UI.</p>
<p>The whole surreal experience of having success in the App Store requires its own post, and Noel also wants me to write about the specific changes we are doing to the iPhone UI, so maybe next week.</p>
<hr />
<p id='idbad'>The third one that got kind of done is the <b>#iDevBlogADay redesign</b>. Let&#8217;s talk briefly about the <i>kind of</i> part.</p>
<p>As you can <a href='http://mysterycoconut.com/blog/2011/02/idevblogaday3/'>read here</a>, I changed the rules slightly and made the new design live last February. Since then, I have not touched the site even once, except for adding people to the waiting list. And to tell the truth, I am growing more dissatisfied with its evolution. For one, doing it every 2 weeks doesn&#8217;t seem to help with the intended purpose of getting in the habit of writing; lots of people drop from the main list because they forgot about it, and I have read one too many &#8220;is going to be short this week because I didn&#8217;t have the time&#8221; posts.</p>
<p>I have also come to realize the new design is too cold. It was done that way so as to not impose a particular style to the blend of authors and blogs. But after following the <a href='http://altdevblogaday.com'>#AltDevBlogADay</a> design revisions, I recognize they make a way better job of representing their authors, with photos, bios, links, featured authors, and more.</p>
<p>Problem is I have not even created a basic Join Us form, or even an About page after 5 months. I have not had the time, and I finally didn&#8217;t recruit anybody else to help. So not sure what&#8217;s next. I think I would like to get closer to the #AltDevBlogADay spirit and support our authors and content better in the future. But maybe is time to point everybody to #AltDevBlogADay and close the doors here. As always, your thoughts on what&#8217;s working, what&#8217;s not, and how to fix it are very welcomed.</p>
<h3>The Ones That Didn&#8217;t Get Done</h3>
<p><img src="http://mysterycoconut.com/wp-content/uploads/2011/07/Arale-2.jpg" alt="" width="220" height="200" class="alignright size-full wp-image-803" />So now for the downers, the other four projects that I did not have time for. <a href='/blog/2011/01/cookies-2/#evilProject2'>iDevTracker</a>, <a href='/blog/2011/01/cookies-2/#evilProject3'>Notedo</a>, and <a href='/blog/2011/01/cookies-2/#evilProject6'>The Legend of Robin Hood</a> received no attention at all. Pretty sad, but lets be serious… didn&#8217;t I write before about <a href='/blog/2010/07/shelve-it/'>the reasons things get shelved around here</a>? The first two enter straight into the &#8220;boring&#8221; category, and the game, although it really pains me, into the &#8220;scope creep&#8221; one. I should just pay more attention to what I write!</p>
<p><img class='alignleft' src='http://mysterycoconut.com/wp-content/uploads/2011/01/ElephantAnimation.gif' alt='' width='190' height='228' />So what&#8217;s left? Well, the <a href='/blog/2011/01/cookies-2/#evilProject7'>Elephant Run</a> game! Since the last <a href='/blog/2011/02/cag3/'>disgruntled post about Core Animation games</a> I have not touched the prototype again. I still think is a pretty good, small, and doable game idea, so this one is not getting canned for sure. Also I promised to explain how to do a scrolling game with <code>CALayers</code> without wasting memory, I just need to get to it.</p>
<h3>More?</h3>
<p>You didn&#8217;t think I was going to be happy getting rid of projects without adding some more to the queue, did you? Some weekends ago I worked on a quick prototype for a different game after watching <a href='http://www.imdb.com/title/tt0412915/'>The Librarian</a> TV movies and then <i>Raiders of the Lost Ark</i> a couple times back to back. Still no title, but I leave you with a screenshot of what I got done:</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/07/TreasureHunt-516x344.png" alt="" width="516" height="344" class="alignnone size-large wp-image-951" /></p>
]]></content:encoded>
			<wfw:commentRss>http://mysterycoconut.com/blog/2011/07/recap/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>iDevBlogADay 2, One Week Later</title>
		<link>http://mysterycoconut.com/blog/2011/02/idevblogaday3/</link>
		<comments>http://mysterycoconut.com/blog/2011/02/idevblogaday3/#comments</comments>
		<pubDate>Thu, 24 Feb 2011 03:45:27 +0000</pubDate>
		<dc:creator>Miguel A. Friginal</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[idevblogaday]]></category>

		<guid isPermaLink="false">http://mysterycoconut.com/?p=701</guid>
		<description><![CDATA[Do you ever wonder what the "excerpt" textfield in your blog is for? Is just so iDevBlogADay readers get a nice summary of your post without ellipses all over the place! You should try it!]]></description>
			<content:encoded><![CDATA[<p>So here we are, one week after I announced the upcoming changes to <a href="http://idevblogaday.com">iDevBlogADay</a> and if you check the site right now you will see I have already some of them online today.</p>
<p>As we did with the first version, I decided to make the new design live early, get some feedback, and improve it with your suggestions. Better to have something out, even with imperfections, than to make you wait forever for it, then never release it.</p>
<p><img class="alignleft" style="margin-right: 1em;" src="http://mysterycoconut.com/wp-content/uploads/2011/02/businessCards.gif" border="0" alt="" width="260" height="400" />It has been kind of a hectic week. Next week I am attending the <a href="http://gdconf.com/">Game Developers Conference</a> in San Francisco, a first time for me. It should be fun, and I promise to write about it when I come back. Of course, since I was doing this, I had to get off my ass and design some business cards! Designing something for yourself is always the most difficult thing, but nothing better than a deadline to make it happen. I am pretty happy with how they turned out (thanks <a href="http://streamingcolour.com">Owen</a> for recommending <a href="http://moo.com">moo.com</a>!).</p>
<p>Noel and I have also been preparing the beta release for <a href="http://caseyscontraptions.com">Casey&#8217;s Contraptions</a>. If you are interested and have an iPad lying around, I think you are still in time; just <a href="http://gamesfromwithin.com/contact">send Noel a note</a>. To top it off, I got a cold that is making the fan of my computer sound like elephants running around my ears. By the way, one of those nights I could not sleep I also finish the scrolling background for the elephants, including randomly generated tiled paths…</p>
<p>So anyway, that is my excuse in case the whole iDevBlogADay site goes down in flames while I am partying. Why did I have to do it this week??? Heck if I know :) But let me give you the rundown of the changes.</p>
<p><span id="more-701"></span></p>
<h3>The New Rules</h3>
<p>Although I got some pretty good suggestions last week about other possible changes, I finally decided to go with my initial plan. That meant basically two things:</p>
<ul>
<li>Each author gets 2 weeks between posts. This means 14 new authors from the waiting list will join starting next week to cover the gap.</li>
<li>10 consecutive posts, or 20 weeks, as a limit. Once an author reaches its 10th post, he will be automatically moved to the end of the waiting list, and the first person in the list will take his place.</li>
</ul>
<p>I was already keeping track of the date each person currently in the main list had started, so counting back I found 4 people had already been longer than 10 posts. I gave them this week to say their goodbyes, and they will be replaced in 2 weeks. Thanks <a href="http://36peas.com/blog">Gareth</a>, <a href="http://iphone.ezone.com">Simon</a>, <a href="http://gandogames.com/">Nicolas</a> and <a href="http://karnakgames.com/wp/">Alfred</a> for being so understanding.</p>
<p>Starting this coming Sunday new authors will have their turn. I already assigned days to the people that were in the top of the waiting list. Check the site to see when is your turn, and if you don&#8217;t like it, since you all are starting at the same time, maybe you can trade with some other person. Just let me know.</p>
<p>As a result of all this, we have reduced the waiting list from 60 something to around 45. In just a few weeks there will be more empty spots (mine included!), and even when all this movement is kind of nice we will see if it solves anything at the end. I have been thinking that maybe starting everybody on the same week is a bad idea, especially if nobody drops before their 10 weeks; but I am playing it by ear, we will see how it looks in a couple months.</p>
<h3>The New Design</h3>
<p>As you can see I changed the horizontal layout to a vertical one. The top of the page will always contain the posts for today, and I ordered the rest in inverse chronological order, so yesterday is just bellow. For each day, apart from the 2 blogs that either wrote or have to write this week, you will also see the 2 that blog in alternating weeks in smaller type over a grey background.</p>
<p>I didn&#8217;t find an appropriate place for the usual NEW badge, so instead I just turned the whole title block red. Not too happy with that, so suggestions are welcomed.</p>
<p class='imgCenter'><img title="idevblogaday3.jpg" src="http://mysterycoconut.com/wp-content/uploads/2011/02/idevblogaday3.jpg" border="0" alt="" width="480" height="315" /></p>
<p>For each blog you will also see a bar representing how many posts the author has left to write. The week the bar is full is the last post for that author. The following week, the first person in the waiting list at the time will take its place, although he will not have to write anything until one week later (so you guys will have at least a week notice for sure). I was thinking maybe I should add some kind of email notification, but for now you will have to check the site.</p>
<p>As you can see the design is pretty dry, but legible. Since iDevBlogADay represents a multitude of authors, and I don&#8217;t want to impose them any particular style, I suppose is better this way. I didn&#8217;t use any fancy javascript this time, so I hope it works in all devices and (modern) browsers without problems.</p>
<h3>The Missing Parts</h3>
<p>Things that were present in the previous design and are nowhere in this one:</p>
<ul>
<li><strong>The list of &#8220;Other posts by this author&#8221;:</strong> I omitted it so you will not have to scroll forever to go to the next day. I am not sure many people used those links, since probably you all use RSS readers and not the site itself. If you guys see the point in having them back, please tell me and I will see if I can fit them there somehow.</li>
<li><strong>The &#8220;about&#8221; blurb, and RSS link:</strong> I still need to add a page with information about what the site is about, how to use it, how to participate, etc. I am thinking I will add a menu at the top by the logo with these links. Since they were not essential, I probably will not get to that until after I come back from San Francisco.</li>
<li><strong>The day navigation: </strong>the links to jump directly to a certain day didn&#8217;t seem as important with the vertical layout. Any opinions?</li>
</ul>
<p>And stuff still in my to-do list:</p>
<ul>
<li>Sign-up page for getting into the waiting list. I am probably going to use Google login for this, no need to create yet another user login system.</li>
<li>Admin to give up your spot in the main list, move to the end of the waiting list if you are getting towards the top and you are not ready, or remove yourself all together from the list.</li>
<li>Archive of previous articles. I get this request now and then, so maybe having a searchable archive of posts is a good idea? There is some cases of previous blogs disappearing all together from the internet, but I am not sure I want to duplicate the content of participant blogs if I can avoid it. </li>
</ul>
<p>I think that&#8217;s about it. As always, send me your feedback and ideas about anything you would like changed. Now if you excuse me, I have to get rid of this cold in the next 4 days (BTW, if your doctor ever tells you to sniff salt up your nostrils, take note that 1/4 of a teaspoon is not the same as 1/4 of a tablespoon. Damn abbreviations :)</p>
]]></content:encoded>
			<wfw:commentRss>http://mysterycoconut.com/blog/2011/02/idevblogaday3/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>iDevBlogADay, Take 2</title>
		<link>http://mysterycoconut.com/blog/2011/02/idevblogaday2/</link>
		<comments>http://mysterycoconut.com/blog/2011/02/idevblogaday2/#comments</comments>
		<pubDate>Thu, 17 Feb 2011 02:37:01 +0000</pubDate>
		<dc:creator>Miguel A. Friginal</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[idevblogaday]]></category>

		<guid isPermaLink="false">http://mysterycoconut.com/?p=691</guid>
		<description><![CDATA[iDevBlogADay has outgrown its very humble beginnings. How can we keep it going? Here are some solutions to our current problems.]]></description>
			<content:encoded><![CDATA[<p><a href="http://idevblogaday.com/">iDevBlogADay</a> started about 8 months ago. If you are reading this post you probably know what it is all about, but a quick recap for those new to it: every day of the week, two developers write on their own blogs about whatever they prefer. They need to do it every week, for as long as they can, on the same week day. For example, I am right now sharing Wednesdays with <a href="http://www.36peas.com/">Gareth Jenkins</a>. If for any reason one of the authors doesn&#8217;t publish anything on his assigned day by midnight PST, he is put at the end of a &#8220;waiting list&#8221; (unless he prefers to call it good), and the first person in that list takes his place.</p>
<p>As you can see the rules cannot be simpler. That&#8217;s how it was intended from the beginning, mainly because if there was more rules somebody would have to enforce them. Take for example the &#8220;you can write about whatever you want&#8221; rule. If it was instead &#8220;write about this particular subject&#8221;, it could be totally open to interpretation; what is good for me may not be good enough for you. I would then become more of an editor, and iDevBlogADay more of an online publication, with schedules, style guides, and who knows what else. At the end it would be less successful in what it really is all about: to make people write. So it was determined that less rules meant less ways things can be unfair. The &#8220;you don&#8217;t post, you are out&#8221; is the kind of cut-and-dried rule that makes it all work with the least possible friction.</p>
<p>But iDevBlogADay has been evolving. With almost 500 posts under its banner, and more than 60 people waiting their turn, is clear that it cannot go any longer without some changes. And those changes, whether I like it or not, are going to require some new rules.</p>
<p><span id="more-691"></span>
<p>One of my main concerns has always been the people waiting in line. For starters, the more people on the waiting list, the less attractive it is to join the group. What&#8217;s the point if you know is going to take forever for it to be your turn? The system was built thinking a dozen people at most would ever be waiting, and the drop rate was expected to be higher, given everybody involved previous experience.</p>
<p>But there are only 2 ways to get people out of the waiting list: either we have more people writing per day, or we impose a time limit after which posters are automatically rotated.</p>
<h3>Time Limits &amp; Other Ways to Get Rid of People</h3>
<p>Time limits have been proposed in the past to help increase the drop rate. Sometimes this is proposed as a way to get rid of people whose posts are growing stale, or that don&#8217;t contribute interesting posts in general. A similar method proposed a number of times is voting each week for the best/worst posts, and kicking whoever gets the less votes.</p>
<p>The reason I don&#8217;t like this much is twofold. First, it totally goes against the main goal. The thing is that goal is all about the writers, not so much about the readers. Yes, iDevBlogADay provides a bigger stage than our individual blogs had to start with (well, <a href="http://gamesfromwithin.com">with exceptions</a>), and we all strive to give readers reasons to come back. But the same way the rules are not about the subject of what you write, they are not about the quality. This is in some aspects the path of less friction for me; I could try the voting system as a way to not only write more, but also write better. And that&#8217;s the other reason I don&#8217;t care much for this; implementing and managing it seems like a nightmare. Until now I was glad to leave everything as is and trust the old adage of practice makes perfect.</p>
<p>At the same time, time limits can be a boom, if not for getting rid of writers, at least for getting people out of the waiting list; that is the only reason I am even considering it.</p>
<h3>More People Per Day</h3>
<p>Having 3 or 4 people per day instead of 2 has also been a constant suggestion. Let&#8217;s say we started tomorrow with 4 people per day. That would be 14 more people going from the waiting list into the main list, so only… 49 people will be left in the waiting list. That&#8217;s only until more join in, of course. I realize this is not a long-term solution either (I don&#8217;t think there is actually one). But what I find more interesting is the other reader complain about this: that would make too many post to read every day!</p>
<p>And on this case I am on the reader&#8217;s side. I don&#8217;t know about you, but I am not gaining spare hours every day. I am not even able to read all is published in iDevBlogADay right now. I would probably care less about the whole thing if there was even more to read, independent of how good the content.</p>
<h3>AltDevBlogADay Solution</h3>
<p>The<a href="http://altdevblogaday.org/"> &#8220;other&#8221; blog a day site</a> doesn&#8217;t seem to have any of these problems (or at least I have not seen them voiced). They also work slightly different: every participant gets a turn, and when everybody that signed up has written a post they start over from the beginning. Some people asked me why we don&#8217;t use the same system then, but it all goes back to the main reason of the existence of iDevBlogADay. If is all about getting in the habit of writing, you <a href="http://mysterycoconut.com/blog/2010/12/habits/">need to do it often</a>. In that sense AltDevBlogADay is more about the content, and less about habit formation.</p>
<p>But their system also got me thinking… is a week a good enough time between posts? What about two weeks instead? I immediately liked this solution because it solved a number of problems.</p>
<p>Take the <a href="http://www.subfurther.com/blog/2011/01/31/up-next…/">last post from Chris Adamson</a> before handling over his day to the waiting list as an example:</p>
<blockquote>
<p>My original plan for being featured on the <a href="http://idevblogaday.com/">iDevBlogADay</a> blogroll was to be able to share some of the work I’m doing on the <a href="http://www.mypearsonstore.com/bookstore/product.asp?isbn=9780321636843"><em>Core Audio</em></a> book. I figured that as I worked through new material, that would translate into blog entries that could then get the word out about the book.</p>
<p>Unfortunately, I think what’s happening is that I’ve been working on iDevBlogADay entries <em>instead of</em> working on the book.</p>
</blockquote>
<p>The thing is a week is not that much time for having something new worth writing about for somebody whose main job is not writing. It happens to me all the time, wondering what the heck to write about, then having to put away my work to do it! And if I had more time to expend on my work, I probably would get more interesting things to write about, no?</p>
<p>So what would be the consequence of having 2 week periods then?</p>
<ul>
<li>For starters, 14 people will get from the waiting list into the main list.</li>
<li>I would have way more to manage. It doesn&#8217;t happen often, but I am doing the whole getting into or off the list manually. I would have 14 more people to check on.</li>
<li>Given that authors will have two full weeks to write their posts, pressure is off. If drop rates were already low, there would be even less reason for anybody to lose its spot.</li>
</ul>
<h3>Future</h3>
<p>The plan I have decided to go with is to have both 2 week periods, and a time limit. The 2 weeks will help with having more people in without having more to read per day, and the time limit will help with making the waiting list move faster. My first thought is the limit will be around 10 posts. That&#8217;s 20 weeks, or 5 months per author. We will see if that&#8217;s not fast enough.</p>
<p>Having to manage more people also makes my need to implement some automatic tools in the backend even more obviously. On my todo list I have:</p>
<ul>
<li>Automatic list handling. If you miss your day or the time limit is up, next person gets your spot, you go to the end of the list. Should have been like that from the very beginning, but since the code was done in a day and has not been touched much since…</li>
<li>A &#8220;how it works&#8221; page. I don&#8217;t know how many times I have to explain the rules to new people over Twitter.</li>
<li>A sign-up form. Same thing, getting the info from new authors on Twitter is getting old.</li>
<li>Multiple admins. It has all been me until now, but I am thinking of recruiting some more individuals that don&#8217;t mind solving problems with the site if any appear. If you are a participant with minimal PHP knowledge and don&#8217;t mind spending a few minutes now and then (hopefully not many once all the automatic tools are in place), ping me. </li>
</ul>
<p>Lastly, this also means <a href="http://idevblogaday.com/v2.php">the new design</a> is not valid anymore. I am probably going to simplify it, get rid of the horizontal scrolling and all the javascript, and have info not only about the 2 authors writing every day, but also about the 2 writing the previous week.</p>
<p>So when? I am planning on next week having the same authors as this one, then introduce the new ones. New authors will start posting then two weeks from now. I will get in contact with whoever is past the time limit too (that may include me now that I think about it). As you can see, the whole thing is a mess of conflicting goals. So my plan for the future may hurt some in favor of others. Hopefully it will all be for the better.</p>
<p>If you have any other ideas, please share.</p>
<h4>Screw-up Update #1</h4>
<p>To demonstrate once more how on top of my game I am, Mr. Acton points AltDevBlogADay doesn&#8217;t work at all as I described! Instead everyone posts every 15 days. The more people they get, the more posts per day. He says:</p>
<div class="quotedtweet" id="tw38089584738836480" style="background-color:#eef;padding:5px;margin-bottom:5px">
	<div class="tw_user-info" style="padding:10px 10px 5px 0;float:left;text-align:center;width:100px;">
		<div class="tw_thumb">
			<a href="http://twitter.com/mike_acton" title="Mike Acton" class="quoting_pic" rel="external"><img src="http://img.tweetimag.es/i/mike_acton_n" alt="mike_acton" /></a>
		</div>
		<div class="tw_screen-name">
			<em><a href="http://twitter.com/mike_acton" title="Twitter page : Mike Acton" rel="external">mike_acton</a></em>
		</div>
		<div class="tw_full-name">
			<strong>(Mike Acton)</strong>
		</div>
	</div>
	<div class="tw_content" style="float: left; width: 500px; font: 20pt Georgia, Verdana, sans-serif; font-style: normal;">
		<div class="tw_entry-content">
				<a href="http://www.twitter.com/mysterycoconut" rel="external">@mysterycoconut</a> For me (as well), it's about the writers first. The readers can read at any speed they want. It's not live-TV.

		</div>
	</div>
	<div style="clear: both; text-align: left;font-style:italic;margin-left:110px">
		<p class="tw_meta tw_entry-meta" style="margin: 0;padding-top:5px">
			<small>
				<span>On <a href="http://twitter.com/mike_acton/status/38089584738836480" rel="external">17-2-2011 04:17:19</a></span> 
				<span>from web</span> 
				<span> in reply to <a href="http://twitter.com/mysterycoconut/status/38064690982682624" rel="external">Miguel Á. Friginal</a></span>
			</small>
		</p>
	</div>
</div>
<p>He has a point. Maybe we should do that instead.</p>
]]></content:encoded>
			<wfw:commentRss>http://mysterycoconut.com/blog/2011/02/idevblogaday2/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Scrolling Hell (Core Animation Games 3)</title>
		<link>http://mysterycoconut.com/blog/2011/02/cag3/</link>
		<comments>http://mysterycoconut.com/blog/2011/02/cag3/#comments</comments>
		<pubDate>Wed, 09 Feb 2011 22:54:12 +0000</pubDate>
		<dc:creator>Miguel A. Friginal</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Core Animation Games]]></category>
		<category><![CDATA[idevblogaday]]></category>

		<guid isPermaLink="false">http://mysterycoconut.com/?p=685</guid>
		<description><![CDATA[All you need to know about why NOT to use Core Animation scrolling and tiling classes for games.]]></description>
			<content:encoded><![CDATA[<p>This week my post is going to be necessarily short. <a href="http://gamesfromwithin.com">Noel</a> and I have been working on preparing the first beta for <a href="http://caseyscontraptions.com">Casey&#8217;s Contraptions</a>, and there is still plenty to do before our intended milestone on Friday. He is deep at work squeashing bugs and working on loose ends, while I have been working on creating levels. Yes, you could say I got all the fun while he was hard working, but somehow solving those bugs always involves the rag doll thrown around, poked, squashed, and generally mistreated during his tests (I have this theory that is all due to his repressed feelings as a game developer that doesn&#8217;t want to make violent games; he is probably dying to make a zombie FPS). Anyway, look at the pretty thumbnails of my levels!</p>
<p class='imgCenter'><a rel="lightbox" href="http://mysterycoconut.com/wp-content/uploads/2011/02/CaseyLevelsBig.jpg"><img src="http://mysterycoconut.com/wp-content/uploads/2011/02/CaseyLevels.jpg" border="0" alt="" width="480" height="382" /></a></p>
<p>I still have plenty to do before Friday, so you will have to tune in some other day for part 3 of the Designing Casey&#8217;s Contraptions series (if you have not read the previous posts, they are <a href="http://mysterycoconut.com/blog/2011/01/designing-casey/">here</a>, and <a href="http://mysterycoconut.com/blog/2011/02/designing-casey-2/">here</a>). While the more artsy readers wait, the coders will have another (small) ration of… Core Animation (I bet you were not expecting it, given the title of the post and everything).</p>
<p><span id="more-685"></span></p>
<h3>The Story So Far</h3>
<p>As you may remember I started working on the Elephant Run game with the intention of doing it all with Core Animation, and so demonstrate what I called Thesis A:</p>
<p class="note" style="text-align: center;">Thesis A: <strong>Core Animation is just fine for most 2D games…</strong></p>
<p>But giving the last few weeks, let me present you with Postulate B:</p>
<p class="note" style="text-align: center;">Postulate B: <strong>…but you will suffer if you try.</strong></p>
<p>To explain this postulate, I will present you with the latest in layer scrolling! And some other issues. Yes, that&#8217;s the noise of my teeth grinding, shut up.</p>
<h3>Scrolling is easy! Cannot you just use…</h3>
<p>Let&#8217;s start by defining what I was looking for:</p>
<ol>
<li>a window into a coordinate system plane populated by objects…</li>
<li>that smoothly changes how its borders map to that underlying coordinate system…</li>
<li>and loads the objects to be displayed as they are needed, while keeping memory requirements in check.</li>
</ol>
<p>If you were just idly browsing the documentation, you have probably seen a few CA classes that look pretty promising: there is a <code><strong>CAScrollLayer</strong></code> that looks exactly right, and even a fancy <code><strong>CATiledLayer</strong></code> that can make you think of something like this the first time you read about it:</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/02/SecretOfMana.jpg" border="0" alt="" width="480" height="440" /></p>
<p>Sadly, it is actually more like this:</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/02/5-1.gif" border="0" alt="" width="32" height="32" /></p>
<h3>CATiledLayer</h3>
<p>What does the documentation say about tiled layers?</p>
<blockquote>
<p><code>CATiledLayer</code> is a subclass of <code>CALayer</code> providing a way to asynchronously provide tiles of the layer&#8217;s content, potentially cached at multiple levels of detail.</p>
<p>As more data is required by the renderer, the layer&#8217;s <code>drawLayer:inContext:</code> method is called on one or more background threads to supply the drawing operations to fill in one tile of data.</p>
</blockquote>
<p>That sounds pretty promising to take care of point 3, and since it lets you create tiles of the content you would say 1 can be covered too.</p>
<p>When you start messing with it though, the first impression is that is slow. Like really slow. You may even notice that slow fade of tiles and think &#8220;hey! Is just my old friends, the damn implicit animations trying to make it look cool when what I need is to make it appear NOW! Let&#8217;s just disable those pesky animations!&#8221;. But I am going to save you the effort by editing the docs for you so they are a bit more useful.</p>
<blockquote>
<p><code>CATiledLayer</code> is a subclass of <code>CALayer</code> providing a way to <strong>asynchronously</strong> provide tiles of the layer&#8217;s content, potentially cached at multiple levels of detail.</p>
<p>As more data is required by the renderer, the layer&#8217;s <code>drawLayer:inContext:</code> method <strong>is called on one or more background threads</strong> to supply the drawing operations to fill in one tile of data.</p>
</blockquote>
<p>Don&#8217;t ask me why I didn&#8217;t see that the first time around. Or the 20th. But anyway, <code>CATiledLayer</code> good for photo galleries and zooming into big images… for games, not so much.</p>
<h3>CAScrollLayer</h3>
<p><code>CAScrollLayer</code> has no problems providing both points 1 and 2. To make it work, you create a layer, give it the bounds size of your &#8220;window&#8221;, then add sublayers to it. The moment you send either <code>scrollToPoint:</code> or <code>scrollToRect:</code> to the scroll layer, its sublayers will scroll by. (Note the layer doesn&#8217;t have scroll bars, and will not do a thing when you touch it; you need a <code>UIScrollView</code> for that).</p>
<p>You can also send a <code>scrollPoint:</code> or <code>scrollRectToVisible:</code> to any <code>CALayer</code>, and it will look through its superlayers for a <code>CAScrollLayer</code> to forward these messages to after the proper adjustment of coordinates.</p>
<p>The way <code>CAScrollLayer</code> accomplishes scrolling is pretty straightforward. It just animates changes to its <code>bounds</code> origin (that as we saw in a previous post determines the origin of coordinates for all the sublayers), and by default masks contents to its bounds (<code>maskToBounds</code> property is <code>NO</code> for any other type of layer). To adjust the speed at which the layer scrolls, you can <a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreAnimation_guide/Articles/Transactions.html%23//apple_ref/doc/uid/TP40006096-SW7">use a transaction to override the duration</a> around your scrolling messages.</p>
<p>All this is great, but point 3 is the tricky one. To be able to add and remove sublayers on the fly, change their contents, or any other dynamic behavior to happen while scrolling, we need notifications. And you see, the <code>bounds</code> property never sends letters while being animated. Instead of a nice &#8220;Hey, I am scrolling! I am at (1.0, 1.0)! Now (1.01, 1.0)! Guess what? Now is (1.03, 1.0)!&#8221;, it just tells you something like &#8220;You want me to go to (20.0, 1.0)? OK, ciao!&#8221;. Some properties are just not sociable.</p>
<p>By the way, if you know how to get the bounds to behave, please tell me. But beware, have a running program to show me, because I cannot tell you how many times I was like &#8220;this trickery SHOULD do it! It SHOULD work!&#8221;, just to find it didn&#8217;t.</p>
<p>Anyway, practical solutions to this? Only 2 I can think of. Either scroll in grid sized chunks that allow you to swap pieces <strong>at the end of the scrolling</strong>, or create your own animatable CGPoint property to take care of the notifications while scrolling (your own properties, as <a href="http://mysterycoconut.com/blog/2011/01/cag1/">seen previously</a>, can send nice <code>display</code> and <code>drawInContext:</code> messages periodically while animating).</p>
<p>Next Core Animation article I will go about creating a custom scroll layer that does all this, but that will be another day. Until then, don&#8217;t be like me and have fun creating games with OpenGL or freaking Cocos2D!</p>
]]></content:encoded>
			<wfw:commentRss>http://mysterycoconut.com/blog/2011/02/cag3/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Designing Casey&#8217;s Contraptions, Part 2</title>
		<link>http://mysterycoconut.com/blog/2011/02/designing-casey-2/</link>
		<comments>http://mysterycoconut.com/blog/2011/02/designing-casey-2/#comments</comments>
		<pubDate>Wed, 02 Feb 2011 22:53:17 +0000</pubDate>
		<dc:creator>Miguel A. Friginal</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Designing Casey's Contraptions]]></category>
		<category><![CDATA[idevblogaday]]></category>

		<guid isPermaLink="false">http://mysterycoconut.com/?p=679</guid>
		<description><![CDATA[Continuing with the articles about Casey's Contraptions UI, we go on a slight detour on how I illustrate in-game assets.]]></description>
			<content:encoded><![CDATA[<p>Following with <a href="http://mysterycoconut.com/blog/2011/01/designing-casey/">last week&#8217;s post on designing the interface for Casey&#8217;s Contraptions</a>, and since I get lots of questions about it lately, I am going to continue with how I create the game assets themselves. Yes, this means there is going to be a part 3 with the rest of my UI misadventures next week. Sorry about that.</p>
<h3>Tools</h3>
<p><img class='alignleft' src="http://mysterycoconut.com/wp-content/uploads/2011/02/illustratorIcon.png" alt="" border="0" width="120" height="90" />All the drawings you have seen, from the first sketch I sent Noel to the later interface designs, were created in Adobe Illustrator. Vector graphics allow me to scale assets without losing quality, adjust shapes, and change colors easily. I know plenty of iOS artists use Flash, but I am way more used to the Illustrator tools.</p>
<p>From time to time people ask on Twitter if there are cheaper alternatives to Illustrator. The truth is there is nothing out there that comes even close to the power and flexibility of Adobe&#8217;s tools. Since I have to be cheap (life of the indie :P) what I do is not buy every release (I am still using CS3 right now). If you have an old version of their products the upgrade price is usually more affordable. Educational discounts are also really nice if you are a student.</p>
<p>I also use a Wacom tablet, a 6×11&#8243; Intuos 3 I got a while ago and had not seen much use until recently. The usual question I get about buying one of these is how big it needs to be. I feel more comfortable with something around letter size, that allows for some arm movement. There is a world of difference between even the smaller tablets and using the mouse though.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/02/wacom.jpg" alt="" border="0" width="350" height="200" /><br />That&#8217;s not my arm. My arm is way hairier.<br />But my Wacom is like that one.</p>
<p>Some people like to sketch first on paper, scan, and then clean up and color with Illustrator or Photoshop. I did that at the beginning, but the more used I get to the Wacom, the easier it is to just start from scratch directly on a blank document on the screen. I still draw doodles on paper any time I can; even if you don&#8217;t think you have any artistic abilities, all you really need to get better is lots of practice, and drawing a variety of subjects so you <a href="http://dresdencodak.tumblr.com/post/913972515/draftsmanship-increasing-your-visual-vocabulary">expand your visual vocabulary</a> (by the way, Aaron Diaz&#8217;s blog is worth its word count in gold for any aspiring illustrator, bookmark it!).</p>
<p>In Illustrator I use both the Brush and the Pen tools extensively. I have a variety of brushes I created for Casey&#8217;s look, but they are all basic calligraphic brushes of different sizes, with size dependent upon how much pressure I exert with the Wacom&#8217;s pen.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/02/calligraphicBrush.png" alt="" border="0" width="500" height="252" /></p>
<p style='clear:both'>Normally I use the Brush to draw the outlines, then the Pen to both simplify lines that got too many points and create color areas. I will get to coloring in a bit.</p>
<p><span id="more-679"></span><br />
<h3>Necessary and Unnecessary Detail</h3>
<p>I will show you how I created a RC monster truck this past week. The idea was simple: we needed both a truck and a controller with a button. The 2 objects can be placed separately on the screen. When something hits the button, the truck moves forward.</p>
<p>When creating objects for the game the first thing I usually do, even for the simplest objects, is get some documentation. In the past illustrators used to collect photographs and magazine clippings to use as reference in what they called their <em>morgue file</em>, but as you can imagine Google Images is the way to go nowadays. I try to look for real-world photos of the object in question and select the ones that seem more representative, the ones closer to the &#8220;ideal&#8221; of the object.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/02/trucks.jpg" border="0" alt="" width="500" height="184" />A couple RC monster trucks found with Google Images.</p>
<p>After that I try to divide the object features into 3 groups: the parts that are fundamental to make it recognizable, the parts that are necessary details that make it believable, and the parts that are mere noise. In the case above is clear the giant wheels are the most important part, plus the general shape of the chassis and bed. The door, windows, decals on the side, and the lights add some necessary detail. At first I thought that I could also include the springs used for the suspension, and the motor and cables underneath, but all that ended up being unnecessary.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/02/Outline-n-scale.gif" border="0" alt="" width="448" height="192" />Yep, that looks like the bare minimum for a truck.<br />Soccer ball is there for size comparison.</p>
<p>When I have difficulties deciding what parts of the object are important and what ones are not, I look for how other illustrators have drawn the object in question. I am looking for a stereotyped version of the object in this case, so the most simplified the style the better. That way I can see what is the minimum needed to make something still recognizable.</p>
<p><img class="alignright" src="http://mysterycoconut.com/wp-content/uploads/2011/02/scale.gif" border="0" alt="" width="120" height="140" />As you can see above I do a really quick sketch to begin with. I am only looking for the right shapes and sizes. I try to make the drawing as close to the size is going to show in the game as possible. The scale is by no means exact; if it was, our tennis ball would be almost half the size, and lets not talk about the pinball or the scissors! They would be way too small for any practical use. So, as happens in comics, I am just looking for close enough to be believable.</p>
<p>Then I start adding some of the details. You can see below I try to use thiner lines for the interior of the object and a thicker outline for the outside. This makes shapes less jumbled.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/02/truck-detail-n-pig.gif" border="0" alt="" width="312" height="247" /></p>
<p>After showing Noel this draft we decided the bed needed to be bigger so we could put stuff inside, not on top. The truck should also be able to tow stuff, so it was missing an attachment point in the back. I made some changes to the shape to get a bigger bed, open on the back so it was easier to insert objects there; I figured I could add a rope hook later for the attachment point.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/02/truck-detail-n-pig2.gif" alt="Truck detail n pig2" title="truck-detail-n-pig2.gif" border="0" width="343" height="225" /></p>
<h3>Wheels, Step by Step</h3>
<p><img class='alignright' src="http://mysterycoconut.com/wp-content/uploads/2011/02/wheel1.gif" alt="Wheel1" title="wheel1.gif" border="0" width="170" height="175" />As the wheels seem the most important part of the object, I started with those. Nothing fancy, just a couple circles, taking a bit more care of line widths this time. I draw the circles by hand, so they didn&#8217;t look too perfect. Since this object is going to rotate in the game, big differences from a perfect circle are quite obvious, but I think small ones give it a bit more character.</p>
<p style='clear:both'><img class='alignleft' src="http://mysterycoconut.com/wp-content/uploads/2011/02/wheel2.gif" alt="" border="0" width="170" height="175" />Then, looking at my sample photos, I saw how important the tire tread pattern was to the overall feeling, so I draw a simple shape for it and duplicated it a few times. I kept looking at this at 100%; I didn&#8217;t wanted too many lines making it a confusing mess. I think I got just enough there to convey the shape without it looking too messy.</p>
<p style='clear:both'><img class='alignright' src="http://mysterycoconut.com/wp-content/uploads/2011/02/wheel3.gif" alt="" border="0" width="170" height="175" />The pattern is three dimensional, so I added some extra shapes to obscure parts of the white circle creating that effect. At 100% this is only a couple pixel difference, so you can say it is unnecessary. However without it the wheel looked way too perfect, so they stayed. This is the kind of little detail I like to add to make shapes more realistic, but I try not to overdo it.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/02/truck-with-yellow-wheels.jpg" alt="" border="0" width="300" height="221" /></p>
<p><img class='alignleft' src="http://mysterycoconut.com/wp-content/uploads/2011/02/wheel4.gif" alt="" border="0" width="170" height="175" />Next I added the center of the wheel. I liked the yellow wheels of the toy truck on this photo I found, so I decided to go with a similar color motive. Notice though that what I draw as a dark blue line is going to be light yellow color, and the space in between the lines is going to be the darker holes; it was just easier to draw the separating lines than to draw the pizza shapes in between.</p>
<h3>Color</h3>
<p>That was looking pretty good, so I started adding color. If you have ever painted miniatures, this is basically the same.</p>
<p><img class='alignright' src="http://mysterycoconut.com/wp-content/uploads/2011/02/wheel5.gif" alt="" border="0" width="170" height="175" />You start with a base color. My advice is to always use the HSB (hue, saturation, brightness) selector in the color palette, and not go crazy with saturated colors. Everybody&#8217;s first impulse is to use nice bright saturated colors for everything. But then nothing can be made to stand out, because everything is visually yelling at you! There are so many nice colors with low saturations that you are missing out if you don&#8217;t use them. The color of the tire here is a mere 14% saturation, and even the bright yellow is 70%; it just looks brighter cause of the surrounding color.</p>
<p>Something I have found really useful when choosing colors is sampling them from real photographs. Just get them in Photoshop and sample the wide variety of colors that make up the image. Even on the parts where you only notice bright saturated reds, you will find multitude of less intrusive colors.</p>
<p>Why isn&#8217;t the tire black instead of this weird violet? Same reason. Black and white are the most powerful colors. Their intensity is stronger than even the most saturated reds, so you need to reserve them for when you really need them. I could have used a gray for the wheel instead, but the lack of color would still draw too much attention when staged with everything else in the game.</p>
<p><img class='alignleft' src="http://mysterycoconut.com/wp-content/uploads/2011/02/wheel6.gif" alt="" border="0" width="170" height="175" />After the base color, I add shadows to the parts of the wheel that recede, so we gain a bit of depth. This are drawn normally with the Pen so I can control better the position of each point, and moved behind the outlines but in front of the base color. In this particular case I was not too worried about the direction the light comes from, since the wheel is going to be moving pretty fast most of the time.</p>
<p>Usually I just decrement the brightness of the base color (not too much!), and maybe adjust the hue a little bit so the colors mix harmoniously (e.g., here I moved the darker yellow a bit more towards the orange).</p>
<p><img class='alignright' src="http://mysterycoconut.com/wp-content/uploads/2011/02/wheel7.gif" alt="" border="0" width="170" height="175" />Finally I add the highlights. Although I try to keep things logical, I don&#8217;t really worry too much about shadows or highlights not being in the correct place for a specific light source. You will notice that even in the truck body they are mere approximations. You have to play with it and see how you like it, but the secret again is not to overdo it. The moment that something looks good enough, I stop.</p>
<h3>Other details (or lack thereof)</h3>
<p>The process for creating the truck body was more or less the same. You can see the steps I went through in the animated GIF below.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/02/truck-color.gif" alt="" border="0" width="409" height="234" /></p>
<p>I did try to draw more detail under the chassis and have those cables, the motor, and the springs as shown in some of the photographs, but it soon became apparent that at 100% it was just becoming a mess of lines that didn&#8217;t add anything to the design. At the end I just added some simple shadows and call it good.</p>
<p>For the highlights I used white this time to get that metallic shine look, and I even add a few darker lines to the brake lights, and some translucency to the window. At that point I considered it done and I posted it to Twitter in case I had forgotten something (the more eyes the better). Just a couple minutes passed before Craig from <a href="http://www.littlewhitebearstudios.com/">Little White Bear</a> reminded me I was missing the antenna! And of course, I was also missing the hook for tying the rope so I added both. All in all, a pretty simple design, that looks pretty good in game.</p>
<p><center>
<p class='imgCenter framed'><img src="http://mysterycoconut.com/wp-content/uploads/2011/02/bye-bye-piggy.jpg" alt="Bye bye piggy" title="bye-bye-piggy.jpg" border="0" width="389" height="205" />&#8220;Bye, bye, piggy&#8221;, she said</p>
<p></center></p>
<p>That&#8217;s basically how I do it for Casey&#8217;s Contraptions. As you can see, is not that complicated. Different games and graphics styles will need a different approach, but I hope this helps you in your own process. As always, feel free to ask if you have any questions!</p>
]]></content:encoded>
			<wfw:commentRss>http://mysterycoconut.com/blog/2011/02/designing-casey-2/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Designing Casey&#8217;s Contraptions, Part 1</title>
		<link>http://mysterycoconut.com/blog/2011/01/designing-casey/</link>
		<comments>http://mysterycoconut.com/blog/2011/01/designing-casey/#comments</comments>
		<pubDate>Thu, 27 Jan 2011 05:47:42 +0000</pubDate>
		<dc:creator>Miguel A. Friginal</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Designing Casey's Contraptions]]></category>
		<category><![CDATA[idevblogaday]]></category>

		<guid isPermaLink="false">http://mysterycoconut.com/?p=653</guid>
		<description><![CDATA[Only I can do post-mortems before the game is finished. So let's talk about the problems we run into while designing the style and the interface for Casey's Contraptions.]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" style="margin-right: 1em;" src="http://mysterycoconut.com/wp-content/uploads/2011/01/CaseyVictory.png" alt="" />Last week I posted a couple <a href="http://caseyscontraptions.com">Casey&#8217;s Contraptions</a> screenshots as intro to yet another Core Animation technical rambling. One of the images, my latest try at designing the &#8220;Level Completed&#8221; screen, got a few interesting comments from other designers, both in the here and on Twitter. These screens take a long time to get right, and although people playing the game usually spend just a few seconds on them, they make the difference between a seamless experience and one with harsh continuity bumps.</p>
<p>Today I wanted to review a few of my own &#8220;failed&#8221; designs for Casey&#8217;s Contraptions. And I quote failed because these are a normal byproduct of development; to know what works, you need to create, analyze, and finally discard lots of things that don&#8217;t. Discarding is hard, but is also going to help me explaining another pet peeve of mine: the widely accepted concept that design is all about the looks. You will notice that some of the discarded designs are prettier than the final ones, and I will try to explain why they were still a failure.</p>
<p>A final disclaimer: Casey&#8217;s Contraptions is still pretty much in development. Whenever I say &#8220;final&#8221;, read it as &#8220;current&#8221; :)</p>
<p><span id="more-653"></span></p>
<h3>Theme</h3>
<p>Noel and I started talking about collaborating back in August last year. After some iPhone tech prototypes Noel had decided to go iPad-only to start with, and had a specific setting for the game: a 10-year old kid making these crazy machines to do things kids care about; open the cookie jar, reach for the pie on the top shelf, break the piggie bank, etc. He had been asking a number of artists to try drawing a few of the game objects, but he was not entirely happy with the results. He wanted something very distinctive, that you could look at and say &#8220;Oh, that&#8217;s a screen from Casey&#8217;s Contraptions!&#8221;.</p>
<p>The moment I heard the theme I started thinking cartoony characters, but cartoons cover a wide range of styles. On one side of the spectrum we had the totally crazy Warner Bros. style, or the misshaped objects and expressionist perspectives of Maniac Mansion, Day of the Tentacle. On the other the more realistic looking Sunday strips, like Peanuts, or Calvin &amp; Hobbes, with suburban landscapes and mostly realistic depictions of everyday objects.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/01/maniacmansion.jpg" border="0" alt="" width="496" height="310" /></p>
<p>We talked for a bit about this; the first style would give us more freedom to introduce weird objects; anything from TNT to shrinking ray guns would feel at home. But it also would have complicated gameplay by introducing cartoon physics, and way more unpredictability for the player when things started squishing and stretching, etc.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/01/coyote.jpeg" border="0" alt="" width="259" height="194" /></p>
<p>So we decided for the later; objects could still be slightly deformed, lines didn&#8217;t need to be totally straight, but we were not getting too crazy. Something like this image from Calvin and Hobbes was my goal.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/01/calvin.jpg" border="0" alt="" width="301" height="305" /></p>
<p>Some advice for designers of any kind: <strong>the more you know about a project and what is expected of you, the better the result</strong>. Never start without enough information. If you are not sure about something, ask. Is not going to upset your client/partner that you show interest in their product. And all this going back and forth with Noel not only helped me create an appropriate theme for the game, it also helped him better define what he wanted to make.</p>
<h3>Casey</h3>
<p>This was my first try at a few game objects. At first I was just going to draw a few objects, but then decided to try sketching Casey too (at that time he didn&#8217;t even had a name).</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/01/Casey01.gif" border="0" alt="" width="480" height="350" /></p>
<p>The objects were solid (that soccer ball even appears in the final game almost untouched!), and the general style of colored outlines, flat colors, and simple shades was set. Casey didn&#8217;t feel right though. He looked too much like an anime character, and way too naive and lacking personality. I didn&#8217;t want a modern Japanese-style cartoon, but one more grounded in the 50s, the golden age of American animated cartoons.</p>
<p>After quite a few tries, I started getting into something I liked better, with more of a Hanna-Barbera style.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/01/Casey02.png" border="0" alt="" width="480" height="264" /><br />Notice my ridiculous annotations to remember how to draw it?</p>
<p>The more I draw him, the more of a personality it started to show. He was a hands-on smart geeky kid. And all those contraptions to get to cookie jars and pies had result in a bit of a belly.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/01/Casey03.png" border="0" alt="" width="480" height="800" />I reused the pencil from a previous sketch there. Don&#8217;t trash anything!<br />Spent some time deciding if I wanted 6 or 8 fingers too. Is that his mom?</p>
<h3>Fonts</h3>
<p>One of the first things I got into after the character design was deciding on fonts. You see, I love typography. The difference between using the default fonts or the freely available ones in any platform, and using professional fonts is like… well, like this.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/01/typography.gif" border="0" alt="" width="480" height="227" /><br /><strong>Arial</strong> to the left, <strong>Sqweash</strong> to the right. Difference? $20</p>
<p>Quality fonts are not expensive taking into account how much they influence the style of your game. You can find single-user licenses for as low as $20. Take into account that those licenses don&#8217;t allow you to include the font file as part of your binary, only to use it in textures or static images (yes, this includes texture atlases with all the glyphs at a certain size; but rendering non-monospaced fonts is not easy if you have to implement all the metrics from scratch). Although you should contact each foundry, you can assume a license to include a font in your binary and let UIFont render it for you, will be around 10 times as expensive as a normal one.</p>
<p>After choosing fonts, I worked a bit on a logo, then on the first drafts for a level selection screen. You will notice that all these pieces were of no relevance to getting content into the game itself. I attacked them first to build on the theme and get a better sense of where we were heading.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/01/logo.gif" border="0" alt="" width="480" height="235" />Don&#8217;t use fonts in your logo you use anywhere else, it cheapens it.</p>
<p>Every piece you add changes how you perceive the game, even if is not gameplay related, and every part has to pull in the same direction. Some people like to leave this for last, add it as the last layer of cream on the pie, because having final art too soon kills opportunities for experimentation. On the other side, having all these can strengthen your initial concept, let you discover what is important and focus on it.</p>
<h3>Location Screen</h3>
<p><a rel="lightbox" href="http://mysterycoconut.com/wp-content/uploads/2011/01/LocationScreen1big.png"><img class="alignleft" src="http://mysterycoconut.com/wp-content/uploads/2011/01/LocationScreen1.png" border="0" alt="" width="240" height="180" /></a>From the beginning we wanted levels separated into different locations. This was the first try at creating a level selection menu (click the screenshots to see them full size). You can see there is not much worth saving there: the colors are kind of depressing, and my first idea of having all the locations in the same screen scrolling vertically, with rows of levels that scrolled individually in the horizontal was pretty confusing.</p>
<p>I did like the outlined titles though, and the thumbnails with details of the levels, and you will see I maintained both in later designs.</p>
<p><a rel="lightbox" href="http://mysterycoconut.com/wp-content/uploads/2011/01/LocationScreen2big.png"><img class="alignright" src="http://mysterycoconut.com/wp-content/uploads/2011/01/LocationScreen2.png" border="0" alt="" width="240" height="180" /></a>Second try was more in line with the theme, with brighter colors. Each location got its own screen, and I decided to style them as a page in a sticker book that you complete as you solve the levels (in this screen all the stickers are the same piggy bank image just because I was lazy). You can see here we were already working on having stars representing degrees of success for each level. The blue info buttons didn&#8217;t pass the first beta tests: nobody ever understood they were actual 2 things you could touch, the center of the sticker to enter the level, and the &#8220;i&#8221; to get info about the level without entering. It was confusing cause of the overlapping hot-areas, but also because of something that has haunted me for the whole process: making interface elements stand on their own without blending with their surroundings. You will see more of this later.</p>
<p><a rel="lightbox" href="http://mysterycoconut.com/wp-content/uploads/2011/01/LevelInfoBig.png"><img class="alignleft" src="http://mysterycoconut.com/wp-content/uploads/2011/01/LevelInfo.png" border="0" alt="" width="240" height="180" /></a>This was the level info screen that the &#8220;i&#8221; button opened (it was supposed to be the back of the level stamp, and we were going to transition to it with a fancy animation from the previous screen). The plan was to have all this information about goals, how your friends had done in that level, and if they had shared any solutions, that you could check before loading the level itself.</p>
<p>When we got rid of the blue &#8220;i&#8221;, we had to put this info in different places inside the level itself. My assumption was that it was better to check all this info before deciding if you wanted to play the level, but tests showed that people just liked to see the level at full size, and since it opens instantly (no &#8220;loading&#8221; progress bars) and you can exit at any moment, there was no catch.</p>
<p>There are other interesting things in this screen I decided to reuse later: the white outlines that appear around different elements, the first use of a normal looking capsule button, the green background colors, the tape and shadows in the thumbnail pics… You can also see something we didn&#8217;t changed until way later: three different goals for each level, each giving different amounts of stars.</p>
<h3>Level Intro</h3>
<p><a rel="lightbox" href="http://mysterycoconut.com/wp-content/uploads/2011/01/LevelIntro1Big.png"><img class="alignleft" src="http://mysterycoconut.com/wp-content/uploads/2011/01/LevelIntro1.png" border="0" alt="" width="240" height="180" /></a>That simple thing, three goals per level, gave me lots of trouble. When you first start a level, you were supposed to get a short blurb by Casey of what to do, but also the level title, and what extra goals you can complete to get 2 and 3 stars. I hated this screen because it was so plain, so I tried to make it more interesting.</p>
<p style="clear: both;"><a rel="lightbox" href="http://mysterycoconut.com/wp-content/uploads/2011/01/LevelIntro2Big.png"><img class="alignright" src="http://mysterycoconut.com/wp-content/uploads/2011/01/LevelIntro2.png" border="0" alt="" width="240" height="180" /></a>To the right is one I particularly liked. But you see, I was trying to solve the wrong problem. I tried to add more stuff to it (the item rewarded for the sandbox if you finished the level, your current star rating…), and make elements bigger and more attractive. But people would either dismiss this screen as fast as possible so they could see the level, then wondered what they were supposed to do, or get confused about the multiple goals, or always try to go for the quite complicated 3-star goal without even considering the simpler ones.</p>
<p><a rel="lightbox" href="http://mysterycoconut.com/wp-content/uploads/2011/01/LevelIntro3Big.png"><img class="alignleft" src="http://mysterycoconut.com/wp-content/uploads/2011/01/LevelIntro3.png" border="0" alt="" width="240" height="180" /></a>What we needed here was not to get fancy, but being straightforward. To the left is the final iteration: title, goal, and you can see almost the whole level, without even the translucent yellow overlay.</p>
<p>That of course also pushed the two other goal descriptions some other place. We figured we could have a menu inside the level with a screen showing these, and that of course caused more trouble. But since this post is already running long, you will have to wait for part 2 to know how we solved that one :)</p>
<p>As always, feel free to ask any questions in the comments below or on Twitter!</p>
]]></content:encoded>
			<wfw:commentRss>http://mysterycoconut.com/blog/2011/01/designing-casey/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Space-Time! (Core Animation Games 2)</title>
		<link>http://mysterycoconut.com/blog/2011/01/cag2/</link>
		<comments>http://mysterycoconut.com/blog/2011/01/cag2/#comments</comments>
		<pubDate>Thu, 20 Jan 2011 00:49:29 +0000</pubDate>
		<dc:creator>Miguel A. Friginal</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Core Animation Games]]></category>
		<category><![CDATA[idevblogaday]]></category>

		<guid isPermaLink="false">http://mysterycoconut.com/?p=623</guid>
		<description><![CDATA[Following our exploration of Core Animation and its use in games, we dive into some peculiarities of a layer's coordinate system and the Media Timing Protocol.]]></description>
			<content:encoded><![CDATA[<p>Progress this week has been slow on most of my projects. <a href="http://twitter.com/noel_llopis">Noel</a> and I were working on <a href="http://mysterycoconut.com/blog/2011/01/cookies-2/#evilProject5">Casey</a>&#8216;s tutorial, then we started implementing more objects so we can create some more levels and start beta–testing. Sneak peek:</p>
<p><center>
<p class='imgCenter framed'><img src="http://mysterycoconut.com/wp-content/uploads/2011/01/caseyNewObjects.jpg" border="0" alt="" width="480" height="200" />Some of the new objects introduced this week.</p>
<p></center></p>
<p>I also finished the design of the &#8220;Goal Completed&#8221; screen! This is a big one for me, mainly because the damn thing has changed so many times during the life of the project I got like a dozen different designs archived! That may require its own post, but here is the final one (as of this week):</p>
<p><center>
<p class='imgCenter framed'><img src="http://mysterycoconut.com/wp-content/uploads/2011/01/LevelCompletedView.jpg" border="0" alt="" width="480" height="360" />Final(?) Level Completed Screen</p>
<p></center></p>
<p>Since obviously I am not involved in enough projects already, I decided to promote yet another Twitter community project: <a href="http://twitter.com/search?q=%23isketchaday">#iSketchADay</a> is an original idea by <a href="http://twitter.com/tearascal">Craig Sharpe</a> (the artistic half of <a href="http://retrodreamer.com/">Retro Dreamer</a>) to promote more doodling. Join with your own sketches on the Twittverse.</p>
<p><center>
<p class='imgCenter framed'><img src="http://mysterycoconut.com/wp-content/uploads/2011/01/LaraVsMom.png" alt="" width="425" height="600" /><br />My &#8220;DEMAND REAL CHARACTERS&#8221; campaign for #iSketchADay</p>
<p></center></p>
<p>I also continued working on <a href="http://mysterycoconut.com/blog/2011/01/cookies-2/#evilProject7">Evil Project #7</a>. After some more Twitter voting it even got a name: <strong>Elephant Run!</strong>. <a href="http://twitter.com/owengoss">Owen</a>&#8216;s suggestion, &#8220;Elephant Run: A Banana Bonanza&#8221; was my favorite by far.</p>
<p><span id="more-623"></span></p>
<h3>Head Over Heels</h3>
<p><img class="alignleft" src="http://mysterycoconut.com/wp-content/uploads/2011/01/headOverHeels2.gif" border="0" alt="" width="92" height="144" />In the few hours I could spend on this I got the elephant sprite to walk. You may think this was solved last week, but there was a little problem with the previous sprite: the head and the body were stuck together in the same graphic, making it impossible to swing the trunk in the direction of the bait while walking.</p>
<p style='clear:both'>After a few tweaks in Illustrator I ended up with this:</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/01/elephantAtlas.jpg" border="0" alt="" width="498" height="413" /></p>
<p>Now I just needed to position the trunk with respect to the body so the whole thing moved together. Since the body was already one of my sprite layers, the idea was to make the trunk a sublayer of it. That guarantees that moving the body would make the trunk follow. If only it had been that easy…</p>
<h3>Origin of Space</h3>
<p>Just a few lines later I had my first WTF.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/01/firstMoveError.gif" border="0" alt="" width="180" height="220" /></p>
<p>Let me explain you what&#8217;s going on there.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/01/firstMoveErrorExplanation.gif" border="0" alt="" width="180" height="230" /></p>
<p>My main problem was that each of the frames in my animation had a different size, so every frame the sprite <code>bounds</code> where changing (red rectangle). The <code>bounds</code> change with respect to the layer&#8217;s <code>position</code>, that by default is in the center (the point in the center of the red rectangle that doesn&#8217;t move).</p>
<p>Now, the easy way out of this was to just make all the frames the same size. But there are two things on this diagram I wanted to talk about first.</p>
<h4>How a layer&#8217;s content draws around its position</h4>
<p>The reason the <code>bounds</code> grow out from the center point is because of the layer&#8217;s <code>anchorPoint</code> property. You can <a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreAnimation_guide/Articles/Layers.html%23//apple_ref/doc/uid/TP40006082-SW9">check the docs here</a> for a long explanation of what the <code>anchorPoint</code> represents. But basically is a <code>CGPoint</code> in the range {0.0, 0.0}-{1.0, 1.0} that indicates where inside the <code>bounds</code> rectangle the layer&#8217;s <code >position</code> is. Or in this case the other way around, how the <code>bounds</code> (and the layer&#8217;s content) are drawn with respect to the <code>position</code> point. The default value is {0.5, 0.5}, and that&#8217;s the reason our red rectangle above grows a few pixels both on the top and the bottom when its size changes. If we change it, this is what will happen:</p>
<p class='imgCenter'><img style='display:inline' src="http://mysterycoconut.com/wp-content/uploads/2011/01/anchorPoint0500.gif" border="0" alt="" width="180" height="230" /><img style='display:inline' src="http://mysterycoconut.com/wp-content/uploads/2011/01/anchorPoint0510.gif" border="0" alt="" width="180" height="230" /><br />Anchor point at {0.5, 0} on the left with bounds growing down, {0.5, 1} on the right with bounds growing up.</p>
<p>As you can see neither option will help with our original problem; the one on the left creates a gap between the body and the trunk, and the one on the right inserts the trunk further than necessary into the body.</p>
<h4>How a layer is positioned with respect to its superlayer</h4>
<p>The question is, why the position vector of the trunk (the blue arrow) starts where it does? I was half expecting it to go from the body&#8217;s anchor point, to the trunk&#8217;s anchor point, but instead it starts in the upper left corner of the body&#8217;s <code>bounds</code>. Can we change that point, start in a more convenient place?</p>
<p>The answer is yes. This line in the documentation tip me off:</p>
<blockquote>
<p>The <code>bounds</code> property is a <code>CGRect</code> that provides the size of the layer (<code>bounds.size</code>) and the origin (<code>bounds.origin</code>). The bounds origin is used as the origin of the graphics context when you override a layer&#8217;s drawing methods</p>
</blockquote>
<p>As I show you last week when changing the <code>bounds</code> of the layer I was setting them like this:</p>
<div class="scgeshi-container"><div class="objc scgeshi">self.bounds <span class="sy0">=</span> CGRectMake<span class="br0">&#40;</span><span class="nu0">0</span>, <span class="nu0">0</span>, currentFrameWidth, currentFrameHeight<span class="br0">&#41;</span>;</div></div>
<p>If you change the <code>bounds.origin</code> the origin of coordinates for all its sublayers change to that point. For some reason, negative numbers (in points) move it right and down, so doing this…</p>
<div class="scgeshi-container"><div class="objc scgeshi">self.bounds <span class="sy0">=</span> CGRectMake<span class="br0">&#40;</span><span class="sy0">-</span>currentFrameWidth<span class="sy0">/</span><span class="nu0">2</span>, <span class="sy0">-</span>currentFrameHeight, currentFrameWidth, currentFrameHeight<span class="br0">&#41;</span>;</div></div>
<p>…and changing the anchor points for the head to waggle, finally got me here:</p>
<p style="text-align: center;"><img src="http://mysterycoconut.com/wp-content/uploads/2011/01/boundsOriginChanged.gif" border="0" alt="" width="180" height="230" /></p>
<h3>Origin of Time</h3>
<p>After that I decided to embark in another easy one: have different speeds for your elephant. I am going for just 3 speeds in the game, slow, normal, and fast, plus completely stopped (with some idle animation). For now I was just going to run the animation I have at different speeds (later on I will probably create different images for each, so I can give a bit more personality to running like crazy vs trotting vs pacing around).</p>
<p>Both <code>CALayer</code> and <code>CAAnimation</code> objects depend on the Media Timing Protocol for time related tasks. You can set duration for your animations, how many times they repeat, or if they autoreverse through properties in this protocol, and yes, there is even a <code>speed</code> property.</p>
<p>The thing is, as with the spatial properties the time properties are also organized hierarchically. This means that changing the <code>speed</code> of the elephant&#8217;s body would also change the speed of any other animations applied to its sublayers. Say we set the body&#8217;s animation <code>speed</code> to 2; animations applied to the trunk will proceed now at double the frame rate! Even worse, if we set the <code>speed</code> to 0, the trunk will not be able to move at all. I could apply the inverse speed to all the layer&#8217;s children, but since we will eventually end with the rider, bananas in the baskets, bait, and who knows what else, that can get messy fast.</p>
<p>So the plan was to create a new animation each time there was a speed change; same parameters except for the <code>duration</code>, that would depend on the required speed.</p>
<p>A couple minutes later I had my second WTF.</p>
<p class='imgCenter'><img src="http://mysterycoconut.com/wp-content/uploads/2011/01/secondMoveError.gif" border="0" alt="secondMoveError.gif" width="180" height="220" /></p>
<p>This time the problem was that recreating the animation was resetting it, so each time I changed speeds it started from the first frame, instead of continuing along with whatever frame was next. Note also that at the moment the animation stops, we only know what frame we are in (through our <code>sampleIndex</code> property), but not if we were going towards the next frame or towards the previous.</p>
<h4 style="margin-bottom: 0;">How long since the animation started?</h4>
<p>There are 2 properties in the Media Timing Protocol that allow us to start an animation not from the beginning, but some time into it: <code>beginTime</code> and <code>timeOffset</code>. The main difference between them is that the first one is scaled to the timespace of the animation&#8217;s layer, and the second one is not. What does that mean? Remember our animation is part of that time hierarchy created by the differences between the layers&#8217; speeds. 4 seconds in <code>beginTime</code> applied to a layer with <code>speed</code> 2 is equal to 2 seconds in <code>timeOffset</code>.</p>
<p>What I needed to do was:</p>
<ol>
<li>Calculate how long the animation had been running by substracting the current time from the time when it started (dt).</li>
<li>Create the new animation with the new duration.</li>
<li>Set <code>beginTime </code>so the new animation starts in the same relative point (dt * newDuration / previousDuration).</li>
</ol>
<p>So how do I know when the animation started without keeping track of it on my own. A non-documented fact about the <code>beginTime</code> property is that <strong>if you don&#8217;t set it to something different, it is internally populated with the animation start time timestamp</strong>.</p>
<p>Remember though that <code>beginTime</code> is scaled by the time hierarchy, so some transformation is required. At least the Media Timing Protocol gives us methods to do this; by passing nil as the 2nd parameter to <code>convertTime:fromLayer:</code> and <code>convertTime:toLayer:</code> you can convert to and from the layer&#8217;s timeframe to the standard one.</p>
<div class="scgeshi-container"><div class="objc scgeshi"><span class="co2">// Setting up my basic animation; all properties are the same each time...</span><br />
CABasicAnimation <span class="sy0">*</span>anim <span class="sy0">=</span> <span class="br0">&#91;</span>CABasicAnimation animationWithKeyPath<span class="sy0">:</span><span class="co3">@</span><span class="st0">&quot;sampleIndex&quot;</span><span class="br0">&#93;</span>;<br />
anim.autoreverses <span class="sy0">=</span> <span class="kw2">YES</span>;<br />
anim.repeatCount <span class="sy0">=</span> MAXFLOAT;<br />
anim.fromValue <span class="sy0">=</span> <span class="br0">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/"><span class="kw5">NSNumber</span></a> numberWithInt<span class="sy0">:</span><span class="nu0">1</span><span class="br0">&#93;</span>;<br />
anim.toValue <span class="sy0">=</span> <span class="br0">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/"><span class="kw5">NSNumber</span></a> numberWithInt<span class="sy0">:</span><span class="nu0">6</span><span class="br0">&#93;</span>;<br />
<span class="co2">//...except duration</span><br />
anim.duration <span class="sy0">=</span> newDuration;<br />
<br />
<span class="co2">// This animation was already running, so let's grab it; notice is read-only</span><br />
CAAnimation <span class="sy0">*</span>prevAnim <span class="sy0">=</span> <span class="br0">&#91;</span>self animationForKey<span class="sy0">:</span><span class="co3">@</span><span class="st0">&quot;bodyMovement&quot;</span><span class="br0">&#93;</span>;<br />
CFTimeInterval prevStart <span class="sy0">=</span> <span class="br0">&#91;</span>self convertTime<span class="sy0">:</span>prevAnim.beginTime toLayer<span class="sy0">:</span><span class="kw2">nil</span><span class="br0">&#93;</span>; <span class="co2">// transform into real time</span><br />
CFTimeInterval dt <span class="sy0">=</span> CACurrentMediaTime<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy0">-</span> prevStart <span class="sy0">-</span> prevAnim.timeOffset; <span class="co2">// standard time</span></div></div>
<p>Notice we also subtract the <code>timeOffset</code> from the starting time (without converting, since <code>timeOffset</code> is not scaled). If the offset is used, it needs to be taken into account.</p>
<p>Finally we can set the new animation <code>beginTime</code>, making sure to set it to a timestamp for the code above to continue working:</p>
<div class="scgeshi-container"><div class="objc scgeshi">CFTimeInterval prevDuration <span class="sy0">=</span> prevAnim.duration;<br />
CFTimeInterval newDt <span class="sy0">=</span> <span class="br0">&#40;</span>newDuration<span class="sy0">/</span>prevDuration<span class="br0">&#41;</span><span class="sy0">*</span>dt;<br />
<br />
<span class="co2">// Set beginTime (layer time)</span><br />
anim.beginTime <span class="sy0">=</span> <span class="br0">&#91;</span>self convertTime<span class="sy0">:</span>CACurrentMediaTime<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-</span>newDt fromLayer<span class="sy0">:</span><span class="kw2">nil</span><span class="br0">&#93;</span>;<br />
<br />
<span class="br0">&#91;</span>self addAnimation<span class="sy0">:</span>anim forKey<span class="sy0">:</span><span class="co3">@</span><span class="st0">&quot;bodyMovement&quot;</span><span class="br0">&#93;</span>;</div></div>
<p>As I said at the beginning not much progress overall, but at least it helped me understand a bit better how everything works together. Hope it is helpful to you too!</p>
]]></content:encoded>
			<wfw:commentRss>http://mysterycoconut.com/blog/2011/01/cag2/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 1.453 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-01-29 19:59:25 -->
<!-- Compression = gzip -->
