<?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>Interactive Pulp Blog &#187; Announcements</title>
	<atom:link href="http://www.interactivepulp.com/blog/category/announcements/feed" rel="self" type="application/rss+xml" />
	<link>http://www.interactivepulp.com/blog</link>
	<description>Game Design and Interactive Pulp announcements</description>
	<lastBuildDate>Thu, 03 Dec 2009 04:11:13 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Experiences porting iPhone apps to Android</title>
		<link>http://www.interactivepulp.com/blog/2009/12/experiences-porting-iphone-apps-to-android</link>
		<comments>http://www.interactivepulp.com/blog/2009/12/experiences-porting-iphone-apps-to-android#comments</comments>
		<pubDate>Thu, 03 Dec 2009 04:07:13 +0000</pubDate>
		<dc:creator>David Brackeen</dc:creator>
				<category><![CDATA[Announcements]]></category>

		<guid isPermaLink="false">http://www.interactivepulp.com/blog/?p=27</guid>
		<description><![CDATA[This year I had the oppurtunity to port two iPhone apps to Android. One was a game, another a communication app. I wanted to share some of the gritty details while they&#8217;ve been bouncing around my head.
With respect to my clients (well actually it&#8217;s because of those crazy NDAs), for the purposes of this blog, [...]]]></description>
			<content:encoded><![CDATA[<p>This year I had the oppurtunity to port two iPhone apps to Android. One was a game, another a communication app. I wanted to share some of the gritty details while they&#8217;ve been bouncing around my head.</p>
<p>With respect to my clients (well actually it&#8217;s because of those crazy NDAs), for the purposes of this blog, I&#8217;ll call the two apps I ported &#8220;the Game App&#8221; and &#8220;the Chat App&#8221;. Also, I mention some code below, but unfortunately I can&#8217;t share that either.</p>
<p>In the (near) future, there may be none of this &#8220;porting&#8221; nonsense &#8211; maybe we&#8217;ll all be building apps using cross-platform APIs like <a href="http://phonegap.com/">PhoneGap</a> or <a href="http://labs.adobe.com/technologies/flashcs5/appsfor_iphone/">Flash CS5</a>. But in the case of these two apps, they were already written in Objective-C, and they needed to be converted to run on Android. So I got to work.</p>
<p>In some cases, Objective-C can be directly translated to Java, while in other cases new Java code has to be written from scratch. Things like string manipulation, XML handling and SQLite interfaces aren&#8217;t that different on the two platforms. However things like UI code can be incredibly different.</p>
<h3>UI layout</h3>
<p>Neither of the two iPhone apps I ported used Interface Builder.</p>
<p>The Game App used UIViews (mostly UIImageViews) and CoreAnimation. This is an acceptable choice for a simple 2D game. So, for the port, I thought I&#8217;d also use Android&#8217;s UI scene graph and animation framework. I was able to do it, but it required a lot of supporting classes for layout and animation, and in the end, it proved to be more difficult than it was worth. It would have been faster to write a custom scene graph. Here are some of the issues:</p>
<ol>
<li>Creating a custom Layout. Android requires Layouts for placing Views, and there was no existing Layout that could place a View based on a position and an anchor (the iPhone version made heavy use of anchorPoints for placement).</li>
<li>Creating custom Animation classes. By default, the animation framework couldn&#8217;t do the type of key-frame animation that CoreAnimation can do (it took a while just to figure that out). I ended up having to create my own Animation class (and subclass AnimationSet) to get it right. This took a long time to figure out because it was a trial-and-error process. Unfortunately, for this app, Android has much longer build times than iPhone, which greatly impacts any trial-and-error process (on my machine, 20 seconds from hitting the &#8220;build&#8221; button to getting it to run on the emulator, vs. 2-4 seconds for the iPhone version).</li>
</ol>
<p>The Chat App was more straightforward, but I needed to use RelativeLayouts on Android, and it was a bit difficult to create a RelativeLayout that matched the absolute positioning on the iPhone. The biggest problem was one of the relative layouts was considered recursive: I was laying out a view group from the bottom up, where the final dimension of the view group was defined by its contents. This was solved by determining the dimension of the view group using trial-and-error at runtime.</p>
<p>The other minor problem with the Chat App was that the iPhone version did some long-running networking in the UI thread. This isn&#8217;t the best practice, but it isn&#8217;t a problem on iPhone if you don&#8217;t have any usable UI controls on the screen at the time (there was just a spinning activity indicator). However, this is a big no-no on Android, which interrupts the user with a dialog asking the user to &#8220;Force Close&#8221; the app or &#8220;Wait&#8221;. (You could say iPhone has a physical &#8220;Force Close&#8221; button &#8211; the Home button. On Android the Home button doesn&#8217;t force close the running app). Luckily, using Android&#8217;s AsyncTask was an easy fix.</p>
<p>Another problem with the Chat App was with contact picking. Unfortunately, the old Contacts API was deprecated in Android 2.0. It still works, but on Android 2.0, the returned values are different from the Android 1.5 version, which required some extra code to fix. Also, at least one device (Motorola CLIQ) has a <a href="http://groups.google.com/group/android-developers/browse_thread/thread/fbf68132d50eca11#">custom built contact picker which gives the user an error dialog every time it runs</a> (to be fair, this is supposed to be fixed in an upcoming OTA release).</p>
<h3>The little things</h3>
<p>One thing to keep in mind is Android&#8217;s lack of a JIT and it&#8217;s slow garbage collection. Eventually this will be fixed, but that fact, and the fact that most Android devices&#8217; hardware is slower than the iPhone, makes the experience of these two apps not as smooth on Android.</p>
<p>One strange problem is that many (or all?) Android devices use 16-bit color. Even on the Droid, which is advertised to have a 24-bit color depth, shows obvious color banding when I displayed a gradient that looked fine on the iPhone. (Apple doesn&#8217;t say what the color depth of the iPhone is, but based on how that gradient appeared, I&#8217;m guessing it&#8217;s 24-bit).</p>
<p>This is a bit off-topic for a moment, but one of the weirdest things about both platforms is launching the email client. Compare iPhone:</p>
<pre>NSString* subject = NSLocalizedString(@"Subject", nil);
NSString* body = NSLocalizedString(@"Body", nil);
NSString* encodedSubject = [subject stringByAddingPercentEscapesUsingEncoding: NSASCIIStringEncoding];
NSString* encodedBody = [body stringByAddingPercentEscapesUsingEncoding: NSASCIIStringEncoding];
NSString* url = [NSString stringWithFormat: @"mailto:?subject=%@&amp;body=%@", encodedSubject, encodedBody];
[[UIApplication sharedApplication] openURL: [NSURL URLWithString: url]];</pre>
<p>To Android:</p>
<pre>String subject = getString(R.string.subject);
String body = getString(R.string.body);
Intent mail = new Intent(Intent.ACTION_SEND);
mail.setType("text/plain");
mail.putExtra(Intent.EXTRA_TEXT, body);
mail.putExtra(Intent.EXTRA_SUBJECT, subject);
Intent chooser = Intent.createChooser(mail, getString(R.string.email_description));
startActivity(chooser);</pre>
<p>Both are awkward, wouldn&#8217;t you say? Why not something like this?</p>
<pre>String to = "";
String subject = getString(R.string.subject);
String body = getString(R.string.body);
context.email(to, subject, body);</pre>
<h3>Distribution</h3>
<p>Obviously the Android Market wins in terms of time-to-release. Fifteen minutes and you&#8217;re done &#8211; no two-week review, no fear of rejection. But there was a couple oddities to deal with.</p>
<p>The Game App had both Full and Lite versions of the game. On the iPhone, both versions used the same codebase, and a few preprocessor conditionals determined which code to execute for each version. Java has no preprocessor conditionals, and also, the Android Market requires that each app have a unique package name. This posed a problem since it would be wise for the two versions to share the same codebase on Android, too. (Creating two projects meant maintaining two codebases!) The problem was exasperated by the fact that Android references image resources by package name, too.</p>
<p>What I did is write a script that programatically copied the project and changed the package name along the way. Everywhere in the manifest, Eclipse project files, and every source file was changed. A single source file named Build.java had a boolean static field named LITE which was programmatically changed as well. The script worked surprisingly well.</p>
<p>Also, the Full version was accidentally marked as &#8220;free&#8221;. We pulled it, but we couldn&#8217;t convert it to a paid app, and we couldn&#8217;t re-upload because the package name was already in use. Support to Google didn&#8217;t help. We ended up using the package-name script again to create a new Full version that we could upload and make a paid app.</p>
<h3>Closing thoughts</h3>
<p>If you&#8217;re looking to port an iPhone app to Android, it might be a good idea to do some code cleanup first. It&#8217;s important to keep the model code clearly separated from the view code. Porting model code, which involves more direct translation rather than re-write, is a lot easier if it&#8217;s not mixed in with the views.</p>
<p>Also, watch out when searching for Android example code. I ran into a few examples that use old, pre-1.0 code that doesn&#8217;t even compile anymore.</p>
<p>All in all, it&#8217;s has been a strange ride. I kind of feel like porting these two apps gave me some new skills that will be obsolete soon, but we&#8217;ll see. At least, if I have to do it again, I&#8217;ve got a few tricks up my sleeve to make it a bit easier.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.interactivepulp.com/blog/2009/12/experiences-porting-iphone-apps-to-android/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>In Helvetica (where available)</title>
		<link>http://www.interactivepulp.com/blog/2007/06/in-helvetica-where-available</link>
		<comments>http://www.interactivepulp.com/blog/2007/06/in-helvetica-where-available#comments</comments>
		<pubDate>Fri, 29 Jun 2007 10:26:16 +0000</pubDate>
		<dc:creator>David Brackeen</dc:creator>
				<category><![CDATA[Announcements]]></category>

		<guid isPermaLink="false">http://www.interactivepulp.com/blog/2007/06/in-helvetica-where-available</guid>
		<description><![CDATA[Just a quick note to mention the new web design here at interactivepulp.com. A lot of stuff was added in the last three months (like pulpgames.net, this blog, and PulpCore) and the site needed a refresh to reflect it.
On a completely different topic, I&#8217;m seeing quite a bit of searches like &#8220;Milpa tips&#8221; and &#8220;Milpa [...]]]></description>
			<content:encoded><![CDATA[<p>Just a quick note to mention the new web design here at interactivepulp.com. A lot of stuff was added in the last three months (like pulpgames.net, this blog, and PulpCore) and the site needed a refresh to reflect it.</p>
<p>On a completely different topic, I&#8217;m seeing quite a bit of searches like &#8220;Milpa tips&#8221; and &#8220;Milpa hints&#8221; showing up in the server logs. So there is a thirst out there &#8211; any Milpa experts out there wanna share their skillz? After all, you all are better at the game than I am. <img src='http://www.interactivepulp.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Write a blog about it and I&#8217;ll link to it!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.interactivepulp.com/blog/2007/06/in-helvetica-where-available/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ridiculously high scores? No problem!</title>
		<link>http://www.interactivepulp.com/blog/2007/05/ridiculously-high-scores-no-problem</link>
		<comments>http://www.interactivepulp.com/blog/2007/05/ridiculously-high-scores-no-problem#comments</comments>
		<pubDate>Sun, 13 May 2007 23:59:32 +0000</pubDate>
		<dc:creator>David Brackeen</dc:creator>
				<category><![CDATA[Announcements]]></category>
		<category><![CDATA[Game Design]]></category>

		<guid isPermaLink="false">http://www.interactivepulp.com/blog/2007/05/ridiculously-high-scores-no-problem</guid>
		<description><![CDATA[Two things became apparent after I added high scores to Milpa: first, people are doing exceptionally well at the game. Second, the game is easy to hack. Check out those scores:

Several people were getting higher than Year 30, doubling my personal high score. I didn&#8217;t expect anyone to get that far. So, hey, you guys [...]]]></description>
			<content:encoded><![CDATA[<p>Two things became apparent after I added high scores to <a href="http://www.pulpgames.net/milpa/">Milpa</a>: first, people are doing exceptionally well at the game. Second, the game is easy to hack. Check out those scores:</p>
<p><img src="http://www.interactivepulp.com/blog/index.php?feedimage=wp-content/uploads/2007/05/alltime.png" alt="All Time" /></p>
<p>Several people were getting higher than Year 30, doubling my personal high score. I didn&#8217;t expect anyone to get that far. So, hey, you guys are awesome.</p>
<p>Second, the game scores are totally hackable. Year 88? No way. I took the precaution of encrypting scores before they are sent to the server, but that doesn&#8217;t stop something I knew nothing about: easy-to-use tools that can modify game memory during runtime. These tools allow you to find where a score is stored in memory and edit its value.  One of these tools is called Cheat Engine.</p>
<p><img src="http://www.interactivepulp.com/blog/index.php?feedimage=wp-content/uploads/2007/05/cheatengine.png" alt="Cheat Engine screenshot" /></p>
<p>There was a recent <a href="http://digg.com/software/Hack_Flash_Games">Digg article about hacking games</a> where many of these tools were mentioned in the comments. People generally seemed enthusiastic about sharing different ways to cheat.</p>
<p>I downloaded Cheat Engine and within 5 minutes hacked Milpa. Watching the score jump from 1,000 to 100,000 felt like I had just won the lottery. It gives a sense of accomplishment, and a chance to show off to others. In a sense, it&#8217;s like playing a whole other game with a new set of rules and your own goals. So I can see why people do it.</p>
<p>I thought about leaving the hacked scores in and just watching to see what happens, but ultimately, that is not fair to the people who legitimately make high scores. So I did a couple things.</p>
<p>First, I made the game more difficult after Year 13. People getting to Year 36 is great, but at that point the game becomes a test of endurance rather than skill &#8211; playing one game must take longer than an hour, which is not at all what I intended. Because of this change, I deleted all  scores higher than Year 13 so that all high scores represent the same difficulty level.</p>
<p>Second, the game now encrypts in-game memory. The game is still hackable, and always will be as long as the game logic exists on the client, but now hacking a score in the same manner won&#8217;t be possible. So if you want to hack, you&#8217;ve got a whole new set of rules to deal with. <img src='http://www.interactivepulp.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Refresh the page to get the latest version of Milpa, and click the <em style="font-family: serif">i</em> button to make sure you&#8217;ve got version 1.2.1.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.interactivepulp.com/blog/2007/05/ridiculously-high-scores-no-problem/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Global high scores for Milpa</title>
		<link>http://www.interactivepulp.com/blog/2007/05/new-global-high-scores-for-milpa</link>
		<comments>http://www.interactivepulp.com/blog/2007/05/new-global-high-scores-for-milpa#comments</comments>
		<pubDate>Fri, 04 May 2007 09:17:38 +0000</pubDate>
		<dc:creator>David Brackeen</dc:creator>
				<category><![CDATA[Announcements]]></category>

		<guid isPermaLink="false">http://www.interactivepulp.com/blog/2007/05/new-global-high-scores-for-milpa</guid>
		<description><![CDATA[Milpa now has global high scores!

There are three lists: personal, recent, and all-time. The personal list shows the scores made on your computer. The recent list shows the top scores in the last 24 hours (although that duration will probably change), and the all-time list shows, well, the best scores ever. Enjoy!
]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.interactivepulp.com/blog/2007/04/hello-world#comment-2"></a><a href="http://www.pulpgames.net/milpa/">Milpa</a> now has global high scores!</p>
<p><img src="http://www.interactivepulp.com/blog/index.php?feedimage=wp-content/uploads/2007/05/screenshot_1.png" alt="Milpa Scores" /></p>
<p>There are three lists: personal, recent, and all-time. The <strong>personal</strong> list shows the scores made on your computer. The <strong>recent</strong> list shows the top scores in the last 24 hours (although that duration will probably change), and the <strong>all-time</strong> list shows, well, the best scores ever. Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.interactivepulp.com/blog/2007/05/new-global-high-scores-for-milpa/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hello world</title>
		<link>http://www.interactivepulp.com/blog/2007/04/hello-world</link>
		<comments>http://www.interactivepulp.com/blog/2007/04/hello-world#comments</comments>
		<pubDate>Mon, 16 Apr 2007 06:20:00 +0000</pubDate>
		<dc:creator>David Brackeen</dc:creator>
				<category><![CDATA[Announcements]]></category>

		<guid isPermaLink="false">http://www.interactivepulp.com/blog/announcements/hello-world</guid>
		<description><![CDATA[A blog. Having a blog sounds like a better idea than creating a new page for this or that every time I want to mention this or that. So here we go, a blog.
This blog will most likely discuss things such as game programming, game design, interaction design, usability, and of course, occasional announcements for [...]]]></description>
			<content:encoded><![CDATA[<p>A blog. Having a blog sounds like a better idea than creating a new page for this or that every time I want to mention this or that. So here we go, a blog.</p>
<p>This blog will most likely discuss things such as game programming, game design, interaction design, usability, and of course, occasional announcements for <a href="http://www.pulpgames.net/">Pulp Games</a>. Random personal topics (like coffee preference based on country of origin) will most likely be kept to a minimum.</p>
<p>As for you, the reader, I&#8217;d like to hear from you lots of creative ideas and constructive criticism that would help make Pulp Games better. The games will be updated based on user feedback, so if you have something to say, this is the place to say it!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.interactivepulp.com/blog/2007/04/hello-world/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
