Friday, November 30, 2012

Deep and meaningful? Screw that!

Everything I've done in my career had meaning and purpose. I've designed medical systems, musical instruments, written educational software and had literally billions of dollars worth of financial trades go through code that I wrote. I've eschewed games as a waste of time and only ever written "serious" software so now I find myself in a delightful situation of having no responsibility to improve someone else's badly written crap of fix other people's magnificent cock-ups. I'm writing entertainment that has no purpose than to occupy the time of the person using the game. Wow! What a relief! All I have to do is make something look good when you blow a hole in it!!

Wednesday, November 28, 2012

Cheating at Android localization

I tried to use Google's localization tool the other day. Is it just me that finds that darned thing utterly unusable? Blimey what a palaver! Anyway. I thought that in the spirit of doing things the quick and simple way I would do another quick macro to strip out the XML.

This macro takes a Strings.xml resource, strips out all the tags, copies the text only parts to the clipboard and shuts the file without saving it. You can then paste directly into Google's translate page and copy-paste the translated stuff back in the order it was created.

Of course, if I was less lazy I would do something more useful but this works for me, especially when I add a section to an Android app and want to propagate that to all the localized files.

Anyway, FWIW, enjoy (or not)


    Sub StringsForTranslation()
        DTE.ExecuteCommand("Edit.Find")
        DTE.Find.FindWhat = "<?xml"
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.Backwards = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        DTE.Find.Action = vsFindAction.vsFindActionFind
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ActiveDocument.Selection.EndOfLine(True)
        DTE.ActiveDocument.Selection.Delete(2)
        DTE.ExecuteCommand("Edit.Find")
        DTE.Find.FindWhat = "<resources>"
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.Backwards = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        DTE.Find.Action = vsFindAction.vsFindActionFind
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ActiveDocument.Selection.Delete(2)
        DTE.ExecuteCommand("Edit.Find")
        DTE.ExecuteCommand("Edit.SwitchtoQuickReplace")
        DTE.Find.Action = vsFindAction.vsFindActionReplaceAll
        DTE.Find.FindWhat = "<string name="
        DTE.Find.ReplaceWith = ""
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResultsNone
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.Find.FindWhat = """>"
        DTE.Find.ReplaceWith = """ = """
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.Find.FindWhat = "</string>"
        DTE.Find.ReplaceWith = """"
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.Find.FindWhat = "<!--"
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.Find.FindWhat = "-->"
        DTE.Find.ReplaceWith = """ /*comment*/"
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ActiveDocument.Selection.SelectAll()
        DTE.ExecuteCommand("Edit.Find")
        DTE.Find.FindWhat = "</resources>"
        DTE.Find.Action = vsFindAction.vsFindActionFind
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.Backwards = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ActiveDocument.Selection.DeleteLeft(2)
        DTE.ActiveDocument.Selection.SelectAll()
        DTE.ActiveDocument.Selection.Copy()
        DTE.ActiveWindow.Close(vsSaveChanges.vsSaveChangesNo)
    End Sub

Sunday, November 25, 2012

Localizing IOS apps from Android XML strings

I have been working on an Android app that I am now transferring to IOS. As one might expect, the method of localizing the strings is different and so I wrote this Visual Studio macro to take XML string resources from my MonoDroid apps written using Visual Studio and convert them to equivalent Localizable.strings files that might be used in MonoTouch.

Enjoy.


    Sub AndroidStringsToIOSLocalizable()
        DTE.ActiveDocument.Selection.PageUp(False, 99)        DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)
        DTE.ExecuteCommand("Edit.Find")
        DTE.Find.FindWhat = "<?"
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.Backwards = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        DTE.Find.Action = vsFindAction.vsFindActionFind
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ActiveDocument.Selection.EndOfLine(True)
        DTE.ActiveDocument.Selection.Delete(2)
        DTE.ExecuteCommand("Edit.Find")
        DTE.Find.FindWhat = "<resources>"
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.Backwards = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        DTE.Find.Action = vsFindAction.vsFindActionFind
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ActiveDocument.Selection.EndOfLine(True)
        DTE.ActiveDocument.Selection.Delete(2)
        DTE.ExecuteCommand("Edit.Replace")
        DTE.Find.Action = vsFindAction.vsFindActionReplaceAll
        DTE.Find.FindWhat = "<string name="
        DTE.Find.ReplaceWith = ""
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResultsNone
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.Find.FindWhat = "</string>"
        DTE.Find.ReplaceWith = """;"
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ExecuteCommand("Edit.Replace")
        DTE.Find.FindWhat = """>"
        DTE.Find.ReplaceWith = """ = """
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResultsNone
        DTE.Find.Action = vsFindAction.vsFindActionReplaceAll
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ExecuteCommand("Edit.Replace")
        DTE.Find.FindWhat = "<!--"
        DTE.Find.ReplaceWith = "/* "
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResultsNone
        DTE.Find.Action = vsFindAction.vsFindActionReplaceAll
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ExecuteCommand("Edit.Replace")
        DTE.Find.FindWhat = "-->"
        DTE.Find.ReplaceWith = "= */"
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResultsNone
        DTE.Find.Action = vsFindAction.vsFindActionReplaceAll
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ExecuteCommand("Edit.Find")
        DTE.Find.FindWhat = "</re"
        DTE.Find.Action = vsFindAction.vsFindActionFind
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.Backwards = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)
        DTE.ActiveDocument.Selection.EndOfLine(True)
        DTE.ActiveDocument.Selection.DeleteLeft(2)
        DTE.ActiveDocument.Save("Localizable.strings")
        DTE.ActiveWindow.Close(vsSaveChanges.vsSaveChangesNo)
    End Sub

Tuesday, November 20, 2012

iPhone or Android - Which is easiest?

Objectively I find that working with the iPhone APIs, Even in the context of Mono is far simpler than Android. I guess that having complete control over the hardware enables Apple to design a cleaner and more integrated set of APIs.

Converting my game from Android to IOS has largely been a job of removing all the complicated stuff I had to do to get it to run on Android.

Saturday, November 17, 2012

Facebook offensive?

Facebook makes money by providing a free service and showing paid adverts on people's pages. This is all well and good. They also have options to hide things that you don't want to see on your page. Particularly you can opt not to look at a certain advert or to see things from certain web-sites.

It seems that I have an odd demographic. I visit a lot of tech sites, I look at a lot of up-to-date programming and technical blogs, I read nerdy stuff that young men read and so Google which I checked, and probably Facebook which I cannot check, place me in the male 23-35 demographic.

As a consequence, on my Facebook pages, I have one account for professional contacts and another for personal and family, I get an endless stream of Singles and Dating adverts. I will usually get three or four singles ads with an admittedly pretty but uninteresting girl on them when I would rather see ads for technical stuff or travel. I therefore recently tried to reprogram Facebook into not putting ads for vacuous blondes or Chinese and Ukrainian girls by hiding every dating site as offensive to my tastes and clicking on ads for Norwegian fjord cruises and techno-toys. All to no avail.

So, this beggars the question that if I have declared on many occasions that site whateverdatingthing.com is offensive to me and that I do not wish to see advertising from them again, why do they invariably pop up again three days later? Facebook obviously doesn't care a whit about what I find offensive and has no intention to respect my demands. The stupid thing is that they are turning away business because I will never click on a dating site ad where I may possibly click on one for arduino controlled helicopters.

Wednesday, November 14, 2012

Thought Leader...

Anyone who has the temerity to put this on their own profile declaration should be immediately disqualified from the position.

Tuesday, November 13, 2012

Grumpy old woman

While I agree with this seniment for drivers, giving people yet another excuse for fining, pissing off and generally controlling the minutiae of peoples lives is a bad idea and Anne Applebaum can go stuff it where se sun shineth not.

The joy of Secs.

I just had a short Twitter Conversation with Charles Arthur of The Guardian in which he complains of having to field calls from people who want to promote their sites and apps. The fact that he gets such requests is no particular surprise as his presence as a technical editor for a well respected paper and his involvement with podcasts in the tech domain is well know. What surprises me is that someone with such a profile has an easily accessible telephone number and no-one to field his calls.

When I was director of Rogue Wave Software in the US for a while, the customer base got to be rather large and I had to have someone field calls for me because my habit of answering personally began to eat significantly into my day. I imagine that anyone who is known for presenting insightful opinions to a global audience will get a vast number of distractions even if its just a tiny percentage of the audience who pluck up courage to call. The evidence of this is clearly seen in his <grrr> posting on Twitter.

My advice to Charles is to move to another desk, change phone number and have someone grab the phone before he is even aware that it rang. The world is too small and communications too immediate to expect a moments peace. It will only get worse.

Android compatibility utter nonsense!

I am in the process of fine-tuning my game and trying to monetize the free version using providers such as AdMob and RevMob. The trouble is that even though I have tested the game on two low capability machines, The Alcatel 951 and the LG E400, the Play site refuses to admit that tha application is compatible with these telephones. Consequentially, the number of devices that my game can deploy to is severely limited.

I discovered that setting certain options such as the hardware camera autofocus feature to optional increased the compatibility matrix by more than 400 devices but the Alcatel and the LG were both still excluded, even though I have solid proof that the game runs on these devices like a charm.


To set the autofocus feature I used:
  <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />

Finally I have added optional feature requests for network location and wifi to increase compatibility to just over 2000 devices but still not my two test phones!!


  <uses-feature android:name="android.hardware.location.network" android:required="false" />
  <uses-feature android:name="android.hardware.wifi" android:required="false" />

This story is obviously set to run and run.

LATE BREAKING NEWS:
Phew, fixed it.. here is my working app manifest for simple Augmented Reality systems:



<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto" package="my.domain.mygame" android:versionCode="10" android:versionName="1.02">
  <uses-sdk android:minSdkVersion="2" android:targetSdkVersion="14" android:required="false" />
  <application android:label="mygame" android:icon="@drawable/icon" android:name="mono.android.app.Application">
    <activity android:name="com.google.ads.AdActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" />
    <activity android:name="com.revmob.ads.fullscreen.FullscreenActivity" android:configChanges="keyboardHidden|orientation" />
    <activity android:alwaysRetainTaskState="true" android:configChanges="keyboard|keyboardHidden|orientation" android:icon="@drawable/icon" android:label="mygame" android:launchMode="singleInstance" android:theme="@style/Theme.Splash" android:name="mygame.MyGameActivity" />
    <activity android:label="@string/instructions" android:name="mygame.instructions" />
    <activity android:alwaysRetainTaskState="true" android:configChanges="keyboard|keyboardHidden|orientation" android:icon="@drawable/icon" android:label="mygame" android:launchMode="singleInstance" android:theme="@style/Theme.Splash" android:name="mygame.MainActivity">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
    <provider android:name="mono.MonoRuntimeProvider" android:exported="false" android:initOrder="2147483647" android:authorities="my.domain.mygame.mono.MonoRuntimeProvider.__mono_init__" />
  </application>
  <supports-screens android:resizeable="true" android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" android:largestWidthLimitDp="4096" />
  <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
  <uses-feature android:name="android.hardware.location.network" android:required="false" />
  <uses-feature android:name="android.hardware.wifi" android:required="false" />
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.CAMERA" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>

Friday, November 09, 2012

Augmented reality zombies are here

Do you have an Android phone?  I've written my first ever game and its as far from ordinary as it gets! This deceptively simple game uses literally billions of dollars worth of equipment and military research to make the player fitter and healthier by stealth.
Try it out! https://play.google.com/store/apps/details?id=net.bobpowell.zombiesplat

Wednesday, November 07, 2012

GPS readings still wobble

I've been working on some Augmented Reality functionality and have come to the conclusion that there is no easy way of getting a steady fix on one's GPS receiver. I have been trying to solve the problem of my targets wobbling about when I look at them with the device. The wobble seemed to be induced by breathing or heartbeat but I suddenly realised that the GPS fix itself wobbles about a bit.

I should probably average the fix data...

Thursday, November 01, 2012

China buying up the world with YOUR shoes

The economic power of China has grown enormously in the last decade because of the west's insatiable appetite for cheap consumer goods. This comes at the cost of ethically marginal manufacturing where people are virtually imprisoned in garrison towns, paid in company script and denied the right to leave with savings in cash intact. It also comes at the cost of Chinese government run companies (Essentially all of them in a communist country) contributing to the country's coffers and permitting China to buy vast interests in strategically valuable places.

China has already bought vast swathes of African shipping, oil and agricultural businesses and are steadily moving Chinese managers into positions of power in many African countries. Chinese purchases in southern European ports where racially biased employment practices are used to ensure Chinese staff and management in what ought to be a fair employment market show again that the business aspects of the owner's tenure runs a close second to strategic concerns.

Today, the announcement that China has bought a huge stake in London's Heathrow airport predicts that the same practices will be carried out there also. It will be easy for China to move people and materials from land-side to airside or vice-versa because they will control a big chunk of the airport at London and at its other holdings Gatwick and Luton. China also recently bought a huge stake in Thames water, a previously state run company, privatised by Conservatives and given to their upper-crust old school chums to be sold privately for vast profit. Why sell your water supply to a foreign power that could use it to poison the capital city?

The dangerous fact of a totalitarian state disguised as a friendly power with tons of cash and an ever smiling demeanour is paid for by your shoes, iPhones, televisions and other plastic goods manufactured by the million ton in China. This is a scarily dangerous situation for all occidental concerns.


Camera Preview Textures on MonoDroid and MonoGame

The saga continues with the conversion of the camera preview stream into XNA Texture2D images.

It seems that the same technique of predicated texturing is used on some Android phones as is used on XBox 360 which means that the texture buffer data for any given texture may not be available immediately after drawing because the Present method outputs the textures in sections according to how much graphics memory is available to the GPU.

The result of this is the frame buffer for a texture is not available for the SetData call and data converted over from the camera preview stream will corrupt the texture nastily if the update happens at the same time.

To overcome this I used two textures A and B and while displaying B I write into A and vice-versa. All a bit complicated but graphics is like that it seems.


I set up the textures like so:

          _cameraBGa = new Texture2D(graphics.GraphicsDevice, _pvWidth, _pvHeight, false, SurfaceFormat.Bgra5551);
            _cameraBGb = new Texture2D(graphics.GraphicsDevice, _pvWidth, _pvHeight, false, SurfaceFormat.Bgra5551);

            _frameData = new short[bs.Width * bs.Height];


Then I fill them like so:

       unsafe void _listener_PreviewFrame(object sender, PreviewFrameEventArgs e)
        {
            lock (this)
            {
                fixed (short* fd = &_frameData[0])
                {
                    fixed (byte* yuv = &e.Data[0])
                    {
                        YUV2RGB.convertYUV420_NV21toRGB5551(yuv, fd,
                                                            _pvWidth, _pvHeight);
                        if (_textureSelect)
                        {
                            _cameraBGb.SetData(_frameData);
                            _bReady = true;
                        }
                        else
                        {
                            _cameraBGa.SetData(_frameData);
                            _aReady = true;
                        }
                        _textureSelect = !_textureSelect;
                    }
                }
                _bgReady = true;
            }
        }

And finally display them like so:

        protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue); //Cleared by the camera

            if (_aReady && _bReady)
            {

            spriteBatch.Begin();
           
            spriteBatch.Draw(_textureSelect ? _cameraBGa : _cameraBGb, new Rectangle(0, 0, _displayWidth, _displayHeight), Color.White);


etc, etc, etc.

Ahh I love graphics problems. Why didn't I become a priest or something? 

Facebook bubble

The era of the dot com bubble isn't over it seems. Like inventions everywhere, the existence of a purely online entity has to have value at least as great as the sum of it's parts or it will not fly. Google provides a vital and ever growing service that certainly does that. Collating, searching and filtering data must only become more important as we generate more and more of it. Google's approach to data research also provides spinoffs to real technologies such as AI, translation, mobile etc. Facebook on the other hand doesn't provide anything that cannot be duplicated by a couple of students working in a dorm room for three months and the staff at Facebook know this.
Social networking is huge but providing a place for people to post even more innane pictures of their blasted cats isn't. Despite its huge user base, facebook only provides a way for people who already know eachother to share more pictures of cats. There's no money in that.