<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-107421633532789675</id><updated>2026-05-26T12:03:14.368+02:00</updated><title type='text'>klutzGames</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://klutzgames.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://klutzgames.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Timo Fleisch</name><uri>http://www.blogger.com/profile/18171872141745431561</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsaCQIqmHrvkkW8FWVUbQi-hejc4l85EthVD3G2QDtEYK5-vKm5YkFqMpId2xHPud71GvX1HJUbBgY1bsj8qGEvdxNcs2fTXezpGjHpicyUthRPIlXDDEBPwVdZwROHw/s220/P2230079.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-107421633532789675.post-4712129090767608884</id><published>2012-09-18T10:41:00.000+02:00</published><updated>2012-09-19T19:30:13.193+02:00</updated><title type='text'>The New Censorship</title><content type='html'>This time I will not write about technical topic but about my concerns about the impact of a few big companies controlling digital content.&lt;br /&gt;
&lt;h2&gt;
Apple censoring political satire&lt;/h2&gt;
On August 19th I submitted my new game LeaderFlip to the Apple Appstore. LeaderFlip is a satiric, political game where the player is flipping a&amp;nbsp;caricature&amp;nbsp;of Germany&amp;nbsp;chancellor Merkel to the moon. The game play is similar to doodle jump, you have to make Merkel jump on floating platforms to get her as high as possible. The idea is&amp;nbsp;derived&amp;nbsp;from&amp;nbsp;a German idiom, where shooting somebody to the moon means you want to get rid of somebody.&lt;br /&gt;
LeaderFlip is already available on the Windows Phone Marketplace since July and received only positive press coverage.&lt;br /&gt;
About ten days after the submission to the Appstore I got an email from Apple stating that LeaderFlip needs some more review time.&lt;br /&gt;
On September 11th I finally got notice that LeaderFlip is rejected because of:&lt;br /&gt;
-------------&lt;br /&gt;
&lt;span style=&quot;background-color: #eef2f4; color: #333333; font-family: &#39;Lucida Grande&#39;, Geneva, Verdana, Arial; font-size: 13px; line-height: 22.100000381469727px;&quot;&gt;16.1&lt;/span&gt;&lt;br /&gt;
&lt;br style=&quot;background-color: #eef2f4; color: #333333; font-family: &#39;Lucida Grande&#39;, Geneva, Verdana, Arial; font-size: 13px; line-height: 22.100000381469727px;&quot; /&gt;
&lt;span style=&quot;background-color: #eef2f4; color: #333333; font-family: &#39;Lucida Grande&#39;, Geneva, Verdana, Arial; font-size: 13px; line-height: 22.100000381469727px;&quot;&gt;We found that your app contains content that many audiences would find objectionable, which is not in compliance with the&lt;/span&gt;&lt;a href=&quot;https://developer.apple.com/appstore/resources/approval/guidelines.html&quot; style=&quot;background-color: #eef2f4; color: #4673cb; font-family: &#39;Lucida Grande&#39;, Geneva, Verdana, Arial; font-size: 13px; line-height: 22.100000381469727px; text-decoration: none;&quot;&gt;App Store Review Guidelines&lt;/a&gt;&lt;span style=&quot;background-color: #eef2f4; color: #333333; font-family: &#39;Lucida Grande&#39;, Geneva, Verdana, Arial; font-size: 13px; line-height: 22.100000381469727px;&quot;&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;br style=&quot;background-color: #eef2f4; color: #333333; font-family: &#39;Lucida Grande&#39;, Geneva, Verdana, Arial; font-size: 13px; line-height: 22.100000381469727px;&quot; /&gt;
&lt;span style=&quot;background-color: #eef2f4; color: #333333; font-family: &#39;Lucida Grande&#39;, Geneva, Verdana, Arial; font-size: 13px; line-height: 22.100000381469727px;&quot;&gt;Specifically, we noticed your app includes images of &quot;German Chancellor &#39;Angie Make&#39;&quot; tied up, as well as that she is propelled by farts.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
-------------&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;iframe allowfullscreen=&#39;allowfullscreen&#39; webkitallowfullscreen=&#39;webkitallowfullscreen&#39; mozallowfullscreen=&#39;mozallowfullscreen&#39; width=&#39;320&#39; height=&#39;266&#39; src=&#39;https://www.youtube.com/embed/Tp9Q5hCtj1o?feature=player_embedded&#39; frameborder=&#39;0&#39;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;br /&gt;
You can have a look at the trailer to make your own judgment on this.&lt;br /&gt;
Rule 16.1 of the Appstore&amp;nbsp;guidelines&amp;nbsp;says:&lt;br /&gt;
&lt;span style=&quot;background-color: white; color: #333333; font-family: &#39;Lucida Grande&#39;, Geneva, Arial, Verdana, sans-serif; font-size: 14px; line-height: 21px;&quot;&gt;&quot;Apps that present excessively objectionable or crude content will be rejected&quot;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; color: #333333; font-family: &#39;Lucida Grande&#39;, Geneva, Arial, Verdana, sans-serif; font-size: 14px; line-height: 21px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
In Germany political satire and caricature has a long history and is a crucial part of all printed media. Depicting a politician tied up in the way we did in the game is comparable soft to what you will find in reputable German newspapers and magazines. And nobody has regarded the game &quot;excessively objectionable or crude&quot; so far.&lt;br /&gt;
&lt;br /&gt;
On the other hand, rule 14.2 of the guidelines say:&lt;br /&gt;
&lt;span style=&quot;background-color: white; color: #333333; font-family: &#39;Lucida Grande&#39;, Geneva, Arial, Verdana, sans-serif; font-size: 14px; line-height: 21px;&quot;&gt;&quot;Professional political satirists and humorists are exempt from the ban on offensive or mean-spirited commentary&quot;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So, now who is to decide, what is &quot;excessively objectionable or crude&quot; or what is &quot;Professional political satirists&quot;? Of course it is Apple who is deciding according to their political and moral views.&lt;br /&gt;
&lt;h2&gt;
Microsoft censoring &quot;provocative imagery&quot;&lt;/h2&gt;
Just when I got angry about Apple driving me closer to my financial ruin because I cannot publish the game that I have been working on for the last months, I got a strange email from Microsoft:&lt;br /&gt;
--------&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Dear Developer,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;This is to notify you that we are updating the 
Windows Phone Marketplace algorithms in order to enhance discoverability
 of applications targeting the broadest set of customers. As such, your 
applications listed below may be less visible
 to the average customer in the catalog. Your applications still can be 
discovered through search on the Windows Phone Marketplace.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Additional applications of yours may be impacted, 
and it could take time before you see any changes to the Windows Phone 
Marketplace.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Applications impacted:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;color: #e46c0a; mso-style-textfill-fill-alpha: 100.0%; mso-style-textfill-fill-color: #E46C0A;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;BulletBabs&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;More information regarding the changes can be &lt;a href=&quot;http://windowsteamblog.com/windows_phone/b/windowsphone/archive/2012/09/12/coming-soon-a-new-website-and-online-app-store.aspx&quot;&gt;
found here&lt;/a&gt;. &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;We look forward to seeing your application updates and new applications on the Windows Phone Marketplace.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Windows Phone Marketplace Team&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
--------&lt;br /&gt;
In other words, they are throwing Bullet Babs out of the Marketplace, for reasons they are not even telling in the email. They just give a link to a blog post:&lt;br /&gt;
&lt;a href=&quot;http://windowsteamblog.com/windows_phone/b/windowsphone/archive/2012/09/12/coming-soon-a-new-website-and-online-app-store.aspx&quot;&gt;http://windowsteamblog.com/windows_phone/b/windowsphone/archive/2012/09/12/coming-soon-a-new-website-and-online-app-store.aspx&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
Only after asking back for the reasons I got the reply:&lt;br /&gt;
---------&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;b&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;Actions Required to Remove the Visibility Impact:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;&lt;span style=&quot;color: windowtext;&quot;&gt;Update and resubmit your iconography with less provocative and suggestive imagery and content.&lt;/span&gt;&lt;span style=&quot;color: #1f497d;&quot;&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;span style=&quot;color: windowtext;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
---------&lt;br /&gt;
In short, Microsoft decided to censor out games, that do not even infringe the marketplace rules. And they do not even have the guts to tell the developers directly, but hide it inside a blogpost about enhancing the marketplace. Now, let us have a look at my &quot;provocative and suggestive imagery&quot;:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://www.klutzgames.com/appstore_icon_512x512.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;http://www.klutzgames.com/appstore_icon_512x512.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Well, it is a girl in a dress holding a gun... Skirt to short? Breasts to big? I don&#39;t know...&lt;br /&gt;
&lt;h2&gt;
Moral and culture defined by companies&lt;/h2&gt;
When looking at big companies we usually worry about cartels threatening the free markets. I think, it is also time to worry about big companies threatening our culture. If we have a look at the smartphone market, we see that there are three global players restricting the content:&lt;br /&gt;
- Apple&lt;br /&gt;
- Google&lt;br /&gt;
- Microsoft (well, WP7 is still not important)&lt;br /&gt;
If you look at online games or private digital data filtering you will also have to look at&lt;br /&gt;
- Facebook&lt;br /&gt;
&lt;br /&gt;
All companies have in common that they define their own guidelines and restrict digital content according to their own moral, cultural as well as political views. As digital content becomes more and more important, their influence will become more dominant.&lt;br /&gt;
&lt;br /&gt;
As a German citizen I see this even more crucial, as German cultural values and moral is different to North American ones. For example, in Germany&amp;nbsp;violent&amp;nbsp;content is regarded more critical then sexual content. Whereas the &quot;Nipplegate&quot; incident teach us how sensitive USA citizens react on sexual content.&lt;br /&gt;
Well, censorship on itself is a difficult topic and this is not what I want to discuss here. My point is, that the censorship is not done by an&amp;nbsp;independent&amp;nbsp;agency anymore, as we see this with games that are traditionally published. And the censorship rules are not according to the&amp;nbsp;country&#39;s&amp;nbsp;laws.&lt;br /&gt;
No, the rules are defined and applied by the companies that run the digital distribution shops or platforms. And by that, they impose their moral, cultural and political views to their customers.&lt;br /&gt;
&lt;br /&gt;
For me, as an indie-developer, the arbitrary decisions are very&amp;nbsp;annoying&amp;nbsp;to handle. But besides the business concerns, I am also concerned about companies creating a moral and culture monopoly.&lt;br /&gt;
Will we in future only be able to see cute &quot;angry&quot; birds and &quot;cute&quot; zombies?&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
*** Update ***&lt;/h3&gt;
&lt;div&gt;
After discussion with Apple they finally published LeaderFlip on the App Store without changes. It &amp;nbsp;took exactly one month from submission to publish. But at least I am happy that I did not have to change the content.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://klutzgames.blogspot.com/feeds/4712129090767608884/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://klutzgames.blogspot.com/2012/09/the-new-censorship.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default/4712129090767608884'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default/4712129090767608884'/><link rel='alternate' type='text/html' href='http://klutzgames.blogspot.com/2012/09/the-new-censorship.html' title='The New Censorship'/><author><name>Timo Fleisch</name><uri>http://www.blogger.com/profile/18171872141745431561</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsaCQIqmHrvkkW8FWVUbQi-hejc4l85EthVD3G2QDtEYK5-vKm5YkFqMpId2xHPud71GvX1HJUbBgY1bsj8qGEvdxNcs2fTXezpGjHpicyUthRPIlXDDEBPwVdZwROHw/s220/P2230079.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107421633532789675.post-7379202172551839395</id><published>2012-04-20T16:47:00.000+02:00</published><updated>2013-01-14T16:42:17.260+01:00</updated><title type='text'>Localization with C# Extensions</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
In this short post I am going to describe how I handle localization for different platforms. Actually each mobile platform comes with its own approach to this topic. But when you develop cross platform you probably don&#39;t want to complicate things by using the native solutions.&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Therefore I came up with a very simple implementation that is just enough for my needs. Basically, in my approach localization just means to replace a text string with a text string for the local language. I do this by using three things:&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;An xml file with the localized strings,&lt;/li&gt;
&lt;li&gt;a singleton class to handle the strings and&lt;/li&gt;
&lt;li&gt;an Extension to the C# String class.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Insinde the xml file I declare a &lt;i&gt;Text&lt;/i&gt; node with a &lt;i&gt;name&lt;/i&gt; attribute, which is the identifier for the text. For me the identifier already is the default text. If you work with a bigger project it might be better to use a pure placeholder text instead. Inside the &lt;i&gt;Text&lt;/i&gt; node there are &lt;i&gt;Item&lt;/i&gt; nodes. Each &lt;i&gt;Item &lt;/i&gt;node has an attribute &lt;i&gt;language &lt;/i&gt;and &lt;i&gt;value&lt;/i&gt;. As language identifier I use the&amp;nbsp;&amp;nbsp;ISO 639-1 two-letter code which you can &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.twoletterisolanguagename.aspx&quot; target=&quot;_blank&quot;&gt;obtain easily in dot Net&lt;/a&gt;. The &lt;i&gt;value &lt;/i&gt;is obviously the translated text. This is an example of my xml file:&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&amp;gt;
&amp;lt;TgexLocalization&amp;gt;
  &amp;lt;Text name=&quot;Score&quot;&amp;gt;
    &amp;lt;Item language=&quot;de&quot; value=&quot;Punkte&quot;&amp;gt;&amp;lt;/Item&amp;gt;
  &amp;lt;/Text&amp;gt;
  &amp;lt;Text name=&quot;Multiplier&quot;&amp;gt;
    &amp;lt;Item language=&quot;de&quot; value=&quot;Multiplikator&quot;&amp;gt;&amp;lt;/Item&amp;gt;
  &amp;lt;/Text&amp;gt;
