<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" gd:etag="W/&quot;D0AFRn84cCp7ImA9WhRUFEk.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195</id><updated>2012-01-24T23:55:17.138+01:00</updated><category term="weather" /><category term="xml" /><category term="activity" /><category term="korea" /><category term="level" /><category term="refactoring" /><category term="adt" /><category term="process" /><category term="development" /><category term="blender" /><category term="galicia" /><category term="memory" /><category term="otempo" /><category term="website" /><category term="game" /><category term="service" /><category term="state" /><category term="meteogalicia" /><category term="density" /><category term="gpl" /><category term="android" /><category term="2D" /><category term="rss" /><category term="admob" /><category term="outage" /><category term="optimization" /><category term="market" /><category term="trailer" /><category term="design" /><category term="egg savior" /><category term="background" /><category term="performance" /><category term="tater hater" /><category term="wrap-content" /><category term="fail" /><category term="menu" /><category term="open-source" /><category term="merge" /><title>The organic android</title><subtitle type="html">The journey of a programmer into the android world.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://organicandroid.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>51</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/organic_android" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="organic_android" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CkMMQHszeip7ImA9WhZRF00.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-3153577547281932410</id><published>2011-04-13T15:14:00.000+02:00</published><updated>2011-04-13T15:14:41.582+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-13T15:14:41.582+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="merge" /><title>Merged permanently</title><content type="html">This blog, along with other blogs maintained by me, have been merged into this new generic blog:&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: center;"&gt;&lt;a href="http://rubenlopezg.wordpress.com/"&gt;http://rubenlopezg.wordpress.com&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: left;"&gt;All posts and comments should have been merged correctly, if not, drop me a comment.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-3153577547281932410?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2011/04/merged-permanently.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/3153577547281932410?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/3153577547281932410?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2011/04/merged-permanently.html" title="Merged permanently" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CEYDR34ycCp7ImA9WhZSE0Q.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-87012819913342317</id><published>2011-03-29T11:49:00.000+02:00</published><updated>2011-03-29T11:49:36.098+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-29T11:49:36.098+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="tater hater" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><title>Tater Hater, you have to try it!</title><content type="html">&lt;div class="separator" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em; text-align: center;"&gt;&lt;a href="http://tater-hater.com/"&gt;&lt;img border="0" height="200" src="http://1.bp.blogspot.com/-41tyNfmaZiU/TZGqdrCLYGI/AAAAAAAAAYU/sW_ZspNajf4/s200/taterHater.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Some time ago, I wrote an article about &lt;a href="http://organicandroid.blogspot.com/2010/12/totalfree-memory-on-android-apps-and.html"&gt;memory management&lt;/a&gt; in Android that was the result of some research with my friend &lt;a href="http://www.estudio256.com/"&gt;Sergio&lt;/a&gt; about his own game. Now he has ended the first version of this game:&amp;nbsp;&lt;a href="http://tater-hater.com/"&gt;Tater Hater&lt;/a&gt;, which you can download from the Android Market. But remember to try first the Lite version and give him some feedback before purchasing the great complete version.&lt;br /&gt;
&lt;br /&gt;
Here you have the links to the android market web site:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="https://market.android.com/details?id=com.TaterHaterLite&amp;amp;feature=search_result"&gt;Tater Hater Lite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://market.android.com/details?id=com.TaterHater&amp;amp;feature=search_result"&gt;Tater Hater&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
I wish Sergio the best of luck with this new Android project, and I wish you to have lots of fun with his game.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-87012819913342317?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2011/03/tater-hater-you-have-to-try-it.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/87012819913342317?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/87012819913342317?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2011/03/tater-hater-you-have-to-try-it.html" title="Tater Hater, you have to try it!" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-41tyNfmaZiU/TZGqdrCLYGI/AAAAAAAAAYU/sW_ZspNajf4/s72-c/taterHater.png" height="72" width="72" /><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;D0cHR3czeSp7ImA9WhZTGUg.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-8374878224460670460</id><published>2011-03-22T22:54:00.001+01:00</published><updated>2011-03-24T09:23:56.981+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-24T09:23:56.981+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="open-source" /><category scheme="http://www.blogger.com/atom/ns#" term="otempo" /><title>OTempo is now open-source</title><content type="html">&lt;div class="separator" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em; text-align: center;"&gt;&lt;img border="0" src="https://lh3.googleusercontent.com/-ufdyJDWq0Mc/TD9P5yOADMI/AAAAAAAAATs/s9oClY2CdIo/s1600/iconosvg_web.png" /&gt;&lt;/div&gt;After a long time of learning stuff about the android ecosystem, I have finally decided to go open-source, and even remove advertisement from OTempo in the source code. This has several implications:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;You can now contribute to this project if you have some programming or artistic skills.&lt;/li&gt;
&lt;li&gt;I will continue to publish new versions of OTempo in the market, completely free of Ads, as significant changes happen in the source code.&lt;/li&gt;
&lt;li&gt;Yes, the next version of OTempo in the market will be completely free of Ads.&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;You can check the google code page for the open-source project here:&lt;/div&gt;&lt;br /&gt;
&lt;a href="http://code.google.com/p/otempo/"&gt;http://code.google.com/p/otempo/&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
If you want to contribute to this project, download the code, play a bit with it, and when you feel confident to make some improvements, either send me a patch or ask me for write permission in the SVN repo.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-8374878224460670460?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2011/03/otempo-is-now-open-source.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/8374878224460670460?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/8374878224460670460?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2011/03/otempo-is-now-open-source.html" title="OTempo is now open-source" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/-ufdyJDWq0Mc/TD9P5yOADMI/AAAAAAAAATs/s9oClY2CdIo/s72-c/iconosvg_web.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CUYNRHo_fip7ImA9Wx9bF0k.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-1320404896526498720</id><published>2011-02-26T18:55:00.001+01:00</published><updated>2011-02-26T18:59:55.446+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-26T18:59:55.446+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="performance" /><category scheme="http://www.blogger.com/atom/ns#" term="level" /><category scheme="http://www.blogger.com/atom/ns#" term="egg savior" /><category scheme="http://www.blogger.com/atom/ns#" term="game" /><title>Baking game levels in Egg Savior</title><content type="html">This article covers the way &lt;a href="http://www.eggsavior.com/"&gt;Egg Savior&lt;/a&gt; handles the rendering of static objects in order to save both CPU and APK size. The method presented is implemented into the last version of Egg Savior and is working really well, given the limited size of game levels.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;The problem&lt;/h3&gt;Egg Savior currently has 30 levels. Each one of these levels include a generic background and a lot of bricks that act as platforms for the main character (the chicken). The bricks are all 64x64 pixels in size, and placed in a grid. The obvious yet inefficient way of rendering and interacting with bricks is to handle all of them one by one:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: java"&gt;for brick in brick_list:
&amp;nbsp;&amp;nbsp;&amp;nbsp; brick.render()
&amp;nbsp;&amp;nbsp;&amp;nbsp; character.detect_collision(brick)
&lt;/pre&gt;&lt;br /&gt;
This code is inefficient for two reasons:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Renders the same bricks in the same way all the time, one by one.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Forces to detect collisions with every single brick, even if they are stuck together creating a larget platform&lt;/li&gt;
&lt;/ol&gt;The bricks are static, they don't change during the gameplay. For this reason, it would be faster to render them just once into an intermediate buffer, and then just render this buffer on each frame. This saves a lot of CPU time at the expense of more memory usage. If you have huge levels it may not be a good solution, because devices limit the amount of memory granted to each application to a quite small value. For Egg Savior this worked very well, because the size of levels is somehow limited.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Different backgrounds&lt;br /&gt;
&lt;/h3&gt;The first version of Egg Savior had only 10 levels, and the approach was to have a different background image for each level, with the bricks already included into it. It worked really well, but as more levels were added, it proved not very scalable, because each new level added a lot of data to the APK. This approach meant brick objects to be just invisible rectangles, without render code, because they were already drawn into the background. This enabled a way to optimize also point 2, because there were no reason for defining each brick individually. If three bricks were stuck together in a row, they were defined as a single larger brick, thus enabling less time to process collisions.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Run-time baking&lt;/h3&gt;The second iteration of the design, focused on solving the scalability problem with an algorithm that allowed baking the bricks above the background when loading a level. This also involved a way to easily define where to place the bricks. The solution was to use strings with spaces on empty cells and hashes on brick cells:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: java"&gt;String levelPattern[] = {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ",
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ",
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; "#&amp;nbsp;&amp;nbsp; #&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ",
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; "##&amp;nbsp; # #&amp;nbsp;&amp;nbsp;&amp;nbsp; ",
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;nbsp;&amp;nbsp; ## # #&amp;nbsp; ",
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; "## ## # # #",
};&lt;/pre&gt;&lt;br /&gt;
With this language to define brick positions, we already know where to place the bricks on the background. Anyway, there is still a problem to solve: brick shape change depending on its neighbours. If a brick is the first or the last in a row, it has round corners, in other case, it has sharp corners in order to blend with the next or previous one. This leaves us with four cases to handle, depending on the previous, current, and next brick (the current brick is in the middle):&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;&lt;tt&gt;[_#_]&lt;/tt&gt;: The brick doesn't have neighbours.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;tt&gt;[##_]&lt;/tt&gt;: The brick has&amp;nbsp;only&amp;nbsp;a neighbour on the left.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;tt&gt;[_##]&lt;/tt&gt;: The brick has&amp;nbsp;only&amp;nbsp;a neighbour on the right.&lt;/li&gt;
&lt;li&gt;&lt;tt&gt;[###]&lt;/tt&gt;: The brick has neighbours on both sides.&lt;/li&gt;
&lt;/ol&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img border="0" src="https://lh5.googleusercontent.com/-wRbs9IlqB-A/TWk4UozBdOI/AAAAAAAAAYE/zq3q3qvlCcc/s1600/bricks_contrast.png" /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Four brick shapes with enhanced contrast.&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;
The algorithm to generate the background with the tiles is as follows (I removed some obvious code to compute drawBitmap rectangles to enhance algorithm readability):&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: java"&gt;public static Bitmap bake(String[] rows, Bitmap baseBackground) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; int nRows = rows.length;
&amp;nbsp;&amp;nbsp; &amp;nbsp;int nCols = rows[0].length();
&amp;nbsp;&amp;nbsp; &amp;nbsp;Bitmap newBitmap = Bitmap.createBitmap(nCols * TILE_SIDE, nRows * TILE_SIDE, Bitmap.Config.ARGB_8888);
&amp;nbsp;&amp;nbsp;&amp;nbsp; Canvas canvas = new Canvas(newBitmap);
&amp;nbsp;&amp;nbsp;&amp;nbsp; canvas.drawBitmap(baseBackground, null, ..., null);
&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int row = 0; row &amp;lt; nRows; row++) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; for (int col = 0; col &amp;lt; nCols; col++) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; char left = '#';
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; char right = '#';
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (col &amp;gt; 0) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; left = rows[row].charAt(col-1);
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (col &amp;lt; nCols - 1) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; right = rows[row].charAt(col+1);
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; char c = rows[row].charAt(col);
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Bitmap toRender = getTile(left, c, right);
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (toRender != null)
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; canvas.drawBitmap(toRender, null, ..., null);
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; return newBitmap;
} &lt;/pre&gt;&lt;br /&gt;
The &lt;span style="font-weight: bold;"&gt;getTile&lt;/span&gt; method just handles the four cases mentioned earlier, and returns the right bitmap from the app resources.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Automatic collision optimization&lt;/h3&gt;The baking of the bricks into the background solved the render part of the original problem (point 1). The bricks, which now consisted only in invisible rectangles, were defined by hand, looking at the hashes and chosing a smart way of arranging them in a minimum set of rectangles. This is a highly boring work that discouraged me to add more levels, and the perfect candidate for automatization.&lt;br /&gt;
&lt;br /&gt;
Finding the minimum set of rectangles that covers all the bricks is not an easy task, because there usually exists more than one way of covering all the bricks with rectangles. Sometimes the best way involves using overlapping rectangles. Even though finding the optimal solution was an interesting challenge, I realized that including complex (and maybe slow) code to reach perfection was not worth in this case. Having 10% more rectangles than the optimal solution didn't impacted the performance in a visible way. I decided to go with a simple algorithm that provided a good enough solution.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img border="0" src="https://lh4.googleusercontent.com/-01MI1MNvD2I/TWk74vcw6bI/AAAAAAAAAYI/mqHa-8MKq_g/s1600/bricks_step0.png" /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Original bricks&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
The basic idea of the algorithm is to process each row independently, looking for contiguous blocks which define single rectangles, and then try to mix rectangles from consecutive rows if possible. As I said, this doesn't find the optimal solution, it is just a greedy algorighm that provides a good enough one.&lt;br /&gt;
&lt;table cellspacing="10px" style="margin: 0 auto;"&gt;&lt;tbody&gt;
&lt;tr&gt; &lt;td&gt;&lt;br /&gt;
&lt;img border="0" src="https://lh6.googleusercontent.com/-wEwSX70nGXQ/TWk8F431kDI/AAAAAAAAAYM/ysneCMPhWhI/s1600/bricks_step1.png" /&gt;&lt;/td&gt; &lt;td&gt;&lt;br /&gt;
&lt;img border="0" src="https://lh3.googleusercontent.com/-fLzlLjlgXAg/TWk8Jas8dsI/AAAAAAAAAYQ/r_Jhle5yIbQ/s1600/bricks_step2.png" /&gt;&lt;/td&gt; &lt;/tr&gt;
&lt;tr&gt; &lt;td style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Column joins&lt;/span&gt;&lt;/td&gt; &lt;td style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Row Joins&lt;/span&gt;&lt;/td&gt; &lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;
This is the pseudo-code:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: java"&gt;previousRow = new Set[Rectangle]
currentRow = new Set[Rectangle]
rectangles = new List[Rectangle]
for row in rows:
&amp;nbsp;&amp;nbsp;&amp;nbsp; currentRectangle = None
&amp;nbsp;&amp;nbsp;&amp;nbsp; currentRow.clear()
&amp;nbsp;&amp;nbsp;&amp;nbsp; for char in row:
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;  if char == '#':
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if currentRectangle == None:
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; currentRectangle = new Rectangle(colNum, rowNum)
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;  &amp;nbsp;&amp;nbsp;&amp;nbsp;  else:
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;  &amp;nbsp;&amp;nbsp;&amp;nbsp;  &amp;nbsp;&amp;nbsp;&amp;nbsp; currentRectangle.grow()
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;  if (char == ' ' or isRowEnd)&amp;nbsp;
           and currentRectangle != None:
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if canMix(previousRow, currentRectangle):
&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;  &amp;nbsp;&amp;nbsp;  &amp;nbsp;&amp;nbsp;  mix(previousRow, currentRectangle)
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;  &amp;nbsp;&amp;nbsp; else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;  &amp;nbsp;&amp;nbsp;  rectangles.add(currentRectangle)
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; currentRow.put(currentRectangle)
&amp;nbsp;&amp;nbsp;&amp;nbsp; previousRow = currentRow
return rectangles
&lt;/pre&gt;&lt;br /&gt;
The algorithm already tries to mix rectangles with the previous row ones while they are generated, and does a pretty good job joining lots of bricks into big rectangles. Another optimization that I did to the algorithm is to encode the &lt;tt&gt;previousRow&lt;/tt&gt; as an array with the same width as one row, where each position of the array has a pointer to the rectangle that covers this cell or to &lt;tt&gt;null&lt;/tt&gt; if it is empty. This way, finding the right rectangle to mix with in the previous row runs in constant time. Actually, my implementation doesn't need a &lt;tt&gt;currentRow&lt;/tt&gt; structure, I overwrite the previousRow one after reading it...&lt;br /&gt;
&lt;br /&gt;
I will not go into the actual implementation to avoid making this article infinite, but if anyone has some doubt on how to implement it, feel free to leave a comment and ask.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;With the background baker and the rectangle optimizator, generating new Egg Savior levels reduces to actually thinking them and mostly writing a string with hashes. This code runs each time that the player starts a level, and is so fast that it is actually overshadowed by resource loading time.&lt;br /&gt;
&lt;br /&gt;
&lt;script type="text/javascript"&gt;
SyntaxHighlighter.all()
&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-1320404896526498720?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2011/02/baking-game-levels-in-egg-savior.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/1320404896526498720?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/1320404896526498720?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2011/02/baking-game-levels-in-egg-savior.html" title="Baking game levels in Egg Savior" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh5.googleusercontent.com/-wRbs9IlqB-A/TWk4UozBdOI/AAAAAAAAAYE/zq3q3qvlCcc/s72-c/bricks_contrast.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CUEHR3o6cSp7ImA9Wx9UGEw.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-7484353316382557257</id><published>2011-02-16T00:47:00.000+01:00</published><updated>2011-02-16T00:47:16.419+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-16T00:47:16.419+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="market" /><category scheme="http://www.blogger.com/atom/ns#" term="egg savior" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><category scheme="http://www.blogger.com/atom/ns#" term="game" /><title>A very exigent market for games</title><content type="html">It has been almost four months since I published the first version of &lt;a href="http://www.eggsavior.com/"&gt;Egg Savior&lt;/a&gt; in the market. This game was mainly an experiment to learn a couple of new things. First of all, I wanted to learn how to develop games for the Android platform. Secondly, I wanted to learn how the market reacts to games. And finally, I wanted to learn how global apps perform, since &lt;a href="http://organicandroid.blogspot.com/search/label/otempo"&gt;OTempo&lt;/a&gt;, my former app, is a local app targeted to galician users.&lt;br /&gt;
&lt;br /&gt;
For the first target, I am quite proud. The game performs quite well even on middle-end hardware like my old Galaxy Spica, and I was able to try graphics, sound and input. You can read my post on&amp;nbsp;&lt;a href="http://organicandroid.blogspot.com/2010/11/creating-2d-games-with-android-and.html"&gt;Creating 2D games with Android and Blender&lt;/a&gt;&amp;nbsp;where I share some of my gathered knowledge.&lt;br /&gt;
&lt;br /&gt;
About market reaction to games, I have learned a quite hard lesson: The market is &lt;b&gt;very exigent&lt;/b&gt;, even with free games. Actually, I think that gamers don't care if your game is free or costs a couple of bucks, they expect a high quality product from the first version, and if the first version is not good enough, upgrading and &lt;b&gt;enhancing it will not work&lt;/b&gt; like it would have done with other apps. Advertising has been very helpful on recognizing usage patterns on the first version and each upgrade.&lt;br /&gt;
I have to admit that this lesson was hard to fit, because I spent long hours working in this game, but sometimes one has to get back to planet earth and remember its objectives. It was a learning experience, and I have learned a lot.&amp;nbsp;I realize that the artistic needs of the game far exceed my ability, and the number of levels is quite ridiculous, but it was not about fame and glory ;-)&lt;br /&gt;
&lt;br /&gt;
About the global market, I also learned a valuable lesson. There is a &lt;b&gt;lot of fragmentation&lt;/b&gt;. Every country behaves differently to this game. All the statistics that admob provides point to the fact that the usage pattern varies a lot from one country to another. The most obvious example is the &lt;a href="http://organicandroid.blogspot.com/2011/01/egg-savior-reached-100k-downloads-in.html"&gt;case of Korea&lt;/a&gt;, where the game was a huge success, maintaining the first position in free games for several consecutive days. I believe that this is a great opportunity rather than a threat. It enables development of products with a strong personality, focused in a concrete market, and opens more opportunities for everyone. It also warns of the risk of starting a serious project (I mean, investing money) without any kind of market research.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-7484353316382557257?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2011/02/very-exigent-market-for-games.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/7484353316382557257?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/7484353316382557257?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2011/02/very-exigent-market-for-games.html" title="A very exigent market for games" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CE4BRXoyeip7ImA9Wx9WGEU.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-294780159302379044</id><published>2011-01-24T11:01:00.001+01:00</published><updated>2011-01-24T16:29:14.492+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-24T16:29:14.492+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="korea" /><category scheme="http://www.blogger.com/atom/ns#" term="egg savior" /><title>Egg Savior reached 100K downloads in Korea</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_n40vhvGrCys/TMYOa660nFI/AAAAAAAAAWM/pLgjdSzP45I/s1600/imagen_promo.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMYOa660nFI/AAAAAAAAAWM/pLgjdSzP45I/s1600/imagen_promo.png" /&gt;&lt;/a&gt;&lt;/div&gt;Some time ago, I made an agreement with &lt;a href="http://www.ubi-nuri.com/"&gt;UbiNuri&lt;/a&gt; to distribute Egg Savior in the korean market. On January 17, Egg Savior was published in the &lt;a href="http://www.tstore.co.kr/userpoc/game/viewProduct.omp?insDpCatNo=DP01003&amp;amp;insProdId=0000090385&amp;amp;prodGrdCd=PD004401&amp;amp;t_top=DP000501"&gt;T Store&lt;/a&gt;, and the users reaction was really impressive. In Just five days it came to the first position in the free game category, with &lt;a href="https://sites.google.com/site/eggsavior/news/eggsaviordalgyaljikigireached50000downloadsinfirstweekinkorea"&gt;50K downloads&lt;/a&gt;, which doubled during the weekend, making a total of &lt;a href="https://sites.google.com/site/eggsavior/news/eggsaviorsurpassed100kdownloadsinkorea"&gt;100K downloads&lt;/a&gt; after just eight days.&lt;br /&gt;
&lt;br /&gt;
I want to thank UbiNuri and all the korean users who are enjoying this game, and promise new versions with more levels.&lt;br /&gt;
&lt;br /&gt;
By the way, the korean name of Egg Savior is&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif; font-size: 13px;"&gt;&lt;a href="http://www.tstore.co.kr/userpoc/game/viewProduct.omp?insDpCatNo=DP01003&amp;amp;insProdId=0000090385&amp;amp;prodGrdCd=PD004401&amp;amp;t_top=DP000501" rel="nofollow" target="_blank"&gt;달걀 지키기&lt;/a&gt;.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-294780159302379044?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2011/01/egg-savior-reached-100k-downloads-in.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/294780159302379044?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/294780159302379044?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2011/01/egg-savior-reached-100k-downloads-in.html" title="Egg Savior reached 100K downloads in Korea" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_n40vhvGrCys/TMYOa660nFI/AAAAAAAAAWM/pLgjdSzP45I/s72-c/imagen_promo.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DUAHRHY9fCp7ImA9Wx9WGEw.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-8865896980929125756</id><published>2011-01-23T22:22:00.000+01:00</published><updated>2011-01-23T22:22:15.864+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-23T22:22:15.864+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="market" /><category scheme="http://www.blogger.com/atom/ns#" term="otempo" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><title>OTempo bugfix release: 2.5</title><content type="html">Unfortunatelly, the previous version of OTempo (2.4) had a bug with advertisement. You now have the choice of upgrading to 2.5, thus supporting development by re-enabling ads, or stay in 2.4 without ads until the next version which will include new features. It is up to you :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-8865896980929125756?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2011/01/otempo-bugfix-release-25.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/8865896980929125756?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/8865896980929125756?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2011/01/otempo-bugfix-release-25.html" title="OTempo bugfix release: 2.5" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;C0AGQXk7fyp7ImA9Wx9WGEQ.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-274116128801342924</id><published>2011-01-18T21:53:00.002+01:00</published><updated>2011-01-24T18:55:20.707+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-24T18:55:20.707+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="market" /><category scheme="http://www.blogger.com/atom/ns#" term="otempo" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><title>OTempo 2.4 in the market</title><content type="html">&lt;div style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_n40vhvGrCys/TD9P5yOADMI/AAAAAAAAATs/QDNDvYLoIug/s1600/iconosvg_web.png" /&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;I have just updated OTempo once again. This time, it contains a bugfix in the dialog management code, that someone of you reported to the market. &lt;b&gt;Thanks&lt;/b&gt;!&lt;br /&gt;
I also took the opportunity to update the rain icon, because the old one was too uniform. I hope you like the new one, and also hope it looks OK in the brighter areas of the background.&lt;br /&gt;
&lt;br /&gt;
By the way, in the moment of this writing, OTempo is &lt;b&gt;ranked 103&lt;/b&gt; in the list of weather applications! Thanks to all the users who trust OTempo!&lt;br /&gt;
&lt;br /&gt;
If you don't have it already, you can download OTempo using a mobile device, from this link:&lt;br /&gt;
&lt;a href="market://details?id=org.otempo"&gt;market://details?id=org.otempo&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
You can also find &lt;a href="http://bubiloop.com/android-newsweather-otempo-galician-weather"&gt;OTempo on bubiloop&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Remember that it only works for &lt;b&gt;Galicia&lt;/b&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-274116128801342924?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2011/01/otempo-24-in-market.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/274116128801342924?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/274116128801342924?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2011/01/otempo-24-in-market.html" title="OTempo 2.4 in the market" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_n40vhvGrCys/TD9P5yOADMI/AAAAAAAAATs/QDNDvYLoIug/s72-c/iconosvg_web.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEUHSHs8eCp7ImA9Wx9XEks.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-621450699172600161</id><published>2011-01-05T23:23:00.000+01:00</published><updated>2011-01-05T23:23:59.570+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-05T23:23:59.570+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="market" /><category scheme="http://www.blogger.com/atom/ns#" term="otempo" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><title>OTempo 2.3 in the market</title><content type="html">&lt;div class="separator" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em; text-align: center;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_n40vhvGrCys/TD9P5yOADMI/AAAAAAAAATs/QDNDvYLoIug/s1600/iconosvg_web.png" /&gt;&lt;/div&gt;&lt;br /&gt;
I have just released a new version of OTempo. This time it is a bugfix release.&lt;br /&gt;
It addresses a bug for all Android 1.5 devices, and another one that affects all phones when using the prediction descriptions in some circumstances.&lt;br /&gt;
&lt;br /&gt;
As always, you can download OTempo using a mobile device, from this link:&lt;br /&gt;
&lt;a href="market://details?id=org.otempo"&gt;market://details?id=org.otempo&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-621450699172600161?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2011/01/otempo-23-in-market.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/621450699172600161?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/621450699172600161?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2011/01/otempo-23-in-market.html" title="OTempo 2.3 in the market" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_n40vhvGrCys/TD9P5yOADMI/AAAAAAAAATs/QDNDvYLoIug/s72-c/iconosvg_web.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CkMERns-fyp7ImA9Wx9XEkk.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-5476296439575655282</id><published>2011-01-05T16:06:00.002+01:00</published><updated>2011-01-05T16:13:27.557+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-05T16:13:27.557+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="adt" /><category scheme="http://www.blogger.com/atom/ns#" term="fail" /><category scheme="http://www.blogger.com/atom/ns#" term="otempo" /><title>Supporting Android 1.5 in the new ADT</title><content type="html">&lt;div class="separator" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em; text-align: center;"&gt;&lt;img border="0" height="150" src="http://3.bp.blogspot.com/_n40vhvGrCys/TE3T-iwNA6I/AAAAAAAAAUE/wctWhygiuLg/s200/fail.png" width="200" /&gt;&lt;/div&gt;It seems that the last version of the &lt;a href="http://developer.android.com/guide/developing/eclipse-adt.html" target="blank"&gt;ADT&lt;/a&gt; behaves slightly different from the previous versions and may involve changing code. One of the changes that I have seen is that you must explicitly disable &lt;a href="http://developer.android.com/guide/topics/resources/string-resource.html#FormattingAndStyling" target="blank"&gt;formatting&lt;/a&gt; in the strings.xml files if you have more than one placeholder that you will use from code (like %s).&lt;br /&gt;
&lt;br /&gt;
The other one was discovered by one of the OTempo users (Jose Miguel). It seems that ADT &lt;a href="http://www.thetekblog.com/?p=236" target="blank"&gt;can not package correctly&lt;/a&gt; the resources if there is a folder called "drawable-mdpi". This is odd, because "drawable" is for density independent images, not mdpi ones. This behaviour seems to affect only Android 1.5 devices, as I could not reproduce it on 1.6, 2.1 or 2.2.&lt;br /&gt;
&lt;br /&gt;
I think that I will have to learn to live with this, at least until the last Android 1.5 user migrates or changes its phone. &lt;br /&gt;
&lt;br /&gt;
Expect a new version of OTempo in the following hours.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-5476296439575655282?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2011/01/supporting-android-15-in-new-adt.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/5476296439575655282?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/5476296439575655282?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2011/01/supporting-android-15-in-new-adt.html" title="Supporting Android 1.5 in the new ADT" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_n40vhvGrCys/TE3T-iwNA6I/AAAAAAAAAUE/wctWhygiuLg/s72-c/fail.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEAERX09fyp7ImA9Wx9QFUg.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-3876381576482073120</id><published>2010-12-28T18:18:00.000+01:00</published><updated>2010-12-28T18:18:24.367+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-28T18:18:24.367+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="memory" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><title>Total/Free memory on android apps and games</title><content type="html">Yesterday I was helping out my friend &lt;a href="http://www.estudio256.com/"&gt;Sergio&lt;/a&gt; with his own Android game, and he needed to how much memory does each android device have, and how much memory is the app using. After checking out the biggest source of wisdom (yes, stackoverflow), &lt;a href="http://stackoverflow.com/questions/3238388/android-out-of-memory-exception-in-gallery/3238945#3238945"&gt;this&lt;/a&gt; seems to be the solution:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Heap size&lt;/b&gt;:&lt;br /&gt;
&lt;pre class="brush: java"&gt;long heapSize = Debug.getNativeHeapSize();
&lt;/pre&gt;The heap size is not exactly the memory that your app is directly using, but the memory that the VM is reserving for your app. It may be slightly higher than the memory that your app is using due to fragmentation and provision. This number will vary as you allocate memory and force the VM to grow the heap to fit the extra needs.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Allocated size&lt;/b&gt;:&lt;br /&gt;
&lt;pre class="brush: java"&gt;long allocated = Debug.getNativeHeapAllocatedSize();
&lt;/pre&gt;The allocated size is the actual memory amount that your app is directly using.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Free size&lt;/b&gt;:&lt;br /&gt;
&lt;pre class="brush: java"&gt;long free = Debug.getNativeHeapFreeSize();
&lt;/pre&gt;The free size is the amount of memory from the heap that is not being used, because of fragmentation or provision.&lt;br /&gt;
&lt;br /&gt;
These three measurements are very useful. Of course, the first one is the more important one, because it tells you if you are approaching the memory limit or not, but the other two are very interesting for performance reasons. If you use to have a lot of free memory in the heap (say, more than 100KB), this could be a symptom that your app is allocating and freeing a lot of memory on a regular basis, and this may lead to &lt;a href="http://organicandroid.blogspot.com/2010/09/performance.html"&gt;performance problems&lt;/a&gt; due to involving the garbage collector all the time.&lt;br /&gt;
&lt;br /&gt;
Ok, this tells you how much memory you are using, but now there is another interesting question left: How much memory are you allowed to use? It actually doesn't depend on the physical memory amount, but in a hardwired limit that vary from device to device.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Memory limit&lt;/b&gt;:&lt;br /&gt;
&lt;pre class="brush: java"&gt;long maxMem = Runtime.getRuntime().maxMemory();
&lt;/pre&gt;This memory limit will tell you how much memory your app can allocate. In my device it is as little as 18MB. And the biggest EggSavior Level is using 13.5MB. There is room for slightly bigger levels!&lt;br /&gt;
&lt;br /&gt;
I hope this brief article will shed some light to other Android game developers.&lt;br /&gt;
&lt;br /&gt;
&lt;script type="text/javascript"&gt;
SyntaxHighlighter.all()
&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-3876381576482073120?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2010/12/totalfree-memory-on-android-apps-and.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/3876381576482073120?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/3876381576482073120?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2010/12/totalfree-memory-on-android-apps-and.html" title="Total/Free memory on android apps and games" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;A0QDSX0yfCp7ImA9Wx9QFU4.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-1627478525626904659</id><published>2010-12-28T13:29:00.000+01:00</published><updated>2010-12-28T13:29:38.394+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-28T13:29:38.394+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="market" /><category scheme="http://www.blogger.com/atom/ns#" term="otempo" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><title>OTempo 2.2 in the market</title><content type="html">&lt;div class="separator" style="clear: both; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_n40vhvGrCys/TD9P5yOADMI/AAAAAAAAATs/QDNDvYLoIug/s1600/iconosvg_web.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_n40vhvGrCys/TD9P5yOADMI/AAAAAAAAATs/QDNDvYLoIug/s1600/iconosvg_web.png" style="cursor: move;" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;I have just updated OTempo to a new version (2.2). &amp;nbsp;This version allows to click on short-prediction days to see its description, which sometimes gives very usefull information. Besides, a bug about using huge custom background images has been fixed.&lt;/div&gt;&lt;br /&gt;
As always, you can download OTempo using a mobile device, from this link:&lt;br /&gt;
&lt;a href="market://details?id=org.otempo"&gt;market://details?id=org.otempo&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-1627478525626904659?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2010/12/otempo-22-in-market.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/1627478525626904659?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/1627478525626904659?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2010/12/otempo-22-in-market.html" title="OTempo 2.2 in the market" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_n40vhvGrCys/TD9P5yOADMI/AAAAAAAAATs/QDNDvYLoIug/s72-c/iconosvg_web.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;A0cDRHkzcCp7ImA9Wx9SFUo.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-226572178508548510</id><published>2010-12-05T20:57:00.000+01:00</published><updated>2010-12-05T20:57:55.788+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-05T20:57:55.788+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="website" /><category scheme="http://www.blogger.com/atom/ns#" term="egg savior" /><title>Egg Savior website</title><content type="html">I have finished the website of &lt;a href="http://www.eggsavior.com/"&gt;Egg Savior&lt;/a&gt;. There you will find images, videos, and instructions to play it, as well as the latest news and a download area for those of you without Android Market in your device:&lt;br /&gt;
&lt;br /&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://www.eggsavior.com/" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_n40vhvGrCys/TPvtK1962bI/AAAAAAAAAXk/dN62d7WI5b4/s1600/eggsavior.com.jpg" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Egg Savior website&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;div style="clear: both;"&gt;From now on, general Egg Savior news will be published in this website, and &lt;a href="http://organicandroid.blogspot.com/"&gt;The organic android&lt;/a&gt; will focus on technical articles derived from the development, as well as other apps like OTempo.&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-226572178508548510?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2010/12/egg-savior-website.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/226572178508548510?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/226572178508548510?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2010/12/egg-savior-website.html" title="Egg Savior website" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_n40vhvGrCys/TPvtK1962bI/AAAAAAAAAXk/dN62d7WI5b4/s72-c/eggsavior.com.jpg" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DE4HSXw5fSp7ImA9Wx9SFEg.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-2200111417083661911</id><published>2010-12-04T11:02:00.000+01:00</published><updated>2010-12-04T11:02:18.225+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-04T11:02:18.225+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="market" /><category scheme="http://www.blogger.com/atom/ns#" term="egg savior" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><category scheme="http://www.blogger.com/atom/ns#" term="game" /><title>Egg Savior 1.5 is here!</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_n40vhvGrCys/TMYOa660nFI/AAAAAAAAAWM/pLgjdSzP45I/s1600/imagen_promo.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMYOa660nFI/AAAAAAAAAWM/pLgjdSzP45I/s1600/imagen_promo.png" /&gt;&lt;/a&gt;&lt;/div&gt;After a lot of work, I have published a new version of Egg Savior, my Android game. This version includes three new levels and these improvements:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Added a level panel, where you can see your achievements. I had advanced it &lt;a href="http://organicandroid.blogspot.com/2010/11/egg-savior-will-have-levels-menu.html"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The last level includes something new that will change the gameplay in next levels.&lt;/li&gt;
&lt;li&gt;Changed black background in small levels for a more interesting one. I hope that this makes the game less ugly :)&lt;/li&gt;
&lt;li&gt;If the chicken is teleported into an obstacle, it dies. This makes the game a bit more realistic (As much as possible with teleportation system ;-)&lt;/li&gt;
&lt;li&gt;Changed game icon for a more dynamic one. I hope this attracts more players.&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;If you are reading this from an android device, you can download Egg Savior from this link:&lt;br /&gt;
&lt;a href="market://details?id=com.eggsavior"&gt;market://details?id=com.eggsavior&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-2200111417083661911?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2010/12/egg-savior-15-is-here.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/2200111417083661911?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/2200111417083661911?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2010/12/egg-savior-15-is-here.html" title="Egg Savior 1.5 is here!" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_n40vhvGrCys/TMYOa660nFI/AAAAAAAAAWM/pLgjdSzP45I/s72-c/imagen_promo.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEAHQn44cSp7ImA9Wx9SEk4.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-6197037717296876007</id><published>2010-12-01T21:52:00.000+01:00</published><updated>2010-12-01T21:52:13.039+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-01T21:52:13.039+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="market" /><category scheme="http://www.blogger.com/atom/ns#" term="otempo" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><title>OTempo 2.1 in the market</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_n40vhvGrCys/TD9P5yOADMI/AAAAAAAAATs/QDNDvYLoIug/s1600/iconosvg_web.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_n40vhvGrCys/TD9P5yOADMI/AAAAAAAAATs/QDNDvYLoIug/s1600/iconosvg_web.png" /&gt;&lt;/a&gt;&lt;/div&gt;I have just updated OTempo to a new version (2.1). Everyone is encouraged to download this version as soon as possible, because it lacked &lt;b&gt;snow&lt;/b&gt; icon, and tomorrow there will be a lot of snow out there.&lt;br /&gt;
Besides, it fixes a couple of bugs that were reported by users.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-6197037717296876007?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2010/12/otempo-21-in-market.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/6197037717296876007?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/6197037717296876007?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2010/12/otempo-21-in-market.html" title="OTempo 2.1 in the market" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_n40vhvGrCys/TD9P5yOADMI/AAAAAAAAATs/QDNDvYLoIug/s72-c/iconosvg_web.png" height="72" width="72" /><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;A04HSHw6eip7ImA9Wx9SEEg.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-4097014396822711230</id><published>2010-11-29T19:30:00.002+01:00</published><updated>2010-11-29T20:45:39.212+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-29T20:45:39.212+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="level" /><category scheme="http://www.blogger.com/atom/ns#" term="egg savior" /><category scheme="http://www.blogger.com/atom/ns#" term="menu" /><category scheme="http://www.blogger.com/atom/ns#" term="game" /><title>Egg Savior will have a levels menu</title><content type="html">I have been quite busy these days developing a couple of new features of Egg Savior. One of them is the levels menu, that will let you know which levels have been played, and what was your score on them.&lt;br /&gt;
This menu is the reason why the previous version started to record scores. I wanted to share its design here, just in the case that anyone with good taste would like to suggest some enhancements before the next version is out:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_n40vhvGrCys/TPPwLJqDffI/AAAAAAAAAXc/IS3VdWI1X90/s1600/levels_menu.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_n40vhvGrCys/TPPwLJqDffI/AAAAAAAAAXc/IS3VdWI1X90/s1600/levels_menu.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
I am planning to add 3 more levels in the next version, thus reaching a milestone of 20 levels. Expect it in the following days...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-4097014396822711230?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2010/11/egg-savior-will-have-levels-menu.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/4097014396822711230?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/4097014396822711230?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2010/11/egg-savior-will-have-levels-menu.html" title="Egg Savior will have a levels menu" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_n40vhvGrCys/TPPwLJqDffI/AAAAAAAAAXc/IS3VdWI1X90/s72-c/levels_menu.png" height="72" width="72" /><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;C0UAQnk-eSp7ImA9Wx9TFEs.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-4070476586950534935</id><published>2010-11-22T22:27:00.000+01:00</published><updated>2010-11-22T22:27:23.751+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-22T22:27:23.751+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="market" /><category scheme="http://www.blogger.com/atom/ns#" term="egg savior" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><category scheme="http://www.blogger.com/atom/ns#" term="game" /><title>Egg Savior 1.4 in the market</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_n40vhvGrCys/TMYOa660nFI/AAAAAAAAAWM/pLgjdSzP45I/s1600/imagen_promo.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMYOa660nFI/AAAAAAAAAWM/pLgjdSzP45I/s1600/imagen_promo.png" /&gt;&lt;/a&gt;&lt;/div&gt;I have just finished a new version of Egg Savior, with the following improvements:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Adds a new level&lt;/li&gt;
&lt;li&gt;Warns if you try to move pieces while the game is paused&lt;/li&gt;
&lt;li&gt;Stores achievements on the phone. Players should not notice anything about this in the current version, but it the next version will do level blocking based on played/unplayed levels, and the game needs to gather info from current users to effectively block levels for them. You will be able to see your achivements in the next version too.&lt;/li&gt;
&lt;/ol&gt;This is a little release because I was working really hard in my &lt;a href="http://organicandroid.blogspot.com/2010/11/creating-2d-games-with-android-and.html"&gt;last article&lt;/a&gt;. Next version will be much more interesting, I promise!&lt;br /&gt;
&lt;br /&gt;
If you are reading this from an android device, you can download Egg Savior from this link:&lt;br /&gt;
&lt;a href="market://details?id=com.eggsavior"&gt;market://details?id=com.eggsavior&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-4070476586950534935?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2010/11/egg-savior-14-in-market.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/4070476586950534935?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/4070476586950534935?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2010/11/egg-savior-14-in-market.html" title="Egg Savior 1.4 in the market" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_n40vhvGrCys/TMYOa660nFI/AAAAAAAAAWM/pLgjdSzP45I/s72-c/imagen_promo.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;AkUCR38zeyp7ImA9Wx9TFUk.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-3620548569933670100</id><published>2010-11-21T02:00:00.001+01:00</published><updated>2010-11-23T22:37:46.183+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-23T22:37:46.183+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="android" /><category scheme="http://www.blogger.com/atom/ns#" term="game" /><category scheme="http://www.blogger.com/atom/ns#" term="blender" /><category scheme="http://www.blogger.com/atom/ns#" term="2D" /><title>Creating 2D games with Android and Blender</title><content type="html">&lt;h3&gt;1. Introduction&lt;/h3&gt;&lt;img align="right" alt="" src="http://2.bp.blogspot.com/_n40vhvGrCys/TOhjlvCy6RI/AAAAAAAAAW0/bRzsbyQmpgI/s1600/blendroid.png" style="height: 120px; width: 160px;" /&gt; This article will cover one of the possible workflows that you can use in order to create &lt;span style="font-weight: bold;"&gt;Android&lt;/span&gt; games using &lt;span style="font-weight: bold;"&gt;Blender&lt;/span&gt; for content creation. This article is based on the knowledge that I could gather during the development of &lt;a href="http://tinyurl.com/OrganicEggSavior"&gt;Egg Savior&lt;/a&gt;. For the programming part, I will assume that you have some knowledge about game creation in Android. If this is not the case, please start by reading &lt;a href="http://organicandroid.blogspot.com/2010/08/starting-to-play-with-graphics.html" target="_blank"&gt;these great tutorials&lt;/a&gt; before continuing. For the graphics part, I will assume that you know how to create graphics with blender. If this is not the case, please start by reading &lt;a href="http://www.blender.org/education-help/tutorials/" target="_blank"&gt;these great tutorials&lt;/a&gt;, or consider hiring a blender artist.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.yofrankie.org/"&gt;&lt;img align="right" alt="" src="http://4.bp.blogspot.com/_n40vhvGrCys/TOhj33FykuI/AAAAAAAAAW4/VzOdFZz7A2s/s1600/yo_frankie.png" style="height: 120px; width: 213px;" /&gt;&lt;/a&gt;Blender is a powerful 3D content creation tool that has proved application in many different areas. It even includes a game engine that you can use to develop PC games. There are several 3D games made with Blender, starting by &lt;a href="http://www.yofrankie.org/" target="_blank"&gt;Yo Frankie&lt;/a&gt;, the first open game from the Blender Foundation. But the most important feature of Blender is its license: which makes it&amp;nbsp;&lt;span style="font-weight: bold;"&gt;open-source&lt;/span&gt;, and &lt;span style="font-weight: bold;"&gt;free&lt;/span&gt; of charge.&lt;br /&gt;
&lt;br /&gt;
So why use a 3D tool for 2D games? Because unless you are a great 2D artist, it is easier and faster to animate in 3D, and it is easier to get an acceptable overall result if you are not very good with graphics (like is my case). The obvious trick is to pre-render the 3D graphics into 2D images and use these images as assets for your game.&lt;br /&gt;
&lt;br /&gt;
In the following sections I will explain how you can build your own pipeline for working with blender for 2D Android game creation. I will focus first on the artistic side (Blender) and then on the engineering side (programming).&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;2. The Blender side (for artists only)&lt;/h3&gt;&lt;img align="right" alt="" src="http://2.bp.blogspot.com/_n40vhvGrCys/TOhkl1YprLI/AAAAAAAAAW8/PGSsw_oiTSM/s1600/eggsavior.png" style="height: 120px; width: 214px;" /&gt; I will focus on pure 2D games. There are some 2D games that fake a 3D effect (eg isometric games) but I still have to explore them and develop a workflow for these. Creating the graphics with blender is quite straightforward, and you just have to follow a few simple rules to have a set of graphics that can be used without problems in a game engine.&lt;br /&gt;
&lt;br /&gt;
First of all, you should chose a hardware target for your game. Android runs on a variety of devices with different screen sizes and resolutions. You simply can't make a 2D game that looks good and runs fast on every possible device. Narrow the hardware where you want your game to run properly and then design your graphics to fit in the chosen range of supported screen resolutions and sizes.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;2.1. Modeling / Shading&lt;/h4&gt;&lt;img align="right" alt="" src="http://1.bp.blogspot.com/_n40vhvGrCys/TOhldZyiksI/AAAAAAAAAXA/LP4g_Qw7_Us/s1600/modeling.png" style="height: 120px; width: 122px;" /&gt; There is nothing magical here. Just ask yourself a few questions before starting:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Which sides of the object will be seen on the screen? Maybe you don't need detail in the whole object.&lt;/li&gt;
&lt;li&gt;What will be the maximum size in pixels of the object? I mean, in the highest resolution device. Maybe you don't need to add feathers to your chicken because they will not be seen ;)&lt;/li&gt;
&lt;li&gt;Do you want to give the game a cartoon look? Take into account the cartoon edges, they also use pixels!&lt;/li&gt;
&lt;/ul&gt;By the way, don't be afraid of the number of polygons, the devices will not see them, because the final output of Blender are images.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;2.2. Rigging&lt;/h4&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_n40vhvGrCys/TOhlp3OR7pI/AAAAAAAAAXE/TKJ_C7yqyq0/s1600/rigging.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img align="right" border="0" height="120" src="http://1.bp.blogspot.com/_n40vhvGrCys/TOhlp3OR7pI/AAAAAAAAAXE/TKJ_C7yqyq0/s200/rigging.png" /&gt;&lt;/a&gt;&lt;/div&gt;Rigging for 2D games is not easier than rigging for movies, but it takes less time. 2D games have something in common with series, though: lots of animation cycles! These are my tips after having made Egg Savior:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Automate everything that you can. You will be animating lots of cycles, and the more automated is the rigging, the less effort you will need to put in animation.&lt;/li&gt;
&lt;li&gt;As with modeling and shading, concentrate on the level of detail. You don't want to add a muscle system that will not be seen because the character will be 64 pixels tall...&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;h4&gt;2.3. Animation&lt;/h4&gt;&lt;a href="http://3.bp.blogspot.com/_n40vhvGrCys/TOhmO0K40UI/AAAAAAAAAXI/AbhRXHcn7Gc/s1600/animation.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img align="right" border="0" height="116" src="http://3.bp.blogspot.com/_n40vhvGrCys/TOhmO0K40UI/AAAAAAAAAXI/AbhRXHcn7Gc/s320/animation.png" width="320" /&gt;&lt;/a&gt;Up to this point, I was just writing about several optimizations that you can do to work less. Now we will get into something more important, because the choices that you make in this point, are related to the choices that have to be made in the programming.&lt;br /&gt;
&lt;br /&gt;
If your character is going to move across the screen because of the animation (eg walking), you have a very important decision to make, how to animate this cycle. Two options (I will use the walking example):&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Move the character across the scene while it walks. You get the highest quality of animation, because you can even change the speed of movement from step to step. The problem is that this involves a bit more complex programming.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Walk in place, as if done in a conveyor belt. It is very easy to program, but it involves strong restrictions on the animation, that have to move the character at a constant speed.&lt;br /&gt;
&lt;/li&gt;
&lt;/ol&gt;Later, I will explain how to program both options. In Egg Savior, I choosed the first one, because I wanted higher quality and to avoid foot slip:&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_n40vhvGrCys/TOhm0_8XxZI/AAAAAAAAAXM/_IFXko6lj-A/s1600/walkcycle_frames.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_n40vhvGrCys/TOhm0_8XxZI/AAAAAAAAAXM/_IFXko6lj-A/s1600/walkcycle_frames.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;h4&gt;2.4. Render&lt;/h4&gt;The first thing to consider in the render phase is how to configure the camera for the render of each asset. I will share my own point of view, although yours may differ (feel free to comment):&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Background. I suggest using a perspective camera unless the background have to be aligned with the foreground. This will add depth to the game levels.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Foreground objects. I am calling foreground objects to those that doesn't move, but the character can interact with them (eg platforms). I suggest using an orthogonal camera, to help them integrate well with the character. If you want to compose the foreground by tiling small objects, the orthogonal camera is the only option.&lt;/li&gt;
&lt;li&gt;Characters. Characters will be animated, and the last frame of the animation must match the first frame to be able to cycle it. Unless you use the "walk in place" solution, the last frame will not match the first frame if you use a perspective projection. Anyway, if the character is rendered with perspective, when it moves across the screen the eye will notice that this perspective is not changing, thus making it less believeable.&lt;br /&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_n40vhvGrCys/TOhnMppQkCI/AAAAAAAAAXQ/Y7MsJiXJLVI/s1600/orthocamera.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="148" src="http://4.bp.blogspot.com/_n40vhvGrCys/TOhnMppQkCI/AAAAAAAAAXQ/Y7MsJiXJLVI/s200/orthocamera.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;The use of an orthogonal camera for the render of foreground objects has an additional benefit. You can predict the size of the object on the image without actually rendering anything, because there is an easy relationship between the size of the object, the size of the camera and the screen size. An easy rule is to setup the orthogonal camera with an scale of 1, and make objects with size 1x1 when they must fill the whole asset image. You can now simply play with the output resolution to make assets with different sizes, if needed.&lt;br /&gt;
&lt;br /&gt;
The second thing to consider is the AA filter that you must use. It depends on the target hardware, and specifically on the screen resolutions. If your graphics are going to be small because you target handhelds, you have to use a crisp filter even if it generates a bit of aliasing.&amp;nbsp; You can try mitch or even catrom. If you target big screen devices with little dpi (like some tablets), then you might consider less crisp filters because the aliasing artifacts can be very noticeable. In that case, avoid catrom, try mitch or even gaussian.&lt;br /&gt;
&lt;br /&gt;
The third thing to consider is the output format. I suggest using PNG in RGBA mode for the foreground and characters, as it is a quite programmer-friendly format.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_n40vhvGrCys/TOhne25B4yI/AAAAAAAAAXU/mHbpksciWzI/s1600/renderopts.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="141" src="http://3.bp.blogspot.com/_n40vhvGrCys/TOhne25B4yI/AAAAAAAAAXU/mHbpksciWzI/s400/renderopts.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;3. The engineering side (for programmers only)&lt;/h3&gt;I have experience with the Canvas object, and will center this part in this way of working with 2D graphics. You can also program 2D graphics with OpenGL ES, and some games do it this way because you can gain some performance, but not every device supports it correctly (eg my Samsung Galaxy Spica).&lt;br /&gt;
&lt;br /&gt;
Rendering foreground objects on the screen is quite straightforward. You can just use the canvas methods for this:&lt;br /&gt;
&lt;pre class="brush: java"&gt;Bitmap loadedAssetBitmap = BitmapFactory.decodeResource(...); 
Rect targetArea = new Rect(left, top, right, bottom); 
[...] 
canvas.drawBitmap(loadedAssetBitmap, null, targetArea, null); &lt;/pre&gt;&lt;br /&gt;
The difficulty comes with animated objects, like characters. There are two decisions to make:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;How to encode the animation?&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;Each frame on a separate image. Easy to program, but bad for performance, as you have to decode lots of images at startup and cycle between them may also hurt the cache.&lt;/li&gt;
&lt;li&gt;Every frame on a single image (like a texture atlas) as &lt;a href="http://www.droidnova.com/2d-sprite-animation-in-android,471.html" target="_blank"&gt;suggested&lt;/a&gt; by Stephen Flockton. Harder to program, but better performance. Also, this option is more OpenGL-friendly, just in the case that you want to switch at some point in the future. This was the option implemented in Egg Savior, with good results. Here you have an example of the walk cycle:&lt;br /&gt;
&lt;img border="0" src="http://4.bp.blogspot.com/_n40vhvGrCys/TOhpvXzOEeI/AAAAAAAAAXY/Z6rVg6UBKsg/s1600/walk_right.png" /&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;How to handle movement? This is a decision that you have to make both for programming and animation, as I wrote before. The two options, as seen from the animation:&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;Walk in place, as if done in a conveyor belt. If the animation was done this way, you just compose every frame that Blender outputs in the single image and compute how many pixels should the character advance on each frame. This way, each time that you advance one animation frame, the character moves X pixels on screen.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Move the character across the scene while it walks. If the animation was done this way, you end up with a series of frames like these three samples:&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_n40vhvGrCys/TOhm0_8XxZI/AAAAAAAAAXM/_IFXko6lj-A/s1600/walkcycle_frames.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_n40vhvGrCys/TOhm0_8XxZI/AAAAAAAAAXM/_IFXko6lj-A/s1600/walkcycle_frames.png" /&gt;&lt;/a&gt;&lt;/div&gt;As you can see, the character advances through the image. And if you play the whole animation, you will see how the character advances through the floor without foot slip. You can make a simple python script that extracts the bounding box of the character and encodes just this piece on the single image, and at the same time, encodes the offset that each new frame applies to the character with respect to the previous one. When programming this thing, you just move the character with the offset associated with each frame. This allows different offset on each frame, and gives more freedom to the animation stage.&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/ol&gt;As you can figure out by seeing the samples, I have chosen the hardest but more efficient and flexible way of handling both aspects. This is the information that I attach to each frame to handle movement:&lt;br /&gt;
&lt;pre class="brush: java"&gt;public class SpriteFrameInfo 
{
    public SpriteFrameInfo(Point pivot, Point posDelta)
    {
        _pivot = pivot;
        _posDelta = posDelta;
    }
    
    Point _pivot;
    Point _posDelta;
}&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;posDelta is the offset that this frame must apply to the character to move it to the right position.&lt;/li&gt;
&lt;li&gt;pivot is the position inside the frame that can be considered as the "character position" to have it standing on the floor. This is usefull in a platform game like Egg Savior, but not as much in other 2D games.&lt;/li&gt;
&lt;/ul&gt;As you have seen, I have a maximum number of columns in the single image that holds every frame. In fact, I try to keep the image as square as possible, to be easy to open with any editor/viewer. Thus, the code to compute the rectangle that corresponds to each frame is this:&lt;br /&gt;
&lt;pre class="brush: java"&gt;public void updateFrameRectangle()
{
    int row = ((int)_curFrame) / _columns;
    int col = ((int)_curFrame) % _columns;
    int x = _spriteWidth * col;
    int y = _spriteHeight * row;
    _srcRectangle.left = x;
    _srcRectangle.top = y;
    _srcRectangle.right = x + _spriteWidth;
    _srcRectangle.bottom = y + _spriteHeight;
}
&lt;/pre&gt;Where:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;_curFrame is the current frame&lt;/li&gt;
&lt;li&gt;_columns is the number of columns of the single image that holds every frame&lt;/li&gt;
&lt;li&gt;_spriteWidth is the width of each frame in the sprite&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;_spriteHeight is the height of each frame in the sprite&lt;/li&gt;
&lt;/ul&gt;And now, the method that updates the current frame:&lt;br /&gt;
&lt;pre class="brush: java"&gt;public boolean updateFrame(long deltaTimeMS)
{
    boolean toReturn = false;
    _curFrameTime+=deltaTimeMS;
    _positionDelta.set(0, 0);
    while (_curFrameTime &amp;gt; _mspf)
    {
        if (_looping == true || _curFrame &amp;lt; _nFrames - 1)
        {
            _curFrame = (_curFrame + 1) % _nFrames;
            _curFrameInfo = _frameInfoList.get(_curFrame);
            _curFrameTime -= _mspf;
            updateFrameRectangle();
            Point p = _curFrameInfo.getPosDelta();
            _positionDelta.x += p.x;
            _positionDelta.y += p.y;
            toReturn = true;
        }
        else
        {
            return toReturn;
        }
    }
    return toReturn;
} &lt;/pre&gt;Where:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;_curFrameTime is the game time relative to the current frame, in miliseconds. Each time that the animation advances, it restarts counting. You need this because the animation framerate may be less than the device framerate.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;_positionDelta is offset that have to be applied to the character in this frame&lt;/li&gt;
&lt;li&gt;_mspf is the number of miliseconds per frame. It is obviously derived from the FPS.&lt;/li&gt;
&lt;li&gt;_curFrameInfo is the current instance of SpriteFrameInfo&lt;/li&gt;
&lt;/ul&gt;You may notice on this code that there is a while. This is needed because on some situations, you may have to advance several animation frames. For example, Egg Savior has a "fast forward" button that simply scales the deltaTimeMS parameter used for animation, faking that time goes faster, and on a single device frame you may have to advance several animation frames, and apply all the offsets of these frames to the character. In that case, the performance would be higher with the "walk in pace" approach, but I prefer the animation freedom.&lt;br /&gt;
&lt;br /&gt;
Finally, the code that renders the sprite is almost obvious:&lt;br /&gt;
&lt;pre class="brush: java"&gt;public void draw(Canvas canvas, int x, int y)
{
    Point pivot = _curFrameInfo.pivot;
    _tgtRectangle.left = x - pivot.x;
    _tgtRectangle.top = y - pivot.y;
    _tgtRectangle.right = _tgtRectangle.left + _spriteWidth;
    _tgtRectangle.bottom = _tgtRectangle.top + _spriteHeight;
    canvas.drawBitmap(_sheet, _srcRectangle, _tgtRectangle, null);
}
&lt;/pre&gt;&lt;br /&gt;
I hope that this article helps you to start developing your own 2D games. And if you are an experienced developer, feel free to share your knowledge and propose other alternatives to these ideas.&lt;br /&gt;
&lt;br /&gt;
&lt;small&gt;The android image of this post is a modification based on work created and &lt;a href="http://code.google.com/policies.html"&gt;shared by Google&lt;/a&gt; and used according to terms described in the &lt;a href="http://creativecommons.org/licenses/by/3.0/"&gt;Creative Commons 3.0 Attribution License&lt;/a&gt;. &lt;br /&gt;
This post is shared according to terms described in the &lt;a href="http://creativecommons.org/licenses/by-sa/3.0/"&gt;Creative Commons 3.0 Attribution Share Alike License&lt;/a&gt; &lt;/small&gt;&lt;br /&gt;
&lt;script type="text/javascript"&gt;
SyntaxHighlighter.all()
&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-3620548569933670100?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2010/11/creating-2d-games-with-android-and.html#comment-form" title="15 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/3620548569933670100?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/3620548569933670100?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2010/11/creating-2d-games-with-android-and.html" title="Creating 2D games with Android and Blender" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_n40vhvGrCys/TOhjlvCy6RI/AAAAAAAAAW0/bRzsbyQmpgI/s72-c/blendroid.png" height="72" width="72" /><thr:total>15</thr:total></entry><entry gd:etag="W/&quot;CE4MQ3w-eSp7ImA9Wx5aGEs.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-1232398123848962228</id><published>2010-11-16T00:16:00.000+01:00</published><updated>2010-11-16T00:16:22.251+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-16T00:16:22.251+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="market" /><category scheme="http://www.blogger.com/atom/ns#" term="egg savior" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><category scheme="http://www.blogger.com/atom/ns#" term="game" /><title>Egg Savior 1.3 fixes the force close bug</title><content type="html">I have just published a new version of Egg Savior to solve a bug introduced in 1.2 that caused &lt;i&gt;force close&lt;/i&gt; on some situations when going to sleep and coming back.&lt;br /&gt;
Sorry for the inconvenience.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-1232398123848962228?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2010/11/egg-savior-13-fixes-force-close-bug.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/1232398123848962228?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/1232398123848962228?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2010/11/egg-savior-13-fixes-force-close-bug.html" title="Egg Savior 1.3 fixes the force close bug" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEIMRXo4fSp7ImA9Wx5aF0s.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-3459516008111575621</id><published>2010-11-14T21:29:00.000+01:00</published><updated>2010-11-14T21:29:44.435+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-14T21:29:44.435+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="market" /><category scheme="http://www.blogger.com/atom/ns#" term="egg savior" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><category scheme="http://www.blogger.com/atom/ns#" term="game" /><title>Egg Savior 1.2 in the market</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_n40vhvGrCys/TMYOa660nFI/AAAAAAAAAWM/pLgjdSzP45I/s1600/imagen_promo.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMYOa660nFI/AAAAAAAAAWM/pLgjdSzP45I/s1600/imagen_promo.png" /&gt;&lt;/a&gt;&lt;/div&gt;I have just finished a new version of &lt;b&gt;Egg Savior, &lt;/b&gt;with &lt;b&gt;three new levels&lt;/b&gt; and the following enhancements:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;Automatic scroll&lt;/b&gt; when approaching an screen edge. Can be configured, or even disabled if you dislike it.&lt;/li&gt;
&lt;li&gt;Now you can drag the pieces that were &lt;b&gt;below the inventory&lt;/b&gt;. This was a bug and on some devices could get very annoying.&lt;/li&gt;
&lt;li&gt;The &lt;b&gt;audio resumes&lt;/b&gt; after turning off/on the screen. This was related to &lt;a href="http://stackoverflow.com/questions/3407192/problems-understanding-the-life-cycle-when-screen-goes-off-and-on/4179045#4179045"&gt;this contribution in StackOverflow&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The game is now &lt;b&gt;paused&lt;/b&gt; when you return from another app, avoiding you to lose the game if you had an incoming call.&lt;/li&gt;
&lt;/ul&gt;If you are reading this from an android device, you can download Egg Savior from this link:&lt;br /&gt;
&lt;a href="market://details?id=com.eggsavior"&gt;market://details?id=com.eggsavior&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
I am working on an in-depth article explaining the Blender/Android pipeline that was used to develop this game. Stay tuned!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-3459516008111575621?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2010/11/egg-savior-12-in-market.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/3459516008111575621?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/3459516008111575621?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2010/11/egg-savior-12-in-market.html" title="Egg Savior 1.2 in the market" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_n40vhvGrCys/TMYOa660nFI/AAAAAAAAAWM/pLgjdSzP45I/s72-c/imagen_promo.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DkMHQ3s9eSp7ImA9Wx5aFE8.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-435251099602094239</id><published>2010-11-10T22:26:00.001+01:00</published><updated>2010-11-10T22:27:12.561+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-10T22:27:12.561+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="market" /><category scheme="http://www.blogger.com/atom/ns#" term="otempo" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><title>OTempo 2.0 in the market</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_n40vhvGrCys/TD9P5yOADMI/AAAAAAAAATs/QDNDvYLoIug/s1600/iconosvg_web.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_n40vhvGrCys/TD9P5yOADMI/AAAAAAAAATs/QDNDvYLoIug/s1600/iconosvg_web.png" /&gt;&lt;/a&gt;&lt;/div&gt;OTempo 2.0 (not a major change, just didn't liked 1.10) has come to the android market. This version is specially driven by the community of users, because most changes are suggested by the users themselves. The list:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;You can change the background image. You should use vertical images to avoid stretching. The ideal size varies from one phone to another, but use something like 320x359, or similar aspect ratio should be nice.&lt;/li&gt;
&lt;li&gt;The &lt;button&gt;Why?&lt;/button&gt; button next to the prediction time will not be shown after you press it once. This button was really ugly, I know.&lt;/li&gt;
&lt;li&gt;Fixed a bug in the widget, that was showing the previous day prediction sometimes. Actually, at any hour from 0:00 to the first day prediction :-(&lt;/li&gt;
&lt;li&gt;Added a share button to the menu. Use it to tell your friends about OTempo, and help creating a community of users. It will share a link to the &lt;a href="http://tinyurl.com/OTempoFacebook"&gt;OTempo facebook page&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
As always, you can download OTempo using a mobile device, from this link:&lt;br /&gt;
&lt;a href="market://details?id=org.otempo"&gt;market://details?id=org.otempo&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-435251099602094239?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2010/11/otempo-20-in-market.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/435251099602094239?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/435251099602094239?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2010/11/otempo-20-in-market.html" title="OTempo 2.0 in the market" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_n40vhvGrCys/TD9P5yOADMI/AAAAAAAAATs/QDNDvYLoIug/s72-c/iconosvg_web.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEYDRH87fyp7ImA9Wx5aEE0.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-8425967648595338540</id><published>2010-11-06T02:14:00.002+01:00</published><updated>2010-11-06T02:16:15.107+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-06T02:16:15.107+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="market" /><category scheme="http://www.blogger.com/atom/ns#" term="egg savior" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><category scheme="http://www.blogger.com/atom/ns#" term="game" /><title>Egg Savior 1.1 in the market</title><content type="html">&lt;a href="http://1.bp.blogspot.com/_n40vhvGrCys/TMYOa660nFI/AAAAAAAAAWM/pLgjdSzP45I/s1600/imagen_promo.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMYOa660nFI/AAAAAAAAAWM/pLgjdSzP45I/s1600/imagen_promo.png" /&gt;&lt;/a&gt;&lt;a href="market://details?id=com.eggsavior" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="200" src="http://4.bp.blogspot.com/_n40vhvGrCys/TNSq2T2lFoI/AAAAAAAAAWg/2KdTqxu38-4/s200/egg_savior_qrcode.png" width="200" /&gt;&lt;/a&gt;Egg Savior has been updated. This new version includes &lt;b&gt;two new levels&lt;/b&gt; and the following changes, suggested by users:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Added a &lt;b&gt;fast-forward&lt;/b&gt; button (asked by a lot of people)&lt;/li&gt;
&lt;li&gt;Disabled &lt;b&gt;scroll&lt;/b&gt; when the whole level fits on the screen (should fix the problems with big-screen devices)&lt;/li&gt;
&lt;li&gt;Fixed&amp;nbsp;&lt;b&gt;bug&lt;/b&gt;: having won, you could not restart the level to improve the score.&lt;/li&gt;
&lt;/ul&gt;If you are reading this from an android device, you can download Egg Savior from this link:&lt;br /&gt;
&lt;a href="market://details?id=com.eggsavior"&gt;market://details?id=com.eggsavior&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Thanks for your support.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-8425967648595338540?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2010/11/egg-savior-11-in-market.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/8425967648595338540?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/8425967648595338540?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2010/11/egg-savior-11-in-market.html" title="Egg Savior 1.1 in the market" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_n40vhvGrCys/TMYOa660nFI/AAAAAAAAAWM/pLgjdSzP45I/s72-c/imagen_promo.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEUBQXo8eCp7ImA9Wx5aEEs.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-3291192856611027427</id><published>2010-11-04T21:32:00.001+01:00</published><updated>2010-11-06T18:57:30.470+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-06T18:57:30.470+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="open-source" /><category scheme="http://www.blogger.com/atom/ns#" term="gpl" /><category scheme="http://www.blogger.com/atom/ns#" term="admob" /><title>open-source and admob</title><content type="html">From the first line of code of my first android app, I had the idea of open-source in mind. I wanted to test the advertisement business model and clear my own ideas before doing the mix with open-source, because I had a lot of doubts about how to manage both things at the same time.&lt;br /&gt;
Now I have a plan and no longer fear this combination from the economic point of view. Take my words with care, as I am still in a learning process with toy projects of zero cost and zero risk (and almost zero income). Two things can happen that I was concerned about:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Case 1&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;/b&gt;Someone can take the code, not contribute anything, and start making money for himself. This is something that can happen with open-source in general, but in the android environment, it is specially easy to do. Anyway, as long as I don't make less money, I don't care if others do it also.&lt;br /&gt;
Even if this person contributes with enhancements and users prefer his/her version over mine, I would have access to the source of his/her enhancements to update my version and build on them. That is the power of open-source, and I am not afraid of it.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Case 2&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Someone can take the code, remove the advertisement, and republish it free of charge and free of ad in the market. This is a little annoying, and would hurt my income. I used to be also a young boy with plenty of free time and no bills to pay, and did projects for fun, but now things changed a bit, so I must take some action to protect the income. Tom Tasche, author of &lt;a href="http://tomtasche.at/p/SayMyName"&gt;SayMyName&lt;/a&gt;, suggested an interesting and friendly solution to this. If someone is so annoyed by the advertisement that he/she would take the time to publish an ad-free version, then I should allow disabling the ads at the configuration. People annoyed by advertisement don't click on ads anyway, and people that don't care and even click when they are interested, would leave them turned on if only as a contribution to the developer.&lt;br /&gt;
&lt;br /&gt;
As I said, my toy projects are not giving real income, allowing me to test these theories with zero risk and better define a business model for the projects to come.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;GPL and admob incompatibility&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
So far so good, but then Brendan Dahl, the author of &lt;a href="http://code.google.com/p/gcal-call-logger/"&gt;gcal-call-logger&lt;/a&gt;, pointed to an interesting problem with GPL (my favorite license). GPL doesn't allow linking with closed-source libraries, like is admob. At first, without community contributions, you could relicense it to yourself without GPL just to publish it with admob, and it would work, as it works for gcal-call-logger. The problem comes when you want to accept community contributions to the codebase, something that I would love to do with OTempo, for example. Community contributions are covered also by GPL, but these contributions are not your property, and you can not relicense them in order to publish the resulting app with admob again.&lt;br /&gt;
&lt;br /&gt;
I have not yet found a solution to this last problem. Maybe GPL is not the right open-source license in this case, or maybe I should give &lt;a href="http://helpcenter.adwhirl.com/"&gt;AdWhirl&lt;/a&gt; (an open-source meta-ad-provider) a try.&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;Update:&lt;/b&gt; People from GNU already thought about issues like this one, and they explain in the FAQ how to overcome it: &lt;a href="http://www.gnu.org/licenses/gpl-faq.html#GPLIncompatibleLibs"&gt;GPL FAQ (GPL incompatible libs)&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-3291192856611027427?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2010/11/open-source-and-admob.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/3291192856611027427?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/3291192856611027427?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2010/11/open-source-and-admob.html" title="open-source and admob" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;DkMNRHs4eyp7ImA9Wx5bFk8.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-4062919831577190304</id><published>2010-11-01T16:14:00.002+01:00</published><updated>2010-11-01T16:14:55.533+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-01T16:14:55.533+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="trailer" /><category scheme="http://www.blogger.com/atom/ns#" term="egg savior" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><category scheme="http://www.blogger.com/atom/ns#" term="game" /><title>Egg Savior - Trailer</title><content type="html">&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube-nocookie.com/v/0byIARFTyRk?fs=1&amp;amp;hl=es_ES&amp;amp;rel=0"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube-nocookie.com/v/0byIARFTyRk?fs=1&amp;amp;hl=es_ES&amp;amp;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-4062919831577190304?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2010/11/egg-savior-trailer.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/4062919831577190304?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/4062919831577190304?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2010/11/egg-savior-trailer.html" title="Egg Savior - Trailer" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;A08FQX05fyp7ImA9Wx5bFU8.&quot;"><id>tag:blogger.com,1999:blog-8121606269770443195.post-7859831848991436308</id><published>2010-10-29T16:28:00.001+02:00</published><updated>2010-10-31T13:56:50.327+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-31T13:56:50.327+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="market" /><category scheme="http://www.blogger.com/atom/ns#" term="egg savior" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><category scheme="http://www.blogger.com/atom/ns#" term="game" /><title>Egg Savior 1.0 published, worldwide!</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_n40vhvGrCys/TMYOa660nFI/AAAAAAAAAWM/pLgjdSzP45I/s1600/imagen_promo.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="133" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMYOa660nFI/AAAAAAAAAWM/pLgjdSzP45I/s200/imagen_promo.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;After just a week of beta testing, it seems that the game is stable enough to be released worldwide. I have uploaded the 1.0 version to the Android Market, and its available for you to download.&lt;br /&gt;
&lt;br /&gt;
This version includes 11 levels, of varying difficulty. I will be adding extra levels on each new release, plus bug fixes and gameplay enhancements as suggested by the players.&lt;br /&gt;
&lt;br /&gt;
Thanks to all contributors who made this possible, especially to &lt;a href="http://feiss.be/"&gt;Diego F. Goberna&lt;/a&gt; for his invaluable help with graphics and Silvia Izquierdo for her patience and the help with the marketing and level&amp;nbsp;design.&lt;br /&gt;
&lt;br /&gt;
Thanks also to all the beta-testers, because without them, this first stable release would not be nearly as stable.&lt;br /&gt;
&lt;br /&gt;
If you are reading this from an android device, you can download Egg Savior from this link:&lt;br /&gt;
&lt;a href="market://details?id=com.eggsavior"&gt;market://details?id=com.eggsavior&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8121606269770443195-7859831848991436308?l=organicandroid.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="text/html" href="http://organicandroid.blogspot.com/2010/10/egg-savior-10-published-worldwide.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/7859831848991436308?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8121606269770443195/posts/default/7859831848991436308?v=2" /><link rel="alternate" type="text/html" href="http://organicandroid.blogspot.com/2010/10/egg-savior-10-published-worldwide.html" title="Egg Savior 1.0 published, worldwide!" /><author><name>Rubén López</name><uri>http://www.blogger.com/profile/17233668160550792036</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://1.bp.blogspot.com/_n40vhvGrCys/TMVZ9xGmRSI/AAAAAAAAAVs/IpAwnatKNbQ/S220/mini_normal.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_n40vhvGrCys/TMYOa660nFI/AAAAAAAAAWM/pLgjdSzP45I/s72-c/imagen_promo.png" height="72" width="72" /><thr:total>0</thr:total></entry></feed>