&amp;lt;/TgexLocalization&amp;gt;
&lt;/pre&gt;
&lt;div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
The localization file and data is then handled by a singleton class, the &lt;i&gt;Localizer&lt;/i&gt;. Before using the &lt;i&gt;Localizer &lt;/i&gt;the &lt;i&gt;Initialize &lt;/i&gt;function has to be called once, giving the xml file filename as parameter. The &lt;i&gt;Localizer &lt;/i&gt;just has a dictionary of a string as key and string as value. When it parses the xml file it will just add entries to the dictionary when a &lt;i&gt;Text &lt;/i&gt;node with an &lt;i&gt;Item &lt;/i&gt;of the current language ID is found. In the above example, the dictionary would only be filled if the local system is German. In this case the dictionary would get two entries.&lt;/div&gt;
To get a localized text, you can now simple call&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Localizer.Instance.GetText(&quot;Score&quot;);&lt;/span&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
If your system is not German, it would just return the same string that you passed as paramater, &lt;i&gt;&quot;Score&quot;&lt;/i&gt;. But if your system is German it finds the entry in the dictionary and returns &lt;i&gt;&quot;Punkte&quot;&lt;/i&gt;.&lt;/div&gt;
The full &lt;i&gt;Localizer.cs&lt;/i&gt; looks like this:&lt;/div&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.Text;
using System.Globalization;
using System.IO;

#if ANDROID
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
#endif

namespace Tgex
{
    public class Localizer
    {
        protected String m_tag;
        /// &amp;lt;summary&amp;gt;
        /// String tag that defines the languages (2 char)
        /// &amp;lt;/summary&amp;gt;
        public String Tag
        {
            get { return m_tag; }
            set { m_tag = value; }
        }

        Dictionary&amp;lt;string, string&amp;gt; m_strings = new Dictionary&amp;lt;string, string&amp;gt;();

        // create singleton
        static readonly Localizer instance = new Localizer();
        /// &amp;lt;summary&amp;gt;
        /// Get instance of singleton.
        /// &amp;lt;/summary&amp;gt;
        public static Localizer Instance
        {
            get
            {
                return instance;
            }
        }
        /// &amp;lt;summary&amp;gt;
        /// Explicit static constructor to tell C# compiler
        /// not to mark type as beforefieldinit
        /// &amp;lt;/summary&amp;gt;
        static Localizer()
        {
        }
        /// &amp;lt;summary&amp;gt;
        /// Constructor
        /// &amp;lt;/summary&amp;gt;
        Localizer()
        {
            m_tag = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
        }

        public void Initialize(string filename)
        {
#if ANDROID
   var reader = new StreamReader(Game.Activity.Assets.Open (filename));
            XDocument xmlFile = XDocument.Load(reader);
#else

            XDocument xmlFile = XDocument.Load(filename);
#endif
            XElement root = xmlFile.Element(&quot;TgexLocalization&quot;);

            // read strings
            var texts = root.Descendants(&quot;Text&quot;);
            if (texts != null)
            {
                texts.ForEach(text =&amp;gt;
                {
                    var items = text.Elements(&quot;Item&quot;);
                    if (items != null)
                    {
                        XElement locStringXml = items.FirstOrDefault(item =&amp;gt; item.Attribute(&quot;language&quot;).Value.ToString() == m_tag);
                        if (locStringXml != null)
                        {
                            m_strings.Add(text.Attribute(&quot;name&quot;).Value.ToString(), locStringXml.Attribute(&quot;value&quot;).Value.ToString());
                        }
                    }
                });
            }
        }

        public String GetText(string name)
        {
            if (m_strings.ContainsKey(name))
            {
                return m_strings[name];
            }
            return name;
        }
    }
}

&lt;/pre&gt;
&lt;div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
To make the access&amp;nbsp;simpler&amp;nbsp;I use C# &lt;i&gt;Extensions&lt;/i&gt;. I love this feature of C# and my &lt;i&gt;Extensions&lt;/i&gt; class is actually very huge - I will probably post some of my most useful code in other blog posts. For now, I just show an extension to the String class. I define an extension function&lt;i&gt; Localize()&lt;/i&gt;, that makes the call to the &lt;i&gt;Localizer&lt;/i&gt; class. By that, I can&amp;nbsp;localize&amp;nbsp;a string by writing:&lt;/div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&quot;Score&quot;.Localize();&lt;/span&gt;&lt;br /&gt;
The &lt;i&gt;Extensions.cs&lt;/i&gt; class for that looks like this:&lt;/div&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Tgex
{
    public static class Extensions
    {
        public static String Localize(this String text)
        {
            return Localizer.Instance.GetText(text);
        }
        // helper so that you can use ForEach on any IEnumerable
        public static void ForEach&amp;lt;T&amp;gt;(this IEnumerable&amp;lt;T&amp;gt; values, Action&amp;lt;T&amp;gt; action)
        {
            foreach (var v in values)
            {
                action(v);
            }
        }
    }
}
&lt;/pre&gt;
&lt;div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Even though this only translates text, you can use it also for resource strings. I use it for texture names, so I can also easily localize buttons with text on it.&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
This is already all that I need for localization of my games. I hope this little and simple approach might be useful for some cross platform developers.&lt;/div&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://klutzgames.blogspot.com/feeds/7379202172551839395/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://klutzgames.blogspot.com/2012/04/localization-with-c-extensions.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default/7379202172551839395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default/7379202172551839395'/><link rel='alternate' type='text/html' href='http://klutzgames.blogspot.com/2012/04/localization-with-c-extensions.html' title='Localization with C# Extensions'/><author><name>Timo Fleisch</name><uri>http://www.blogger.com/profile/18171872141745431561</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsaCQIqmHrvkkW8FWVUbQi-hejc4l85EthVD3G2QDtEYK5-vKm5YkFqMpId2xHPud71GvX1HJUbBgY1bsj8qGEvdxNcs2fTXezpGjHpicyUthRPIlXDDEBPwVdZwROHw/s220/P2230079.JPG'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107421633532789675.post-6201685793460717523</id><published>2012-03-27T16:29:00.000+02:00</published><updated>2012-03-27T16:29:26.270+02:00</updated><title type='text'>Using Amazon SimpleDB for Runtime App-Parameter Editing</title><content type='html'>When you develop an app, you probably have a few parameters that you need to adjust and tweak to find the desired value. The usual approach would be to change the parameter in the source code, recompile and deploy the app to your phone to test it. If you have a lot of parameters to tweak, you probably add a developer GUI &amp;nbsp;to your app that enables you to change the parameters at runtime.&lt;br /&gt;
In this blog post I present an easy to integrate alternative. Instead of reading the values from your source code or an in game GUI, the parameter values are stored and retrieved in a cloud database. The technology is build onto my former blog post about using Amazon SimpleDB, hence for this we use SimpleDB again. The idea of this approach is like this:&lt;br /&gt;
Store all parameters you want to edit in an own class, e.g. &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;AppParameter&lt;/span&gt;. When running your app in &lt;i&gt;edit mode&lt;/i&gt;&amp;nbsp;you will retrieve the values for &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;AppParameter &lt;/span&gt;from the database. On your PC you run a .NET application that allows you to edit the database parameters. Reread the values inside your app and test the changed parameters. No need to recompile or even restart you app and edit the parameters from any PC.&lt;br /&gt;
To make the integration easy I present a solution that uses C# reflections to automatically determine the fields of the &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;AppParameter &lt;/span&gt;class. Saving and reading the parameter class to and from the SimpleDB uses generics. That means you can use the code for any class you define. Also the PC-Editor automatically creates the GUI for the class parameters. This is a picture of the Editor using some arbitrary game parameters:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjQLNHTgqi66rBC7M0l_EZh3W8H8gRbx9sHMRDe3fmvn74Ynq1FbgVJgEkjQLdqDBxwO8ep_OmVRx6q5fCSNXsaW7lzxU0sVtNvN7onAxAvQHMc4rHe-CWIffUIDbKGspAy34Ea4jdTXw1/s1600/paramtereditor.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjQLNHTgqi66rBC7M0l_EZh3W8H8gRbx9sHMRDe3fmvn74Ynq1FbgVJgEkjQLdqDBxwO8ep_OmVRx6q5fCSNXsaW7lzxU0sVtNvN7onAxAvQHMc4rHe-CWIffUIDbKGspAy34Ea4jdTXw1/s1600/paramtereditor.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
The parameter class used here:&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public class AppParamter
{
    public float JumpForce;
    public float Gravity;
    public float Height;
    public float Weight;
    public Vector2 StartPosition;
    public Vector2 LevelOffset;
    public int NumOfLives;
    public int MaxItems;
    public int MinItems;
}
&lt;/pre&gt;
If you want to use this with your app you only have to change the &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;AppParameter &lt;/span&gt;class to contain the parameters you need. However, I currently only support the data format &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;float&lt;/span&gt;, &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Vector2 &lt;/span&gt;and &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;int&lt;/span&gt;. If you need other formats you need to extend the example.&lt;br /&gt;
The Editor provides buttons to read and write the values from and to the Amazon SimpleDB. With the &lt;i&gt;Clear DB&lt;/i&gt; button you can delete the complete entry for this parameter class. This is&amp;nbsp;recommendable&amp;nbsp;every time&amp;nbsp;you &amp;nbsp;change the structure of the parameter class.&lt;i&gt;&amp;nbsp;Copy Values&lt;/i&gt; creates a code&amp;nbsp;snippet&amp;nbsp;and copies it to the clipboard&amp;nbsp;that sets the current values of your class. Use this once you finalized your parameters to set the values inside your app without the database. The code snippet created for this example is:&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public void SetValues()
{
    JumpForce = 2.3f;
    Gravity = 7f;
    Height = 12f;
    Weight = 55f;
    StartPosition = new Vector2(12f, 25f);
    LevelOffset = new Vector2(-3f, -2f);
    NumOfLives = 7;
    MaxItems = 5;
    MinItems = 1;
}
&lt;/pre&gt;
&lt;h3&gt;







Implementation&lt;/h3&gt;
The core class of this project is the &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;ParameterProcessor&lt;/span&gt;. It is realized as a singleton and provides the interface to the database. Furthermore it provides functions to create strings from values and the other way round.&amp;nbsp;You will find a lot of similarities to my previous SimpleDB blog post.&lt;br /&gt;
The class is designed to be used from the PC-Editor as well as from the phone app. Therefore I did not use the Amazon AWS SDK for .NET for the SimpleDB access from Windows, but used the SDK designed for the Windows Phone. For that I needed to create Windows Library Project and add the SDK source files. Compiling and running it from Windows worked smooth with only one exception. In &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;SimpleDBResponsce.cs&lt;/span&gt; line 39, the &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;IsRequestSuccessful&lt;/span&gt; property for set is declared protected. This caused the &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;XmlSerializer &lt;/span&gt;to throw an Exception. Removing the protected modifier solved the problem. Now let us take a look at the code. In the beginning the singleton is defined and in the constructor the amazon client is&amp;nbsp;initialized. Don&#39;t forget to enter your SimpleDB keys there.&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;    public class ParameterProcessor
    {
        #region singleton
        // create singleton
        static readonly ParameterProcessor instance = new ParameterProcessor();
        /// &amp;lt;summary&amp;gt;
        /// Get instance of singleton.
        /// &amp;lt;/summary&amp;gt;
        public static ParameterProcessor Instance
        {
            get
            {
                return instance;
            }
        }
        /// &amp;lt;summary&amp;gt;
        /// Explicit static constructor to tell C# compiler
        /// not to mark type as beforefieldinit
        /// &amp;lt;/summary&amp;gt;
        static ParameterProcessor()
        {
        }
        #endregion

        // db
        AmazonSimpleDB m_sdb;

        /// &amp;lt;summary&amp;gt;
        /// Constructor
        /// &amp;lt;/summary&amp;gt;
        ParameterProcessor()
        {
            // intitialize db
            // amazon cloud access
            m_sdb = AWSClientFactory.CreateAmazonSimpleDBClient(&quot;YourPublicKey&quot;, &quot;YourPrivatKey&quot;);
        }
&lt;/pre&gt;
The function SaveToDB uses generics to pass the parameter class and instance of which values are stored in the database. The second function parameter is the name of the domain in SimpleDB. The domain needs to be created before. The response handler, which is called after the parameters have been stored in the database, currently does nothing. Using C# reflections the fields of the parameter class are easily iterated through an &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;FieldInfo &lt;/span&gt;array provided by the function G&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;etFields()&lt;/span&gt; from the &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Type &lt;/span&gt;class. The database then simply stores the field name as an attribute with the field value converted to a string. Additionally I save a time stamp that could be used to check if data has been updated without retrieving all attribute. This could make sense if the data you store is very huge. The complete class values are entered as one item into SimpleDB where the parameter class name is used as key value for the item. By that you could store multiple different parameter classes within one SimpleDB domain.&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;/// &amp;lt;summary&amp;gt;
/// Takes a class and enters its fields to an Amazon SimpleDB
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;typeparam name=&quot;T&quot;&amp;gt;Serializable Class to be saved into the database&amp;lt;/typeparam&amp;gt;
/// &amp;lt;param name=&quot;data&quot;&amp;gt;Class instance that is saved into the database&amp;lt;/param&amp;gt;
/// &amp;lt;param name=&quot;tableName&quot;&amp;gt;Name of domain in SimpleDB&amp;lt;/param&amp;gt;
public void SaveToDB&amp;lt;T&amp;gt;(T data, string tableName)
{
    SimpleDBResponseEventHandler&amp;lt;object, ResponseEventArgs&amp;gt; handler = null;
    handler = delegate(object senderAmazon, ResponseEventArgs args)
    {
        //Unhook from event.
        m_sdb.OnSimpleDBResponse -= handler;
        PutAttributesResponse response = args.Response as PutAttributesResponse;
        if (null != response)
        {
        }
        else
        {
        }
    };

    m_sdb.OnSimpleDBResponse += handler;

    string structName = data.GetType().Name;
    PutAttributesRequest putAttributesRequest = new PutAttributesRequest { DomainName = tableName, ItemName = structName };
    List&amp;lt;ReplaceableAttribute&amp;gt; attributesOne = putAttributesRequest.Attribute;

    Type type = data.GetType();
    System.Reflection.FieldInfo[] fields = type.GetFields();
    foreach (System.Reflection.FieldInfo field in fields)
    {
        string valueString = FieldToString(field, data);
        attributesOne.Add(new ReplaceableAttribute().WithName(field.Name).WithValue(valueString).WithReplace(true));
    }
    attributesOne.Add(new ReplaceableAttribute().WithName(&quot;TimeStamp&quot;).WithValue(DateTime.Now.Ticks.ToString()).WithReplace(true));

    m_sdb.PutAttributes(putAttributesRequest);
}
&lt;/pre&gt;
The &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;ReadFromDB &lt;/span&gt;function also uses generics and reads the values from the database into the passed parameter class instance. Additionally you can pass an &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Action &lt;/span&gt;delegate, that is called after the data is received. Remember that the database calls are asynchronous, so if you for example need to refresh your GUI after the new values are received, you can use this delegate.&lt;br /&gt;
The select request retrieves the SimpleDB item with the key value (itemName) of the parameter class name. The request handler then iterates through the retrieved attributes and using reflections sets the values into the fields of the parameter class instance.&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;/// &amp;lt;summary&amp;gt;
/// Reads values from a SimpleDB and writes it into a class instance.
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;typeparam name=&quot;T&quot;&amp;gt;Serializable Class that is read from the database&amp;lt;/typeparam&amp;gt;
/// &amp;lt;param name=&quot;data&quot;&amp;gt;Class instance where the database values are written into&amp;lt;/param&amp;gt;
/// &amp;lt;param name=&quot;tableName&quot;&amp;gt;Name of domain in SimpleDB&amp;lt;/param&amp;gt;
/// &amp;lt;param name=&quot;readFinished&quot;&amp;gt;A delegate that is called when reading the values has finished. Set null if not needed.&amp;lt;/param&amp;gt;
public void ReadFromDB&amp;lt;T&amp;gt;(T data, string tableName, Action readFinished)
{
    // create response handler and delegate
    SimpleDBResponseEventHandler&amp;lt;object, ResponseEventArgs&amp;gt; handler = null;

    handler = delegate(object sender, ResponseEventArgs args)
    {
        //Unhook from event.
        m_sdb.OnSimpleDBResponse -= handler;
        SelectResponse response = args.Response as SelectResponse;

        if (null != response)
        {
            Type type = data.GetType();
            System.Reflection.FieldInfo[] fields = type.GetFields();

            SelectResult selectResult = response.SelectResult;
            if (null != selectResult)
            {
                foreach (Item item in selectResult.Item)
                {
                    // actually should just be one item
                    foreach (Amazon.SimpleDB.Model.Attribute attribute in item.Attribute)
                    {
                        var field = fields.FirstOrDefault(f =&amp;gt; f.Name == attribute.Name);
                        if (field != null)
                        {
                            StringToFieldValue(field, data, attribute.Value);
                        }
                    }
                }
            }
            if (readFinished != null)
            {
                readFinished.Invoke();
            }
        }
    };
    m_sdb.OnSimpleDBResponse += handler;

    string structName = data.GetType().Name;
    // create request
    string sql = &quot;SELECT * FROM &quot; + tableName + &quot; WHERE itemName()=&#39;&quot; + structName + &quot;&#39;&quot;;
    m_sdb.Select(new SelectRequest { SelectExpression = sql, ConsistentRead = true });
}
&lt;/pre&gt;
SimpleDB can only store string values, therefore the parameter class field have to be converted to a string. This is done by the &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;FieldToString &lt;/span&gt;function. The current implementation explicitly only supports float, int and Vector2. You can add more types if you need them here.&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;/// &amp;lt;summary&amp;gt;
/// Using reflection to get a value string of a class field.
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name=&quot;field&quot;&amp;gt;The field of the class to get the value from&amp;lt;/param&amp;gt;
/// &amp;lt;param name=&quot;data&quot;&amp;gt;Class instance with values&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
public String FieldToString(System.Reflection.FieldInfo field, object data)
{
    string valueString;
    if (field.FieldType == typeof(float))
    {
        valueString = ((float)field.GetValue(data)).ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
    }
    else if (field.FieldType == typeof(Vector2))
    {
        Vector2 vec = (Vector2)field.GetValue(data);

        System.Globalization.NumberFormatInfo nfi
                = System.Globalization.CultureInfo.InvariantCulture.NumberFormat;
        valueString = vec.X.ToString(nfi) + &quot;, &quot;
                    + vec.Y.ToString(nfi);
    }
    else
    {
        // just use the default ToString for all other field types
        // extend it if you need special handling like the types before
        valueString = field.GetValue(data).ToString();
    }
    return valueString;
}
&lt;/pre&gt;
The complement function to the above takes a string and writes the value into the field of the passed instance. Again only float, int and Vector2 is supported here.&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;/// &amp;lt;summary&amp;gt;
/// Using reflection to set a class field from a value string.
/// Currently only float, Vector2 and int is supported.
/// Extend for you needs.
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name=&quot;field&quot;&amp;gt;The field of the class for which the value will be set.&amp;lt;/param&amp;gt;
/// &amp;lt;param name=&quot;data&quot;&amp;gt;Class instance where the value will be stored into&amp;lt;/param&amp;gt;
/// &amp;lt;param name=&quot;valueString&quot;&amp;gt;A string containing a value for the field&amp;lt;/param&amp;gt;
public void StringToFieldValue(System.Reflection.FieldInfo field, object data, string valueString)
{
    if (field.FieldType == typeof(float))
    {
        field.SetValue(data, float.Parse(valueString, System.Globalization.CultureInfo.InvariantCulture.NumberFormat));
    }
    else if (field.FieldType == typeof(Vector2))
    {
        System.Globalization.NumberFormatInfo nfi
            = System.Globalization.CultureInfo.InvariantCulture.NumberFormat;
        String[] values = valueString.Split(&#39;,&#39;);
        Vector2 point = new Vector2();
        try
        {
            point.X = float.Parse(values[0], nfi);
            point.Y = float.Parse(values[1], nfi);
        }
        catch
        {
            // oh no
        }
        field.SetValue(data, point);
    }
    if (field.FieldType == typeof(int))
    {
        field.SetValue(data, Int32.Parse(valueString, System.Globalization.CultureInfo.InvariantCulture.NumberFormat));
    }
    else
    {
        // unsupported type
    }
}
&lt;/pre&gt;
The Windows &lt;i&gt;DB Parameter Editor&lt;/i&gt; uses the above class to read and write to and from the database. I will not go much into the details of the editor source code here. Worth mentioning is the dynamic creation of the parameter GUI. Therefore exists a base class &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;ParameterControl&lt;/span&gt;, which is derived from &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;UserControl&lt;/span&gt;. This base class also has a static function &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;CreateParameterControl&lt;/span&gt;, which serves as a factory for the actual derived parameter controls. According to the type of the passed &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;FieldInfo &lt;/span&gt;different controls can be generated. Anyhow, in this example I only implemented the TextBoxParameterControl, where you enter the values into a simple text box. Possible extensions could for example be a slider control for floats, &amp;nbsp;a checkbox control for a bool parameter or a color picker control for a color field. Inside the main form (&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Form1.cs&lt;/span&gt;) the controls are then created like this:&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;Type type = classData.GetType();
System.Reflection.FieldInfo[] fields = type.GetFields();
int offset = 15;
foreach (System.Reflection.FieldInfo field in fields)
{
    ParameterControl control = ParameterControl.CreateParameterControl(field, classData);
    control.Top = offset;
    control.Left = 5;
    offset += control.Height;
    this.parameterGroupBox.Controls.Add(control);
}
&lt;/pre&gt;
Using the &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;ParameterProcessor &lt;/span&gt;class you can finally integrate the database access into your application. Just reread the parameter class values at your&amp;nbsp;convenience. You could add an update button, or reread every time you restart a level or even poll at a certain time interval.&lt;br /&gt;
&lt;h3&gt;
Download and Conclusion&lt;/h3&gt;
The complete source code of the &lt;i&gt;DB Parameter Editor&lt;/i&gt; can be downloaded from my homepage:&lt;br /&gt;
&lt;a href=&quot;http://www.klutzgames.com/download/DBParameterEditor.zip&quot;&gt;DBParameterEditor.zip&lt;/a&gt;&lt;br /&gt;
It is developed using Microsoft Visual Studio 2010 Express, but it should not be a problem to use it in MonoDevelop. I also included the AWSSDKWP7 (SDK for SimpleDB) as Windows binary, so that you can directly start testing.&lt;br /&gt;
&lt;br /&gt;
In this post I presented an easy way to tweak app parameters from a PC using a cloud database. This scenario can be extended in multiple directions. For example you could extend the Editor to become a more flexible game level editor. By that your game and level designers can modify levels on the running application. You could also extend it to be usable with a release version of a game. By that you can make game play adjustments without the need of an update.</content><link rel='replies' type='application/atom+xml' href='http://klutzgames.blogspot.com/feeds/6201685793460717523/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://klutzgames.blogspot.com/2012/03/using-amazon-simpledb-for-runtime-app.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default/6201685793460717523'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default/6201685793460717523'/><link rel='alternate' type='text/html' href='http://klutzgames.blogspot.com/2012/03/using-amazon-simpledb-for-runtime-app.html' title='Using Amazon SimpleDB for Runtime App-Parameter Editing'/><author><name>Timo Fleisch</name><uri>http://www.blogger.com/profile/18171872141745431561</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsaCQIqmHrvkkW8FWVUbQi-hejc4l85EthVD3G2QDtEYK5-vKm5YkFqMpId2xHPud71GvX1HJUbBgY1bsj8qGEvdxNcs2fTXezpGjHpicyUthRPIlXDDEBPwVdZwROHw/s220/P2230079.JPG'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjQLNHTgqi66rBC7M0l_EZh3W8H8gRbx9sHMRDe3fmvn74Ynq1FbgVJgEkjQLdqDBxwO8ep_OmVRx6q5fCSNXsaW7lzxU0sVtNvN7onAxAvQHMc4rHe-CWIffUIDbKGspAy34Ea4jdTXw1/s72-c/paramtereditor.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107421633532789675.post-5356435916389286352</id><published>2012-03-15T22:54:00.000+01:00</published><updated>2012-03-15T23:09:03.820+01:00</updated><title type='text'>Save and Read an Encrypted Data File</title><content type='html'>Your mobile game or app most probably has some data you want to store locally on the phone. Also there might be good reason why you don&#39;t want this saved data to be easily accessible and changeable from outside of your app. For the iPhone for example you can simply use &lt;a href=&quot;http://www.macroplant.com/iexplorer/&quot;&gt;iExplorer&lt;/a&gt;&amp;nbsp;to read and change any files of an app - no jailbreak needed. If you develop a game you might want to avoid that a user can easily cheat points and&amp;nbsp;achievements. If your app has in-app purchasable items you might even get financial loss if the user can easily cheat.&lt;br /&gt;
Luckily the .Net Framework comes with a lot of classes that make file encryption easy to implement. If you want to secure your data from manipulation you generally have two ways of achieving it:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Leave the data readable but add an&amp;nbsp;authentication&amp;nbsp;hash key.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Encrypt the complete data file.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
The first method is for example used by RESTful web services. In my previous post I talked about Amazon SimpleDB which uses a hash key for authentication&amp;nbsp;of the database requests. Take a look inside the library source code if you are interested in a working cross-platform implementation example.&lt;/div&gt;
&lt;div&gt;
The second method encrypts the complete data file. People&amp;nbsp;sneaking&amp;nbsp;into your data files will not be even able to read it and might not be tempted to try to alter the values.&lt;br /&gt;
In this post I will give an example for the second method. I will give an implementation that works well with Windows Phone, MonoTouch and Mono for Android and can be easily added to any app.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Application Flow&lt;/b&gt;&lt;br /&gt;
In this implementation the data that should be stored is located inside a &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;struct&lt;/span&gt;. Using XML serialization the struct is converted to XML which is then encrypted and finally stored as an isolated storage file.&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;struct -&amp;gt; XmlSerializer -&amp;gt; XmlWriter -&amp;gt; CryptoStream -&amp;gt; IsolatedStorageFileStream&lt;/span&gt;&lt;br /&gt;
When reading the encrypted file the flow is the other way round:&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;IsolatedStorageFileStream&amp;nbsp;-&amp;gt; CryptoStream -&amp;gt; XmlSerializer -&amp;gt; struct&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Implementation&lt;/b&gt;&lt;br /&gt;
Start by adding the following using statements to your source file:
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Security;
using System.Security.Cryptography;
using System.IO.IsolatedStorage;
&lt;/pre&gt;
In my example I use the following data structure, which is some simple game data.
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public struct SaveGameStruct
{
    public string Name;
    public int HiScore;
    public int NumOfCoins;
    public DateTime Date;
    public string Guid;
}
&lt;/pre&gt;
Next store a password and a salt as member variable string:
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;string m_password = &quot;7Sj)fjfdHf734Jjd&quot;;
string m_salt = &quot;hHeh=j84&quot;;
&lt;/pre&gt;
The password is not the actual password that is used to encode your data file. Instead it is used to create a key that then is used for encryption. The &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx&quot; target=&quot;_blank&quot;&gt;key generator&lt;/a&gt; uses pseudo random numbers, hence the &lt;a href=&quot;http://en.wikipedia.org/wiki/Cryptographic_salt&quot; target=&quot;_blank&quot;&gt;salt&lt;/a&gt;. Don&#39;t forget to change the password and salt values in your source code.&lt;br /&gt;
The function to save an encrypted file now looks like this:
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public void DoSaveGame()
{
    //Generate a Key based on a Password and HMACSHA1 pseudo-random number generator
    //Salt must be at least 8 bytes long
    //Use an iteration count of at least 1000
    Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(m_password, Encoding.UTF8.GetBytes(m_salt), 1000);

    //Create AES algorithm
    AesManaged aes = new AesManaged();
    //Key derived from byte array with 32 pseudo-random key bytes
    aes.Key = rfc2898.GetBytes(32);
    //IV derived from byte array with 16 pseudo-random key bytes
    aes.IV = rfc2898.GetBytes(16);
            
    string SAVEFILENAME = &quot;savegame.xml&quot;;

    IsolatedStorageFileStream storageStream = m_savegameStorage.OpenFile(SAVEFILENAME, FileMode.Create);
    XmlWriterSettings writerSettings =
    new XmlWriterSettings
    {
        Indent = true,
        IndentChars = &quot;\t&quot;
    };

    XmlSerializer serializer = new XmlSerializer(typeof(SaveGameStruct));

    CryptoStream cryptoStream = new CryptoStream(storageStream, aes.CreateEncryptor(), CryptoStreamMode.Write);

    using (XmlWriter xmlWriter = XmlWriter.Create(cryptoStream, writerSettings))
    {
        // m_saveGame is a member variable of the type SaveGameStruct which holds the data to be saved
        serializer.Serialize(xmlWriter, m_saveGame);
    }
    cryptoStream.FlushFinalBlock();
    cryptoStream.Close();
    storageStream.Close();
}
&lt;/pre&gt;
As you can see I use AesManaged, because this is an encryption class that I found to work with WP7, MonoTouch and Mono for Windows. That is all that is necessary to store a structure inside an encrypted file. The function to read the encrypted file is similar simple:
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;void LoadSaveGame()
{
    //Generate a Key based on a Password and HMACSHA1 pseudo-random number generator
    //Salt must be at least 8 bytes long
    //Use an iteration count of at least 1000
    Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(m_password, Encoding.UTF8.GetBytes(m_salt), 1000);

    //Create AES algorithm
    AesManaged aes = new AesManaged();
    //Key derived from byte array with 32 pseudo-random key bytes
    aes.Key = rfc2898.GetBytes(32);
    //IV derived from byte array with 16 pseudo-random key bytes
    aes.IV = rfc2898.GetBytes(16);

    string SAVEFILENAME = &quot;savegame.xml&quot;;
    if (m_savegameStorage.FileExists(SAVEFILENAME))
    {
        IsolatedStorageFileStream fs = null;
        try
        {
            fs = m_savegameStorage.OpenFile(SAVEFILENAME, System.IO.FileMode.Open);
        }
        catch (IsolatedStorageException)
        {
            // The file couldn&#39;t be opened, even though it&#39;s there.
            // You can use this knowledge to display an error message
            // for the user (beyond the scope of this example).
        }

        if (fs != null)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(SaveGameStruct));
            CryptoStream cryptoStream = new CryptoStream(fs, aes.CreateDecryptor(), CryptoStreamMode.Read);
            m_saveGame = (SaveGameStruct)serializer.Deserialize(cryptoStream);
        }
    }
    else
    {
        // if file is not found it is probably the first time the app launched - handle it properly
    }
}
&lt;/pre&gt;
As you can see it is pretty much similar to the file save function, just the streams are the other way round.&lt;br /&gt;
And this already completes the code for saving and reading an encrypted data file. Please note, that I didn&#39;t handle exceptions at the stream reading and writing parts. So you still have to add a proper exception handling here.&lt;br /&gt;
My solution was heavily inspired (and partly copy and pasted) from this &lt;a href=&quot;http://robtiffany.com/dont-forget-to-encrypt-your-windows-phone-7-data/&quot; target=&quot;_blank&quot;&gt;awesome blog post&lt;/a&gt;.&lt;br /&gt;
The encryption solution described here is not perfectly save against being hacked, as the password is saved in the source code and could be disassembled. If you have to encrypt critical data, like passwords, bank data or confidential company data, you should use a more save encryption method. But probably&amp;nbsp;cross platform implementation will be not as easily be achieved then. You can read more about this topic and a solution for Windows Phone &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/hh487164(v=VS.92).aspx&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://klutzgames.blogspot.com/feeds/5356435916389286352/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://klutzgames.blogspot.com/2012/03/save-and-read-encrypted-data-file.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default/5356435916389286352'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default/5356435916389286352'/><link rel='alternate' type='text/html' href='http://klutzgames.blogspot.com/2012/03/save-and-read-encrypted-data-file.html' title='Save and Read an Encrypted Data File'/><author><name>Timo Fleisch</name><uri>http://www.blogger.com/profile/18171872141745431561</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsaCQIqmHrvkkW8FWVUbQi-hejc4l85EthVD3G2QDtEYK5-vKm5YkFqMpId2xHPud71GvX1HJUbBgY1bsj8qGEvdxNcs2fTXezpGjHpicyUthRPIlXDDEBPwVdZwROHw/s220/P2230079.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107421633532789675.post-397862965363115006</id><published>2012-03-09T11:17:00.000+01:00</published><updated>2012-03-09T11:24:55.353+01:00</updated><title type='text'>Cross-Platform Global High-Score using Amazon SimpleDB</title><content type='html'>In this post I am going to describe my solution for a simple global high score that works with WP7, iOS and Android. I wasn&#39;t really following the development of web technologies for more than 10 years. So when looking for a global high score solution for my new game I needed to catch up with the recent technologies and then had to decide which one to use. I don&#39;t know if what I came up with is the best solution, but it is powerful yet simple and easy.&lt;br /&gt;
The preconditions for me for the global high score where:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;It should be easy and fast to implement and maintain.&lt;/li&gt;
&lt;li&gt;It should use standard web technologies.&lt;/li&gt;
&lt;li&gt;It should be scaleable.&lt;/li&gt;
&lt;li&gt;It should use the standard web http protocol.&lt;/li&gt;
&lt;li&gt;It should be secure,&lt;/li&gt;
&lt;li&gt;and it should be as cross platform as possible.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
When it came to a standard interface using http I soon was sure that web services are the way to go. From there I decided that a RESTful (&lt;a href=&quot;http://en.wikipedia.org/wiki/Representational_state_transfer&quot; target=&quot;_blank&quot;&gt;Representational state transfer&lt;/a&gt;) web service using XML should be most suited for .NET applications.&lt;/div&gt;
&lt;div&gt;
The next decision was&amp;nbsp;whether&amp;nbsp;to use my own virtual root server and setup the appropriate interface to a data base or use a cloud service. Even though there are a lot of tools available that support you to develop server side web services, in the end it looked like it would really brake the precondition of easy and fast implementation. Also scaling might get a problem if the game becomes very popular. I found that Amazon and Microsoft both offer a cloud service to a simple nosql database that already comes with a complete RESTful web service interface:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://aws.amazon.com/simpledb/&quot; target=&quot;_blank&quot;&gt;Amazon SimpleDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/windowsazure/dd179463.aspx&quot; target=&quot;_blank&quot;&gt;Microsoft Azure Storage Service: Table Service&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
I actually first wanted to try the Microsoft Azure Service, but just when I tried to open an account, the management service was down and kept being down for the whole afternoon. Not a good omen for a cloud service, so I decided to go for Amazon SimpleDB instead.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
Microsoft(!) offers a &lt;a href=&quot;http://blogs.msdn.com/b/interoperability/archive/2012/01/20/beta-of-aws-sdk-for-windows-phone-released.aspx&quot; target=&quot;_blank&quot;&gt;SDK for Windows Phone&lt;/a&gt; (though still beta) for the Amazon cloud services and of course Amazon offers SDKs for iOS and Android. But the cool part is, that the Windows Phone SDK comes with &lt;b&gt;source code&lt;/b&gt; and can therefore be easily used with MonoTouch and Mono for Android as well! Using the SDK there is no need to write low level client side RESTful web services yourself, instead you have an easy to use interface to the Amazon SimpleDB data base.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Setting up the Amazon SDK&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
The source code for the AWS-SDK for Windows Phone is available from a &lt;a href=&quot;https://github.com/Microsoft-Interop/AWS-SDK-for-WP&quot; target=&quot;_blank&quot;&gt;GIT-Hub repository&lt;/a&gt;. So first check out the source code to a local directory. It comes with a complete set of samples for different Amazon cloud services. Inside the directory&amp;nbsp;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;AWSWP7SDK &lt;/span&gt;you find the actual sdk. For WP7 you just have to include the project file&amp;nbsp;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;AWSSDKWP7.csproj &lt;/span&gt;to your game solution and add the project as reference to your game.&lt;/div&gt;
&lt;div&gt;
For MonoTouch and Mono for Android you have to create a new project file for each. Just create a new MonoTouch and Mono for Android library and add all the SDK files. Then you need to make small changes in two files:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Amazon.Runtime\AWSCredentials.cs&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Amazon.Runtime\ConfigurationManager.cs&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
In both files you should make a &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;#if WINDOWS_PHONE&lt;/span&gt;&amp;nbsp;... &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;#endif&lt;/span&gt; around all using statement to the &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;System.Windows&lt;/span&gt; domain and sub domains. Inside the &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;ConfigurationManager.cs&lt;/span&gt; you also should to this to the body of the &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;LoadConfigFile()&lt;/span&gt; function, because we cannot read Windows config files with Mono. To initialize the database we therefore have to set the database key and security key in code instead of the config file, which is the the better way to do anyhow.&lt;/div&gt;
&lt;div&gt;
Now the SDK should compile with MonoTouch and Mono for Android and you can add the projects to your game solutions.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Getting started with Amazon SimpleDB&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
Before you can start developing you need to sign up for &lt;a href=&quot;http://aws.amazon.com/&quot; target=&quot;_blank&quot;&gt;Amazon AWS here&lt;/a&gt;. There is a good setup guide from Amazon&amp;nbsp;&lt;a href=&quot;http://docs.amazonwebservices.com/AmazonSimpleDB/latest/GettingStartedGuide/GetSetUp.html&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;. Unfortunately Amazon does not include SimpleDB within their web based management console. Therefore it is a good idea to setup a management software like the Scratchpad from the setup guide.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;Simple Global High Score implementation&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
Amazon itself has an &lt;a href=&quot;http://aws.amazon.com/articles/Amazon-SimpleDB/8829919029640036&quot; target=&quot;_blank&quot;&gt;article for a global high score&lt;/a&gt;&amp;nbsp;using the iOS and Android SDK on their web page. The sample I provide here is not very different from that.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
First you should create a domain for your game in the database using a&amp;nbsp;management&amp;nbsp;tool like the Scratchpad. Then start implementing by creating a SimpleDB client object:&lt;/div&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;// add at beginning of your file
// Amazon db
using Amazon;
using Amazon.SimpleDB;
using Amazon.SimpleDB.Util;
using Amazon.SimpleDB.Model;

// make this a member variable
AmazonSimpleDB m_sdb;

// and create the client inside the constructor
m_sdb = AWSClientFactory.CreateAmazonSimpleDBClient(&quot;your_access_key&quot;, &quot;your_secrete_access_key&quot;);
&lt;/pre&gt;
&lt;div&gt;
The SimpleDB is a nosql database and therefore a table does not have a fixed structure. Anyhow, when you store and read high score data from the database you still have to decide on which attributes a high score entry inside your domain table should have. The table I use has the following attributes:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Category - this is always &quot;HighScore&quot; for high score entries&lt;/li&gt;
&lt;li&gt;Player - name of the player to display in high score list&lt;/li&gt;
&lt;li&gt;Score - score of the entry&lt;/li&gt;
&lt;li&gt;OS - I also store &quot;Windows Phone&quot;, &quot;iOS&quot; or &quot;Android&quot; for statistics.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Using these attributes the function to store a high score entry now looks like this:&lt;/div&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;void WriteGlobalHighscore()
{
    SimpleDBResponseEventHandler&amp;lt;object, ResponseEventArgs&amp;gt; handler = null;
    handler = delegate(object senderAmazon, ResponseEventArgs args)
    {
        //Unhook from event.
        m_sdb.OnSimpleDBResponse -= handler;
        PutAttributesResponse response = args.Response as PutAttributesResponse;
        if (null != response)
        {
           // we could do something when we get a success response from the server
        }
    };

    m_sdb.OnSimpleDBResponse += handler;
    string uniqueID = &quot;UNIQUE_ID&quot;;
    string playerName = &quot;PLAYER_NAME&quot;;
    string domainName = &quot;YOUR_DOMAIN_NAME&quot;;
    string operationSystem = &quot;Windows Phone&quot;; // change for other os
    PutAttributesRequest putAttributesRequest = new PutAttributesRequest { DomainName = domainName, ItemName = uniqueID };
    List&amp;lt;ReplaceableAttribute&amp;gt; attributesOne = putAttributesRequest.Attribute;

    attributesOne.Add(new ReplaceableAttribute().WithName(&quot;Category&quot;).WithValue(&quot;HighScore&quot;).WithReplace(true));
    attributesOne.Add(new ReplaceableAttribute().WithName(&quot;Player&quot;).WithValue(playerName).WithReplace(true));
    // zero pad highscore string - necessary for sorting in select request because all value types are strings
    string number = AmazonSimpleDBUtil.EncodeZeroPadding(m_saveGame.HiScore, 10);
    attributesOne.Add(new ReplaceableAttribute().WithName(&quot;Score&quot;).WithValue(number).WithReplace(true));
    attributesOne.Add(new ReplaceableAttribute().WithName(&quot;OS&quot;).WithValue(operationSystem).WithReplace(true));

    m_sdb.PutAttributes(putAttributesRequest);
}
&lt;/pre&gt;
&lt;div&gt;
As you can see, the call to the database is&amp;nbsp;asynchronous. When the operation is completed the response handler is called. Out of&amp;nbsp;laziness&amp;nbsp;the handler is directly declared as delegate inside this function.&lt;br /&gt;
The variables &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;uniqueID&lt;/span&gt;, &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;playerName &lt;/span&gt;and &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;domainName&amp;nbsp;&lt;/span&gt;have to be assigned with proper values. The &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;uniqueID &lt;/span&gt;is the key value of the database table. I follow the example from Amazon and use an ID that is unique for each phone. I do this by creating a GUID the first time the game is started and store this GUID in a file. To get the player name you have to implement a dialog to let the player enter a name. The name should also be stored inside a file, so that you don&#39;t have to ask the player each time again.&lt;br /&gt;
&lt;br /&gt;
You should now use the Scratchpad to verify if your entry really is stored at your SimpleDB. To do that you use the Select function and enter the Select Expression &quot;&lt;i&gt;select * from &amp;lt;your_domain_name&amp;gt;&lt;/i&gt;&quot;.&lt;br /&gt;
&lt;br /&gt;
If you confirmed your successful storage of your high score you are ready to implement the function to request the entry from your game:&lt;/div&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;void RequestGlobalHighscore()
{
    // create response handler and delegate
    SimpleDBResponseEventHandler&amp;lt;object, ResponseEventArgs&amp;gt; handler = null;

    handler = delegate(object sender, ResponseEventArgs args)
    {
        int globlaHighscore;
        string playerName;
        string operationSystem;
        //Unhook from event.
        m_sdb.OnSimpleDBResponse -= handler;
        SelectResponse response = args.Response as SelectResponse;

        if (null != response)
        {
            SelectResult selectResult = response.SelectResult;
            if (null != selectResult)
            {
                foreach (Item item in selectResult.Item)
                {
                    // actually should just be one item
                    foreach (Amazon.SimpleDB.Model.Attribute attribute in item.Attribute)
                    {
                        switch (attribute.Name)
                        {
                            case &quot;Score&quot;:
                                globlaHighscore = Int32.Parse(attribute.Value);
                                break;
                            case &quot;Player&quot;:
                                playerName = attribute.Value;
                                break;
                            case &quot;OS&quot;:
                                operationSystem = attribute.Value;
                                break;
                        }
                    }
                }
            }
            // now store the attributes to some member variables
            // ....
        }
    };
    m_sdb.OnSimpleDBResponse += handler;

    // create request
    string domainName = &quot;YOUR_DOMAIN_NAME&quot;;
    string sql = &quot;SELECT * FROM &quot; + domainName + &quot; WHERE Category=&#39;HighScore&#39; INTERSECTION Score IS NOT null ORDER BY Score DESC LIMIT 1&quot;;
    m_sdb.Select(new SelectRequest { SelectExpression = sql, ConsistentRead = true });
}&lt;/pre&gt;
&lt;div&gt;
This database request again is&amp;nbsp;asynchronous&amp;nbsp;and the handler, that is called when the answer arrived, is directly defined as delegate inside this function. In this example the result attributes are just stored inside local variables. Of course you need to copy them to some global structure or member variables.&lt;br /&gt;
&lt;br /&gt;
This ends the post about my solution for a simple global high score implementation that works with WP7, iOS and Android. I think it is very elegant as the actual game code is shared along all platforms without any special modifications for a platform necessary. Also the SDK for the Amazon AWS cloud services is very easy to use. Following this example adding a global high score to your game can be done in just a few hours.&lt;/div&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://klutzgames.blogspot.com/feeds/397862965363115006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://klutzgames.blogspot.com/2012/03/cross-platform-global-high-score-using.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default/397862965363115006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default/397862965363115006'/><link rel='alternate' type='text/html' href='http://klutzgames.blogspot.com/2012/03/cross-platform-global-high-score-using.html' title='Cross-Platform Global High-Score using Amazon SimpleDB'/><author><name>Timo Fleisch</name><uri>http://www.blogger.com/profile/18171872141745431561</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsaCQIqmHrvkkW8FWVUbQi-hejc4l85EthVD3G2QDtEYK5-vKm5YkFqMpId2xHPud71GvX1HJUbBgY1bsj8qGEvdxNcs2fTXezpGjHpicyUthRPIlXDDEBPwVdZwROHw/s220/P2230079.JPG'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107421633532789675.post-7242599921470667123</id><published>2012-02-23T12:45:00.000+01:00</published><updated>2012-02-23T12:45:01.132+01:00</updated><title type='text'>MonoGame: Getting Started 3/3</title><content type='html'>Now let us create an Android project for the game. To start the project the following files are need:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Activity class file&lt;/li&gt;
&lt;li&gt;Manifest file&lt;/li&gt;
&lt;li&gt;Project file&lt;/li&gt;
&lt;li&gt;Solution file&lt;/li&gt;
&lt;li&gt;Icon file&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
In Android each app needs to have at least one Activity class. Therefore create a file inside your Android directory with the name &lt;b&gt;Activity1.cs&lt;/b&gt; and the following content:&lt;/div&gt;
&lt;pre class=&quot;brush: csharp&quot; title=&quot;Activity1.cs&quot;&gt;using Android.App;
using Android.OS;
using Android.Util;
using Android.Views;
using Android.Widget;
using Android.Content.PM;

namespace MyNamespace
{
    [Activity(Label = &quot;MyGame Label&quot;, 
       MainLauncher = true, 
       Icon = &quot;@drawable/icon&quot;, 
       ScreenOrientation = ScreenOrientation.Portrait,
       ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden, 
       LaunchMode=LaunchMode.SingleInstance
    )]
    public class Activity1 : Microsoft.Xna.Framework.AndroidGameActivity
    {
        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);
     
            MyGame.Activity = this;
            var game = new MyGame ();
            
            FrameLayout fl = new FrameLayout(this);
            fl.AddView(game.Window);                               
            SetContentView (fl);            

            game.Run ();            
        }
    }
}
&lt;/pre&gt;
&lt;div&gt;
Inside this source change the &lt;i&gt;MyNamespace &lt;/i&gt;and &lt;i&gt;MyGame &lt;/i&gt;to fit your project. Next we need a manifest file. For that create a directory &lt;i&gt;Properties &lt;/i&gt;and inside create the file &lt;b&gt;AndroidManifest.xml&lt;/b&gt; with this content:&lt;/div&gt;
&lt;script class=&quot;brush:xml&quot; title=&quot;AndroidManifest.xml&quot; type=&quot;syntaxhighlighter&quot;&gt;
&lt;![CDATA[&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot; android:versionCode=&quot;1&quot; android:versionName=&quot;1.0&quot; package=&quot;mygame.mygame&quot;&gt;
 &lt;application android:label=&quot;MyGame Label&quot; android:debuggable=&quot;true&quot; android:icon=&quot;@drawable/icon&quot;&gt;
 &lt;/application&gt;
 &lt;uses-sdk android:minSdkVersion=&quot;8&quot; targetSdkVersion=&quot;8&quot; /&gt;
 &lt;supports-screens android:resizeable=&quot;true&quot; android:smallScreens=&quot;true&quot; android:normalScreens=&quot;true&quot; android:largeScreens=&quot;true&quot; /&gt;
 &lt;uses-permission android:name=&quot;android.permission.INTERNET&quot; /&gt;
 &lt;uses-permission android:name=&quot;android.permission.ACCESS_NETWORK_STATE&quot; /&gt;
&lt;/manifest&gt;]]&gt;
&lt;/script&gt;

&lt;br /&gt;
&lt;div&gt;
Before saving it you have to change the &lt;i&gt;package&lt;/i&gt; tag to your game name and application&lt;i&gt; label&lt;/i&gt;. The manifest file is the configuration file for your Android app. E.g. the &lt;i&gt;minSdkVersion &lt;/i&gt;8 means the Android API 8, which is Android 2.2. So this manifest file supports devices from version 2.2 upwards. Also the permissions of what features your application uses are defined in this file. Please read the Android docs to find out more about the manifest file:&lt;br /&gt;
&lt;a href=&quot;http://developer.android.com/guide/topics/fundamentals.&quot;&gt;http://developer.android.com/guide/topics/fundamentals.&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
Now go back to your Android source directory and create the project file &lt;b&gt;MyGame.android.csproj&lt;/b&gt; with the following content:&lt;/div&gt;
&lt;script class=&quot;brush:xml&quot; title=&quot;MyGame.android.csproj&quot; type=&quot;syntaxhighlighter&quot;&gt;
&lt;![CDATA[&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;project DefaultTargets=&quot;Build&quot; ToolsVersion=&quot;4.0&quot; xmlns=&quot;http://schemas.microsoft.com/developer/msbuild/2003&quot;&gt;
  &lt;propertygroup&gt;
    &lt;configuration Condition=&quot; &#39;$(Configuration)&#39; == &#39;&#39; &quot;&gt;Debug&lt;/Configuration&gt;
    &lt;platform Condition=&quot; &#39;$(Platform)&#39; == &#39;&#39; &quot;&gt;AnyCPU&lt;/Platform&gt;
    &lt;productversion&gt;10.0.0&lt;/ProductVersion&gt;
    &lt;schemaversion&gt;2.0&lt;/SchemaVersion&gt;
    &lt;projecttypeguids&gt;{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}&lt;/ProjectTypeGuids&gt;
    &lt;outputtype&gt;Library&lt;/OutputType&gt;
    &lt;rootnamespace&gt;MyNamespace&lt;/RootNamespace&gt;
    &lt;monoandroidresourceprefix&gt;Resources&lt;/MonoAndroidResourcePrefix&gt;
    &lt;monoandroidassetsprefix&gt;Assets&lt;/MonoAndroidAssetsPrefix&gt;
    &lt;androidresgenclass&gt;Resource&lt;/AndroidResgenClass&gt;
    &lt;androidapplication&gt;True&lt;/AndroidApplication&gt;
    &lt;androidresgenfile&gt;Resources\Resource.designer.cs&lt;/AndroidResgenFile&gt;
    &lt;assemblyname&gt;MyGame&lt;/AssemblyName&gt;
    &lt;androidmanifest&gt;Properties\AndroidManifest.xml&lt;/AndroidManifest&gt;
    &lt;deployexternal&gt;false&lt;/DeployExternal&gt;
    &lt;androidsupportedabis&gt;armeabi-v7a&lt;/AndroidSupportedAbis&gt;
    &lt;androidstoreuncompressedfileextensions /&gt;
    &lt;mandroidi18n /&gt;
    &lt;targetframeworkversion&gt;v4.0&lt;/TargetFrameworkVersion&gt;
    &lt;androidlinkmode&gt;SdkOnly&lt;/AndroidLinkMode&gt;
    &lt;androidusesharedruntime&gt;false&lt;/AndroidUseSharedRuntime&gt;
  &lt;/PropertyGroup&gt;
  &lt;propertygroup Condition=&quot; &#39;$(Configuration)|$(Platform)&#39; == &#39;Debug|AnyCPU&#39; &quot;&gt;
    &lt;debugsymbols&gt;true&lt;/DebugSymbols&gt;
    &lt;debugtype&gt;full&lt;/DebugType&gt;
    &lt;optimize&gt;false&lt;/Optimize&gt;
    &lt;outputpath&gt;bin\Debug&lt;/OutputPath&gt;
    &lt;defineconstants&gt;DEBUG; ANDROID&lt;/DefineConstants&gt;
    &lt;errorreport&gt;prompt&lt;/ErrorReport&gt;
    &lt;warninglevel&gt;4&lt;/WarningLevel&gt;
    &lt;consolepause&gt;false&lt;/ConsolePause&gt;
    &lt;embedassembliesintoapk&gt;true&lt;/EmbedAssembliesIntoApk&gt;
    &lt;androidsupportedabis&gt;armeabi,armeabi-v7a&lt;/AndroidSupportedAbis&gt;
  &lt;/PropertyGroup&gt;
  &lt;propertygroup Condition=&quot; &#39;$(Configuration)|$(Platform)&#39; == &#39;Release|AnyCPU&#39; &quot;&gt;
    &lt;debugtype&gt;none&lt;/DebugType&gt;
    &lt;optimize&gt;true&lt;/Optimize&gt;
    &lt;outputpath&gt;bin\Release&lt;/OutputPath&gt;
    &lt;errorreport&gt;prompt&lt;/ErrorReport&gt;
    &lt;warninglevel&gt;4&lt;/WarningLevel&gt;
    &lt;consolepause&gt;false&lt;/ConsolePause&gt;
    &lt;defineconstants&gt;ANDROID&lt;/DefineConstants&gt;
    &lt;embedassembliesintoapk&gt;true&lt;/EmbedAssembliesIntoApk&gt;
    &lt;androidsupportedabis&gt;armeabi,armeabi-v7a&lt;/AndroidSupportedAbis&gt;
  &lt;/PropertyGroup&gt;
  &lt;itemgroup&gt;
    &lt;reference Include=&quot;System&quot; /&gt;
    &lt;reference Include=&quot;System.Xml&quot; /&gt;
    &lt;reference Include=&quot;System.Core&quot; /&gt;
    &lt;reference Include=&quot;Mono.Android&quot; /&gt;
    &lt;reference Include=&quot;OpenTK&quot; /&gt;
    &lt;reference Include=&quot;System.Xml.Linq&quot; /&gt;
  &lt;/ItemGroup&gt;
  &lt;itemgroup&gt;
    &lt;compile Include=&quot;Activity1.cs&quot; /&gt;
  &lt;/ItemGroup&gt;
  &lt;itemgroup&gt;
    &lt;none Include=&quot;Properties\AndroidManifest.xml&quot; /&gt;
  &lt;/ItemGroup&gt;
  &lt;itemgroup&gt;
    &lt;folder Include=&quot;Assets\&quot; /&gt;
    &lt;folder Include=&quot;Assets\Content\&quot; /&gt;
  &lt;/ItemGroup&gt;
  &lt;itemgroup&gt;
    &lt;androidresource Include=&quot;Resources\drawable\Icon.png&quot; /&gt;
  &lt;/ItemGroup&gt;
  &lt;import Project=&quot;$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets&quot; /&gt;
  &lt;itemgroup&gt;
    &lt;projectreference Include=&quot;..\..\MonoGame\ThirdParty\Lidgren.Network\Lidgren.Network.Android.csproj&quot;&gt;
      &lt;project&gt;{565129E0-4EE5-4F6F-B403-C3484C9740BE}&lt;/Project&gt;
      &lt;name&gt;Lidgren.Network.Android&lt;/Name&gt;
    &lt;/ProjectReference&gt;
    &lt;projectreference Include=&quot;..\..\MonoGame\MonoGame.Framework\MonoGame.Framework.Android.csproj&quot;&gt;
      &lt;project&gt;{BA9476CF-99BA-4D03-92F2-73D2C5E58883}&lt;/Project&gt;
      &lt;name&gt;MonoGame.Framework.Android&lt;/Name&gt;
    &lt;/ProjectReference&gt;
  &lt;/ItemGroup&gt;
&lt;/Project&gt;]]&gt;
&lt;/script&gt;
You have to change the &lt;i&gt;RootNamespace &lt;/i&gt;and &lt;i&gt;AssemblyName &lt;/i&gt;tag to match your project. Also check if the &lt;i&gt;ProjectReference &lt;/i&gt;tag of MonoGame and Lidgren point to your local installation path.&lt;br /&gt;
Now create the solution file for this project &lt;b&gt;MyGame.sln&lt;/b&gt; and copy this content:
&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot; title=&quot;MyGame.sln&quot;&gt;Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project(&quot;{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}&quot;) = &quot;Lidgren.Network.Android&quot;, &quot;..\..\MonoGame\ThirdParty\Lidgren.Network\Lidgren.Network.Android.csproj&quot;, &quot;{565129E0-4EE5-4F6F-B403-C3484C9740BE}&quot;
EndProject
Project(&quot;{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}&quot;) = &quot;MonoGame.Framework.Android&quot;, &quot;..\..\MonoGame\MonoGame.Framework\MonoGame.Framework.Android.csproj&quot;, &quot;{BA9476CF-99BA-4D03-92F2-73D2C5E58883}&quot;
EndProject
Project(&quot;{2150E333-8FDC-42A3-9474-1A3956D46DE8}&quot;) = &quot;Solution Items&quot;, &quot;Solution Items&quot;, &quot;{9C06E528-B9C7-4115-81C1-0E572103B242}&quot;
EndProject
Global
 GlobalSection(SolutionConfigurationPlatforms) = preSolution
  Debug|Any CPU = Debug|Any CPU
  Release|Any CPU = Release|Any CPU
 EndGlobalSection
 GlobalSection(ProjectConfigurationPlatforms) = postSolution
  {565129E0-4EE5-4F6F-B403-C3484C9740BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
  {565129E0-4EE5-4F6F-B403-C3484C9740BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
  {565129E0-4EE5-4F6F-B403-C3484C9740BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
  {565129E0-4EE5-4F6F-B403-C3484C9740BE}.Release|Any CPU.Build.0 = Release|Any CPU
  {BA9476CF-99BA-4D03-92F2-73D2C5E58883}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
  {BA9476CF-99BA-4D03-92F2-73D2C5E58883}.Debug|Any CPU.Build.0 = Debug|Any CPU
  {BA9476CF-99BA-4D03-92F2-73D2C5E58883}.Release|Any CPU.ActiveCfg = Release|Any CPU
  {BA9476CF-99BA-4D03-92F2-73D2C5E58883}.Release|Any CPU.Build.0 = Release|Any CPU
  {C04E8EB0-46A8-431F-9C16-E5DA58C1D705}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
  {C04E8EB0-46A8-431F-9C16-E5DA58C1D705}.Debug|Any CPU.Build.0 = Debug|Any CPU
  {C04E8EB0-46A8-431F-9C16-E5DA58C1D705}.Release|Any CPU.ActiveCfg = Release|Any CPU
  {C04E8EB0-46A8-431F-9C16-E5DA58C1D705}.Release|Any CPU.Build.0 = Release|Any CPU
  {F10C1F14-64AF-4957-847E-E60490371E84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
  {F10C1F14-64AF-4957-847E-E60490371E84}.Debug|Any CPU.Build.0 = Debug|Any CPU
  {F10C1F14-64AF-4957-847E-E60490371E84}.Release|Any CPU.ActiveCfg = Release|Any CPU
  {F10C1F14-64AF-4957-847E-E60490371E84}.Release|Any CPU.Build.0 = Release|Any CPU
  {1C3FA898-56B3-4135-8A92-C876CECB5C60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
  {1C3FA898-56B3-4135-8A92-C876CECB5C60}.Debug|Any CPU.Build.0 = Debug|Any CPU
  {1C3FA898-56B3-4135-8A92-C876CECB5C60}.Release|Any CPU.ActiveCfg = Release|Any CPU
  {1C3FA898-56B3-4135-8A92-C876CECB5C60}.Release|Any CPU.Build.0 = Release|Any CPU
 EndGlobalSection
 GlobalSection(NestedProjects) = preSolution
 EndGlobalSection
 GlobalSection(MonoDevelopProperties) = preSolution
  StartupItem = BulletBabs.Android.csproj
  Policies = $0
  $0.DotNetNamingPolicy = $1
  $1.DirectoryNamespaceAssociation = None
  $1.ResourceNamePolicy = FileFormatDefault
 EndGlobalSection
EndGlobal
&lt;/pre&gt;
Here again check if the path to the MonoGame and Lidgren project files point to your local MonoGame installation.&lt;br /&gt;
The one file remaining now is an icon for your game. For that you should create the folders &lt;i&gt;Resources/drawable&lt;/i&gt; and place a png image file with the name&lt;i&gt; Icon.png&lt;/i&gt; inside. Make the resolution of this file 96x96 pixel.&lt;br /&gt;
&lt;br /&gt;
Now you are ready to open the solution file in either Visual Studio or MonoGame, depending on your installation option of Mono for Android. First check if the references to the MonoGame and Lidgren project are correct. Then add your game by using add project to add the project file we created before.&lt;br /&gt;
If you created and placed all files correctly you should now see all files inside your project map. Again please the if the references to MonoGame are correct.&lt;br /&gt;
Now you have to proceed similar as with the iOS project. First you add all your game source files as&lt;b&gt; link&lt;/b&gt; to your project. At this point you should then already be able to compile your game. If not, try to find and fix the errors.&lt;br /&gt;
Once your game compiles you are ready to add the content files. If you haven&#39;t, please read the remarks to that in the iOS part before. On Android all content goes into an &lt;i&gt;Assets&lt;/i&gt; folder. Therefore you need to add your content files in a folder &lt;i&gt;Assets/Content&lt;/i&gt;. Change the options of each file to &quot;&lt;i&gt;Build Type: AndroidAsset&lt;/i&gt;&quot;.&lt;br /&gt;
&lt;br /&gt;
Now you are ready to deploy and run your game on the Android emulator. However, the Android emulator is so slow - at least on my computer - that running and debugging is cumbersome. For a first test it should be fine though.&lt;br /&gt;
Unfortunately, if you are seriously porting your game to Android, you are not finished her yet. Unlike WP7 and iOS, Android does not take care about your application when it gets suspended and resumed. On Android you have to handle it yourself. The magic word here is Lifecycle Management, you can start getting the idea be reading the official Android docs:&lt;br /&gt;
&lt;a href=&quot;http://developer.android.com/reference/android/app/Activity.html&quot;&gt;http://developer.android.com/reference/android/app/Activity.html&lt;/a&gt;
&lt;br /&gt;
To make things worse, your application&#39;s OpenGL context will get invalid once your app is resumed, resulting in broken textures. Hopefully in later versions Mono for Android or MonoGame will take care of that. By the time of writing however, you will have to take care about this yourself. You should check the discussion board of MonoGame on how you could handle it. I am not very satisfied with the &lt;i&gt;hack&lt;/i&gt; I am using for my games so far myself.&lt;br /&gt;
&lt;br /&gt;
I hope this blog post is useful to show how fast you can get your XNA game running on iOS and Android. However, if you seriously planning to publish your game on these platforms, you also need to read about and understand their special technical differences and issues.</content><link rel='replies' type='application/atom+xml' href='http://klutzgames.blogspot.com/feeds/7242599921470667123/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://klutzgames.blogspot.com/2012/02/monogame-getting-started-33.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default/7242599921470667123'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default/7242599921470667123'/><link rel='alternate' type='text/html' href='http://klutzgames.blogspot.com/2012/02/monogame-getting-started-33.html' title='MonoGame: Getting Started 3/3'/><author><name>Timo Fleisch</name><uri>http://www.blogger.com/profile/18171872141745431561</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsaCQIqmHrvkkW8FWVUbQi-hejc4l85EthVD3G2QDtEYK5-vKm5YkFqMpId2xHPud71GvX1HJUbBgY1bsj8qGEvdxNcs2fTXezpGjHpicyUthRPIlXDDEBPwVdZwROHw/s220/P2230079.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107421633532789675.post-7415766157554088748</id><published>2012-02-21T18:07:00.000+01:00</published><updated>2012-02-23T11:53:19.112+01:00</updated><title type='text'>MonoGame: Getting Started 2/3</title><content type='html'>&lt;span style=&quot;font-family: inherit;&quot;&gt;Next we set up the iOS project. Inside the iOS directory create a file called &lt;b&gt;AppDelegate.cs&lt;/b&gt;:&lt;/span&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: csharp&quot; title=&quot;AppDelegate.cs&quot;&gt;using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;

using Microsoft.Xna.Framework;

namespace MyNamespace
{
 // The UIApplicationDelegate for the application. This class is responsible for launching the 
 // User Interface of the application, as well as listening (and optionally responding) to 
 // application events from iOS.
 [Register (&quot;AppDelegate&quot;)]
 class Program : MonoGameProgram 
 {
  private MyGame game;

  public override bool FinishedLaunching (UIApplication app, NSDictionary options)
  {
   // Fun begins..
   game = new MyGame();
   MonoGameGame = game;
   game.Run();
   return true;
  }

  static void Main (string [] args)
  {
   UIApplication.Main (args,null,&quot;AppDelegate&quot;);
  }
 }
}&lt;/pre&gt;
&lt;br /&gt;
Change &lt;i&gt;MyNamespace &lt;/i&gt;to your namespace and &lt;i&gt;MyGame &lt;/i&gt;to your game class name.&lt;br /&gt;
The second file we need is &lt;b&gt;Info.plist&lt;/b&gt;. If you are new to Apple, a plist file is a configuration file for the application. Create the file like this:&lt;br /&gt;
&lt;pre class=&quot;brush: xml&quot; title=&quot;Info.plist&quot;&gt;&lt;plist version=&quot;1.0&quot;&gt;
&lt;dict&gt;
 &lt;key&gt;MinimumOSVersion&lt;/key&gt;
 &lt;string&gt;4.1&lt;/string&gt;
 &lt;key&gt;UIDeviceFamily&lt;/key&gt;
 &lt;array&gt;
  &lt;string&gt;2&lt;/string&gt;
 &lt;/array&gt;
 &lt;key&gt;UISupportedInterfaceOrientations&lt;/key&gt;
 &lt;array&gt;
  &lt;string&gt;UIInterfaceOrientationPortrait&lt;/string&gt;
 &lt;/array&gt;
&lt;/dict&gt;
&lt;/plist&gt;
&lt;/pre&gt;
&lt;br /&gt;
Now we only need a solution and a project file. For the project file, create a text file with the name of your game dot ios dot csproj, e.g. &lt;b&gt;MyGame.ios.csproj&lt;/b&gt; and copy this content:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: xml&quot; title=&quot;MyGame.ios.csproj&quot;&gt;&lt;project defaulttargets=&quot;Build&quot; toolsversion=&quot;4.0&quot; xmlns=&quot;http://schemas.microsoft.com/developer/msbuild/2003&quot;&gt;
  &lt;propertygroup&gt;
    &lt;configuration condition=&quot; &#39;$(Configuration)&#39; == &#39;&#39; &quot;&gt;Debug&lt;/configuration&gt;
    &lt;platform condition=&quot; &#39;$(Platform)&#39; == &#39;&#39; &quot;&gt;iPhoneSimulator&lt;/platform&gt;
    &lt;productversion&gt;10.0.0&lt;/productversion&gt;
    &lt;schemaversion&gt;2.0&lt;/schemaversion&gt;
    &lt;projecttypeguids&gt;{6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}&lt;/projecttypeguids&gt;
    &lt;outputtype&gt;Exe&lt;/outputtype&gt;
    &lt;rootnamespace&gt;MyGame.ios&lt;/rootnamespace&gt;
    &lt;assemblyname&gt;MyGameios&lt;/assemblyname&gt;
  &lt;/propertygroup&gt;
  &lt;propertygroup condition=&quot; &#39;$(Configuration)|$(Platform)&#39; == &#39;Debug|iPhoneSimulator&#39; &quot;&gt;
    &lt;debugsymbols&gt;true&lt;/debugsymbols&gt;
    &lt;debugtype&gt;full&lt;/debugtype&gt;
    &lt;optimize&gt;false&lt;/optimize&gt;
    &lt;outputpath&gt;bin\iPhoneSimulator\Debug&lt;/outputpath&gt;
    &lt;defineconstants&gt;DEBUG; IOS;&lt;/defineconstants&gt;
    &lt;errorreport&gt;prompt&lt;/errorreport&gt;
    &lt;warninglevel&gt;4&lt;/warninglevel&gt;
    &lt;consolepause&gt;false&lt;/consolepause&gt;
    &lt;mtouchlink&gt;None&lt;/mtouchlink&gt;
    &lt;mtouchdebug&gt;true&lt;/mtouchdebug&gt;
  &lt;/propertygroup&gt;
  &lt;propertygroup condition=&quot; &#39;$(Configuration)|$(Platform)&#39; == &#39;Release|iPhoneSimulator&#39; &quot;&gt;
    &lt;debugtype&gt;none&lt;/debugtype&gt;
    &lt;optimize&gt;false&lt;/optimize&gt;
    &lt;outputpath&gt;bin\iPhoneSimulator\Release&lt;/outputpath&gt;
    &lt;errorreport&gt;prompt&lt;/errorreport&gt;
    &lt;warninglevel&gt;4&lt;/warninglevel&gt;
    &lt;consolepause&gt;false&lt;/consolepause&gt;
    &lt;mtouchlink&gt;None&lt;/mtouchlink&gt;
  &lt;/propertygroup&gt;
  &lt;propertygroup condition=&quot; &#39;$(Configuration)|$(Platform)&#39; == &#39;Debug|iPhone&#39; &quot;&gt;
    &lt;debugsymbols&gt;true&lt;/debugsymbols&gt;
    &lt;debugtype&gt;full&lt;/debugtype&gt;
    &lt;optimize&gt;false&lt;/optimize&gt;
    &lt;outputpath&gt;bin\iPhone\Debug&lt;/outputpath&gt;
    &lt;defineconstants&gt;DEBUG;&lt;/defineconstants&gt;
    &lt;errorreport&gt;prompt&lt;/errorreport&gt;
    &lt;warninglevel&gt;4&lt;/warninglevel&gt;
    &lt;consolepause&gt;false&lt;/consolepause&gt;
    &lt;mtouchdebug&gt;true&lt;/mtouchdebug&gt;
    &lt;codesignkey&gt;iPhone Developer&lt;/codesignkey&gt;
    &lt;ipapackagename&gt;
    &lt;mtouchi18n&gt;
  &lt;/mtouchi18n&gt;&lt;/ipapackagename&gt;&lt;/propertygroup&gt;
  &lt;propertygroup condition=&quot; &#39;$(Configuration)|$(Platform)&#39; == &#39;Release|iPhone&#39; &quot;&gt;
    &lt;debugtype&gt;none&lt;/debugtype&gt;
    &lt;optimize&gt;false&lt;/optimize&gt;
    &lt;outputpath&gt;bin\iPhone\Release&lt;/outputpath&gt;
    &lt;errorreport&gt;prompt&lt;/errorreport&gt;
    &lt;warninglevel&gt;4&lt;/warninglevel&gt;
    &lt;consolepause&gt;false&lt;/consolepause&gt;
    &lt;codesignkey&gt;iPhone Developer&lt;/codesignkey&gt;
  &lt;/propertygroup&gt;
  &lt;itemgroup&gt;
    &lt;reference include=&quot;System&quot;&gt;
    &lt;reference include=&quot;System.Xml&quot;&gt;
    &lt;reference include=&quot;System.Core&quot;&gt;
    &lt;reference include=&quot;monotouch&quot;&gt;
    &lt;reference include=&quot;System.Xml.Linq&quot;&gt;
  &lt;/reference&gt;&lt;/reference&gt;&lt;/reference&gt;&lt;/reference&gt;&lt;/reference&gt;&lt;/itemgroup&gt;
  &lt;itemgroup&gt;
    &lt;none include=&quot;Info.plist&quot;&gt;
  &lt;/none&gt;&lt;/itemgroup&gt;
  &lt;itemgroup&gt;
    &lt;compile include=&quot;AppDelegate.cs&quot;&gt;
  &lt;/compile&gt;&lt;/itemgroup&gt;
  &lt;import project=&quot;$(MSBuildBinPath)\Microsoft.CSharp.targets&quot;&gt;
  &lt;itemgroup&gt;
    &lt;projectreference include=&quot;..\..\MonoGame\MonoGame.Framework\MonoGame.Framework.iOS.csproj&quot;&gt;
      &lt;project&gt;{DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}&lt;/project&gt;
      &lt;name&gt;MonoGame.Framework.iOS&lt;/name&gt;
    &lt;/projectreference&gt;
  &lt;/itemgroup&gt;
  &lt;itemgroup&gt;
    &lt;folder include=&quot;Content\&quot;&gt;
  &lt;/folder&gt;&lt;/itemgroup&gt;
&lt;/import&gt;&lt;/project&gt;
&lt;/pre&gt;
Change the tag&amp;nbsp;&lt;i&gt;RootNamespace &lt;/i&gt;and&amp;nbsp;&lt;i&gt;AssemblyName &lt;/i&gt;to meet your game name and check the tag&amp;nbsp;&lt;i&gt;ProjectReference &lt;/i&gt;for the path to MonoGame project file to point on your disk.&lt;br /&gt;
Finally create a solution file e.g. MyGame.ios.sln with this content:&lt;br /&gt;
&lt;pre class=&quot;brush: xml&quot; title=&quot;MyGame.ios.sln&quot;&gt;Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project(&quot;{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}&quot;) = &quot;Lidgren.Network.iOS&quot;, &quot;..\..\MonoGame\ThirdParty\Lidgren.Network\Lidgren.Network.iOS.csproj&quot;, &quot;{734EAA48-F1CA-481A-B391-0285BC0E8B40}&quot;
EndProject
Project(&quot;{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}&quot;) = &quot;MonoGame.Framework.iOS&quot;, &quot;..\..\MonoGame\MonoGame.Framework\MonoGame.Framework.iOS.csproj&quot;, &quot;{DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}&quot;
EndProject
Global
 GlobalSection(SolutionConfigurationPlatforms) = preSolution
  Debug|iPhoneSimulator = Debug|iPhoneSimulator
  Release|iPhoneSimulator = Release|iPhoneSimulator
  Debug|iPhone = Debug|iPhone
  Release|iPhone = Release|iPhone
 EndGlobalSection
 GlobalSection(ProjectConfigurationPlatforms) = postSolution
  {734EAA48-F1CA-481A-B391-0285BC0E8B40}.Debug|iPhone.ActiveCfg = Debug|Any CPU
  {734EAA48-F1CA-481A-B391-0285BC0E8B40}.Debug|iPhone.Build.0 = Debug|Any CPU
  {734EAA48-F1CA-481A-B391-0285BC0E8B40}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
  {734EAA48-F1CA-481A-B391-0285BC0E8B40}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
  {734EAA48-F1CA-481A-B391-0285BC0E8B40}.Release|iPhone.ActiveCfg = Release|Any CPU
  {734EAA48-F1CA-481A-B391-0285BC0E8B40}.Release|iPhone.Build.0 = Release|Any CPU
  {734EAA48-F1CA-481A-B391-0285BC0E8B40}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
  {734EAA48-F1CA-481A-B391-0285BC0E8B40}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
  {77FF5112-1227-4929-A04C-5B36E87A93D5}.Debug|iPhone.ActiveCfg = Debug|Any CPU
  {77FF5112-1227-4929-A04C-5B36E87A93D5}.Debug|iPhone.Build.0 = Debug|Any CPU
  {77FF5112-1227-4929-A04C-5B36E87A93D5}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
  {77FF5112-1227-4929-A04C-5B36E87A93D5}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
  {77FF5112-1227-4929-A04C-5B36E87A93D5}.Release|iPhone.ActiveCfg = Release|Any CPU
  {77FF5112-1227-4929-A04C-5B36E87A93D5}.Release|iPhone.Build.0 = Release|Any CPU
  {77FF5112-1227-4929-A04C-5B36E87A93D5}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
  {77FF5112-1227-4929-A04C-5B36E87A93D5}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
  {9D1AD899-582E-407D-A504-AB36062BCA1F}.Debug|iPhone.ActiveCfg = Debug|iPhone
  {9D1AD899-582E-407D-A504-AB36062BCA1F}.Debug|iPhone.Build.0 = Debug|iPhone
  {9D1AD899-582E-407D-A504-AB36062BCA1F}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
  {9D1AD899-582E-407D-A504-AB36062BCA1F}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
  {9D1AD899-582E-407D-A504-AB36062BCA1F}.Release|iPhone.ActiveCfg = Release|iPhone
  {9D1AD899-582E-407D-A504-AB36062BCA1F}.Release|iPhone.Build.0 = Release|iPhone
  {9D1AD899-582E-407D-A504-AB36062BCA1F}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
  {9D1AD899-582E-407D-A504-AB36062BCA1F}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
  {DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}.Debug|iPhone.ActiveCfg = Debug|iPhone
  {DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}.Debug|iPhone.Build.0 = Debug|iPhone
  {DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
  {DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
  {DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}.Release|iPhone.ActiveCfg = Release|iPhone
  {DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}.Release|iPhone.Build.0 = Release|iPhone
  {DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
  {DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
 EndGlobalSection
EndGlobal
&lt;/pre&gt;
&lt;br /&gt;
Again change the path of the MonoGame project and the&amp;nbsp;Lidgren.Network project to match your local installation.&lt;br /&gt;
Next open the solution with MonoDevelop. If you edited the path correctly you should have the MonoGame and Lidgren project there. If you entered the path wrong than just add them with add project.&lt;br /&gt;
Now use add project to add the project file of your game that you created before. Here also check that the reference to MonoGame is correct. So far you should only have two files in the project. The &lt;i&gt;AppDelegate.cs&lt;/i&gt; and the &lt;i&gt;Info.plist&lt;/i&gt;.&lt;br /&gt;
Now add the source code of your game to the project. Add each of your source files, except for the &lt;i&gt;Program.cs&lt;/i&gt;. Add the source files as &lt;b&gt;link&lt;/b&gt;, so you will use the same files for all platforms and not copies.&lt;br /&gt;
If everything worked fine, you should now be able to compile the source code. If you run across code that won&#39;t compile with MonoGame, you should use defines for each platform as work around.&lt;br /&gt;
The last step that remains is adding your content to the project. Obviously you don&#39;t have the content pipeline from the original XNA in MonoGame. But that is no problem as most content types can be read by MonoGame directly without being pre-processed. If you created the project file as described before, you already should have a &lt;i&gt;Content&lt;/i&gt; folder inside your project. Now add all your content from the WP7 content folder there. As with the source code, you should add them as &lt;b&gt;link &lt;/b&gt;to prevent them from being copied.&lt;br /&gt;
The only content file I ran across so far that is not supported, is .&lt;i&gt;spritefont&lt;/i&gt;. To add this type of content, you have to take the compiled file from the &lt;i&gt;bin/Content&lt;/i&gt; directory of your WP7 folder. The compiled file has the ending &lt;i&gt;.xnb&lt;/i&gt;. Just copy the&lt;i&gt; fontname.xnb&lt;/i&gt; to your &lt;i&gt;MyGame.ios/Content&lt;/i&gt; folder and add this in the project instead of the original spritefont file.&lt;br /&gt;
For each content file in your project you have to set the option&amp;nbsp;&lt;span style=&quot;background-color: white; line-height: 18px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;i&gt;&quot;Build action Content&quot;&lt;/i&gt;. Also be aware, that iOS, unlike Windows, is case sensitive to your content file names. For example, if your Content folder is upper case but in your source code you reference to lower case, you will end up in an exception at runtime.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;background-color: white; line-height: 18px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;Now you should be able to compile your game and test it on the emulator. On my MacMini the emulator runs rather slow. With an actual device, deploying, debugging and running is much better.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div class=&quot;line number1 index0 alt2&quot; style=&quot;background-attachment: initial !important; background-clip: initial !important; background-color: white; background-image: none !important; background-origin: initial !important; border-bottom-left-radius: 0px !important; border-bottom-right-radius: 0px !important; border-bottom-width: 0px !important; border-color: initial !important; border-image: initial !important; border-left-width: 0px !important; border-right-width: 0px !important; border-style: initial !important; border-top-left-radius: 0px !important; border-top-right-radius: 0px !important; border-top-width: 0px !important; bottom: auto !important; box-sizing: content-box !important; float: none !important; height: auto !important; left: auto !important; margin-bottom: 0px !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 0px !important; min-height: inherit !important; outline-color: initial !important; outline-style: initial !important; outline-width: 0px !important; overflow-x: visible !important; overflow-y: visible !important; padding-bottom: 0px !important; padding-left: 1em !important; padding-right: 1em !important; padding-top: 0px !important; position: static !important; right: auto !important; text-align: left; top: auto !important; vertical-align: baseline !important; width: auto !important;&quot;&gt;
&lt;div style=&quot;text-align: -webkit-auto;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: -webkit-auto;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://klutzgames.blogspot.com/feeds/7415766157554088748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://klutzgames.blogspot.com/2012/02/monogame-getting-started-23.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default/7415766157554088748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default/7415766157554088748'/><link rel='alternate' type='text/html' href='http://klutzgames.blogspot.com/2012/02/monogame-getting-started-23.html' title='MonoGame: Getting Started 2/3'/><author><name>Timo Fleisch</name><uri>http://www.blogger.com/profile/18171872141745431561</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsaCQIqmHrvkkW8FWVUbQi-hejc4l85EthVD3G2QDtEYK5-vKm5YkFqMpId2xHPud71GvX1HJUbBgY1bsj8qGEvdxNcs2fTXezpGjHpicyUthRPIlXDDEBPwVdZwROHw/s220/P2230079.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107421633532789675.post-1208374442058259656</id><published>2012-02-21T18:06:00.000+01:00</published><updated>2012-02-21T18:06:58.791+01:00</updated><title type='text'>MonoGame: Getting Started 1/3</title><content type='html'>In this post I will give a short&amp;nbsp;walk-through&amp;nbsp;on how to port your existing XNA game to iOS and Android using MonoGame. MonoGame is an open source implementation of the XNA framework. To keep things simple you should start with a simple 2D game&lt;br /&gt;
MonoGame is based on Mono, so you need to install Mono first. For iOS and Android you need the Mono libraries MonoTouch and/or Mono For Android from Xamarin. For MonoTouch you need an Apple PC. To write the source code you will use MonoDevelop. For Mono For Android you can choose to use&amp;nbsp;either&amp;nbsp;an Apple PC or a Windows PC. On Apple you again have to use MonoDevelop. On Windows you can choose between Visual Studio or MonoDevelop. Unfortunately Visual Studio Express will not work as it does not support plug-ins.&lt;br /&gt;
&lt;br /&gt;
You can get evaluation versions from Xamarin here:&lt;br /&gt;
&lt;br /&gt;
MonoTouch for iOS:&lt;br /&gt;
&lt;a href=&quot;http://xamarin.com/monotouch&quot;&gt;http://xamarin.com/monotouch&lt;/a&gt;
&lt;br /&gt;
Mono For Android:&lt;br /&gt;
&lt;a href=&quot;http://xamarin.com/monoforandroid&quot;&gt;http://xamarin.com/monoforandroid&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
To install these please follow their installation documentation.&lt;br /&gt;
MonoTouch install:&lt;br /&gt;
&lt;a href=&quot;http://docs.xamarin.com/ios/getting_started/installation&quot;&gt;http://docs.xamarin.com/ios/getting_started/installation&lt;/a&gt;
&lt;br /&gt;
Mono For Android install:&lt;br /&gt;
&lt;a href=&quot;http://docs.xamarin.com/android/getting_started/installation&quot;&gt;http://docs.xamarin.com/android/getting_started/installation&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
You will also find a lot of useful tutorials and an API reference on their webpage.&lt;br /&gt;
&lt;br /&gt;
Now you are ready to start with MonoGame.&amp;nbsp;First get the following downloads.&lt;br /&gt;
&lt;br /&gt;
Download MonoGame (currently 2.1) from here:&lt;br /&gt;
&lt;a href=&quot;http://monogame.codeplex.com/&quot;&gt;http://monogame.codeplex.com/&lt;/a&gt;
&lt;br /&gt;
You could also get the source of the developer branch from their GitHub repository but I recommend starting with the stable download version.&lt;br /&gt;
Second get the samples from their GitHub:&lt;br /&gt;
http://github.com/CartBlanche/MonoGame-Samples&lt;br /&gt;
&lt;br /&gt;
After you extracted the MonoGame source to an appropriate path on your computer, you are ready to go.&lt;br /&gt;
&lt;br /&gt;
MonoGame does not come with a script that will convert your project file automatically, so you have to do this by hand. Basically you have to create a solution and project file for iOS and Android each. The best way to create these is to take these files from the MonoGame sample applications and edit them in a text editor. But before doing this you should make sure that these run fine.&lt;br /&gt;
Therefore open an iOS and/or Android sample project and run them in the emulator. Make sure that all references to Mono and MonoGame are correct. Once the sample runs, you are ready for the next step.&lt;br /&gt;
I recommend creating a new&amp;nbsp;directory&amp;nbsp;for each platform to keep things more clear. A directory structure for a typical XNA game then may look like this:&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;MyGame +-MyGameContent&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;+-MyGame&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;+- Properties&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;+-MyGame.ios&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;+-Content&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;+- MyGame.android&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;+-Assets&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;+-Content&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;+-Properties&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;+-Resources&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;I keep the WP7 default directories for the project and content and then add additional directories for iOS and Android. Inside each platform directory I then create an additional content directory. For Android this has to be inside an directory called &lt;i&gt;Assets&lt;/i&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://klutzgames.blogspot.com/feeds/1208374442058259656/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://klutzgames.blogspot.com/2012/02/monogame-getting-started-13.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default/1208374442058259656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default/1208374442058259656'/><link rel='alternate' type='text/html' href='http://klutzgames.blogspot.com/2012/02/monogame-getting-started-13.html' title='MonoGame: Getting Started 1/3'/><author><name>Timo Fleisch</name><uri>http://www.blogger.com/profile/18171872141745431561</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsaCQIqmHrvkkW8FWVUbQi-hejc4l85EthVD3G2QDtEYK5-vKm5YkFqMpId2xHPud71GvX1HJUbBgY1bsj8qGEvdxNcs2fTXezpGjHpicyUthRPIlXDDEBPwVdZwROHw/s220/P2230079.JPG'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-107421633532789675.post-989619597329415592</id><published>2012-02-16T17:40:00.000+01:00</published><updated>2012-02-16T17:40:48.392+01:00</updated><title type='text'>Cross platform mobile game development</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
On this blog I plan to give some insights on my development that I think might be useful to others. In this first post, I will give an overview on what tools I use and why I chose them.&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
When I first came in contact with C# as a tools developer at the German game studio Radon Labs (developer of &lt;a href=&quot;http://en.wikipedia.org/wiki/Drakensang:_The_Dark_Eye&quot;&gt;Drakensang&lt;/a&gt;) in 2008, I quickly fall in love with it. Having used C++ for about 10 years till then, I felt that computer languages finally had advanced. Soon I started to use XNA for private projects and even ported my Virtual Reality library to XNA. With the release of Windows Phone 7, I couldn&#39;t resist the temptation of developing apps in C# and entered the world of smart phones with an HTC HD7.&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
When I decided to quit my job as a C++ developer and become a full time indie game developer last year, I began looking into cross platform&amp;nbsp;possibilities for smart phones. My preconditions were:&lt;/div&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;C#&lt;/li&gt;
&lt;li&gt;Support of iOS, Android and Windows Phone 7&lt;/li&gt;
&lt;/ul&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Obviously these preconditions made it hard to find any usable solution at all. I finally looked into these options:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://unity3d.com/&quot;&gt;Unity 3D&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://deltaengine.net/&quot;&gt;Delta Engine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://monogame.codeplex.com/&quot;&gt;MonoGame&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Unity 3D is obviously the most advanced of these choices, being a full featured game engine since many years. Unfortunately it lacks the support of WP7. WP7 might not be of much commercial interest right now, but because it is the OS I privately use, I didn&#39;t want to ignore it. Furthermore, if you want to have the advanced features of Unity 3D, it becomes rather pricey.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Delta Engine is a .NET based game library in C# with a multi-platform approach. It is developed by the German game studio MobileBits, which is using it itself for their mobile game development. It looked very promising for me and I was very excited when the beta started. It is rather&amp;nbsp;comprehensive and has a well known XNA developer behind it. Unfortunately the support for iOS and Android was not available to beta users at that time.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Actually from MonoGame I expected the least but got surprised. MonoGame is an open source project to provide the XNA framework to Mono, which is an open source implementation of Microsoft&#39;s .Net framework. Mono is available for Windows, MacOS and Linux. However, the Mono libraries for iOS and Android are not free and you need to buy them from&amp;nbsp;&lt;a href=&quot;http://xamarin.com/&quot;&gt;Xamarin&lt;/a&gt;.&amp;nbsp;And these are mandatory if you want to use MonoGame on iOS or Android. For testing, you can get these for free, but they will only run in the emulator and will not deploy to an actual device. I gave it a try and was surprised how easy it was to got my source code compiled and up running in the emulator. However, MonoGame so far only works stable for 2D functions, if you develop 3D games, you will have to wait for a later update.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
I have used MonoGame for two games (Santa Melia and Bullet Babs) now. I use Windows Phone as my lead development platform. After I complete the WP7 version I first port it to iOS and then Android. For my second game Bullet Babs, porting source code didn&#39;t take more than a day for each platform. I spent more time recreating graphics for the different resolutions and aspect ratios and the store submission procedures. You have to create icons and screenshots for each platform. I will share some of my experiences with MonoGame as well as my multi-platform approaches and&amp;nbsp;general&amp;nbsp;C# tips in following posts.&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://klutzgames.blogspot.com/feeds/989619597329415592/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://klutzgames.blogspot.com/2012/02/cross-platform-mobile-game-development.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default/989619597329415592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/107421633532789675/posts/default/989619597329415592'/><link rel='alternate' type='text/html' href='http://klutzgames.blogspot.com/2012/02/cross-platform-mobile-game-development.html' title='Cross platform mobile game development'/><author><name>Timo Fleisch</name><uri>http://www.blogger.com/profile/18171872141745431561</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsaCQIqmHrvkkW8FWVUbQi-hejc4l85EthVD3G2QDtEYK5-vKm5YkFqMpId2xHPud71GvX1HJUbBgY1bsj8qGEvdxNcs2fTXezpGjHpicyUthRPIlXDDEBPwVdZwROHw/s220/P2230079.JPG'/></author><thr:total>4</thr:total></entry></feed>