Saturday, December 17, 2011

Android Explorations


Today I bought an Android powered tablet, the Acer Iconia 7" tablet. As my friends keep telling me, I should start doing Android development, so that I can port the little crane that could to Android devices. Apart from the horrible colours and contrast of the display, I am satisfied with the device so far. Graphics performance seems way behind what an iPad2 can do though, so graphics optimizations are going to be important. Here are some things I learned about Android programming so far:

  • You need to install an SDK and an NDK.
  • As of recently, you can do native development in C without writing a single line of Java code. To do this, see the NativeActivity sample from the NDK.
  • You can do development from the command line without IDE's.
  • Instead of make, you need to use a combination of ndk-build and ant.
  • GLESv1_CM is the OpenGL ES1 library to use. CM stands for COMMON and means that it uses floating point, not fixed point.
  • Doing 'ant debug' and 'ant installd' is often not enough, as I need to do a clean before building. Are the dependencies not set up properly in the sample projects?
  • The emulator cannot do OpenGL ES2, only ES1. When doing ES1 it is super slow, even on a modern mac.
  • The equivalent of GLX for Android is called EGL
  • Android NDK by default targets the ARMV6 devices, which means software floating point emulation. This is very slow.
  • To target ARMV7 with hardware floating point (VFP), add this to jni/Application.mk: APP_ABI := armeabi-v7a
  • To see verbose output of the build process, use ndk-build V=1
  • Loading assets from native code is a painful experience. So instead I convert images to C source code, and build as a shared object. Then I use dlopen() to get to the data.
  • To debug simply run ndk-gdb --start from the project dir.
  • You can set java compiler flags on the ant command line like this: ant "-Djava.compilerargs=-Xlint:unchecked -Xlint:deprecation" debug
  • You can make screenshots with the ddms utility. Select the device and press ⌘S to grab the screen.
  • To incorporate a third party framework, all you have to do is copy the .jar file into your projects ./lib/ directory, and the build system will automagically find and use it.
  • If you want to install certain resource types without compression, then you need to edit your SDK. Change the tools/ant/build.xml file by adding a < nocompress extension="foo" /> to the aapt section.
  • Don't get confused by -msoft-float and -mhard-float, they do not toggle the hardware floating point unit. Instead they influence the convention for passing function arguments. So using -mhard-float will only get a modest speed bump, at the cost of decreased ABI compatibility.
  • in jni/Application.mk you need to keep APP_PLATFORM set to android-20 or lower. At android-21, downward compatibility breaks, and on a pre-android L device, your app will crash with a 'failed: dlopen failed: cannot locate symbol "rand" referenced by...' error.
I am using The Android NDK Beginner's Guide as reference, as well as a guide by IIvan Vučica. That last one is pretty ambitious: it sets up the development environment so that you can do Objective C for Android. However, I decided to keep it simple, and do my project in C.
There is an excellent GDC presentation from Lars Bishop of nVidia on android development.
For future reference, you need to set up some environment variables. This is what I use in my .bashrc file:
export ANDROID_NDK_ROOT=$HOME/android-ndk-r9d
export ANDROID_SDK_ROOT=$HOME/android-sdk-linux
export NDK_MODULE_PATH=$HOME/apps:$HOME/src
PATH=$PATH:$ANDROID_NDK_ROOT:$ANDROID_SDK_ROOT

Friday, December 16, 2011

First Art

Annelies made her first art today at day care. Well art, not sure if you can call it art, but she did paint a picture. Some bold use of colour! The teacher misspelled her name though.

Thursday, December 15, 2011

Nieuwe Nederlanders / New Dutchies

En met deze handdruk is Amy een Nederlandse geworden. Haar man is Nederlands, haar dochter is Nederlands, maar dankzij Amy's Nederlandse moeder is Amy nu genaturaliseerd door de deputy consul in Vancouver.

And with this handshake, Amy became a Dutch citizen. Her husband is Dutch, her daughter is dutch, but thanks to Amy's Dutch mother, Amy could be naturalized by the deputy consul in Vancouver.

Tuesday, December 6, 2011

Don't bother buying Infinity Blade II

So, after all that hype, I decided it was time to find out what Infinity Blade II was all about. I've heard things attributed to it as 'best looking game on iOS' and such, so as a game developer myself I wanted to see it. So I pay the $6.99, got my fancy noise cancelling headphones for the optimal experience, and then..... NOTHING! The game crashes during the title credits. Tried a few times, a 100% crash. I stopped ALL backgrounded apps on my iPad2, and tried again... Crash.

I've noticed this weird trend where the bigger the studio/publisher, the more crashes I see. Why do these big studios get away with publishing crap, and still rank among the top grossing titles? I noticed it with EA's SimCity Deluxe for iPad. The names don't get any bigger than that: EA, Sim City. Yet, they are unable to create a stable experience without crashing. My advice to the consumers here: forget about that big studio crap, and buy indie games. You will typically get email support from the author directly, and there is someone who actually cares about you. Don't let EA and Chair Entertainment get away with this: just stop buying from them.

And you don't have to take my word for it, there are plenty of crash reports from users. In case someone at Chair entertainment decides to do something about it, here is the log of a run where there is not a single other app running in the background:


Dec 6 18:35:18 unknown kernel[0] : launchd[11064] Builtin profile: container (sandbox)
Dec 6 18:35:18 unknown kernel[0] : launchd[11064] Container: /private/var/mobile/Applications/6CD18407-B4A9-4692-AA34-D07EBAF21381 [69] (sandbox)
Dec 6 18:35:18 unknown SwordGame[11064] : Installing signal handler
Dec 6 18:35:19 unknown SwordGame[11064] : Unknown movie state 0
Dec 6 18:35:19 unknown kernel[0] : virtual void AppleCLCD::mieEnable(bool), enable: 1
Dec 6 18:35:20 unknown SwordGame[11064] : This device is [iPad2,1], enum value 5
Dec 6 18:35:20 unknown sandboxd[11065] : SwordGame(11064) deny file-write-data /private/var/mobile/Library/Mobile Documents/8XJ6WJ8Z84~com~chairentertainment~IB2
Dec 6 18:35:21 unknown kernel[0] : launchd[11067] Builtin profile: gamed (sandbox)
Dec 6 18:35:22 unknown gamed[11067] : 18:35:22.436090 com.apple.AVConference: GKSConnSettings: set server: {
"gk-cdx" = "17.173.254.221:4398";
"gk-commnat-cohort" = "17.173.254.223:16386";
"gk-commnat-main0" = "17.173.254.222:16384";
"gk-commnat-main1" = "17.173.254.222:16385";
}
Dec 6 18:35:23 unknown SwordGame[11064] : 18:35:23.312345 com.apple.AVConference: GKSConnSettings: set server: {
"gk-cdx" = "17.173.254.221:4398";
"gk-commnat-cohort" = "17.173.254.223:16386";
"gk-commnat-main0" = "17.173.254.222:16384";
"gk-commnat-main1" = "17.173.254.222:16385";
}
Dec 6 18:35:23 unknown kernel[0] : virtual void AppleCLCD::mieEnable(bool), enable: 0
Dec 6 18:35:23 unknown SwordGame[11064] : Initialize!
Dec 6 18:35:23 unknown SwordGame[11064] : FBDelegate: !
Dec 6 18:35:23 unknown SwordGame[11064] : SetAppID to 152777738124418 / (null) / (null)!
Dec 6 18:35:23 unknown SwordGame[11064] : FBDelegate.FB: !
Dec 6 18:35:24 unknown SwordGame[11064] : GLView: 1357870
Dec 6 18:35:24 unknown SwordGame[11064] : GLView: (EAGLView: 0x1357870; frame = (0 0; 1024 768); layer = )
Dec 6 18:35:27 unknown SwordGame[11064] : Requesting product id com.chair.IB2.goldbag.25000
Dec 6 18:35:27 unknown SwordGame[11064] : Requesting product id com.chair.IB2.goldbag.150000
Dec 6 18:35:27 unknown SwordGame[11064] : Requesting product id com.chair.IB2.goldbag.750000
Dec 6 18:35:27 unknown SwordGame[11064] : Requesting product id com.chair.IB2.goldbag.2500000
Dec 6 18:35:27 unknown wifid[27] : WiFi:[344918127.366272]: Client itunesstored is background application
Dec 6 18:35:27 unknown librariand[11053] : item update observer error: Connection invalid
Dec 6 18:35:28 unknown SwordGame[11064] : Reading int value for key CurrentSlot369d86c1e1a21755d7f29b7aa7ac2065436e116d
Dec 6 18:35:30 unknown MobileMail[11062] : Received memory warning.
Dec 6 18:35:30 unknown SwordGame[11064] : Received memory warning.
Dec 6 18:35:31 unknown SpringBoard[15] : Received memory warning.
Dec 6 18:35:31 unknown syncdefaultsd[11058] : received memory warning
Dec 6 18:35:32 unknown SwordGame[11064] : Reading int value for key LocalSaves_dvb54c8b744f649484cfcae3478da0ec06
Dec 6 18:35:36 unknown com.apple.launchd[1] : (com.apple.gamed) Exited: Killed: 9
Dec 6 18:35:36 unknown com.apple.launchd[1] : (UIKitApplication:com.apple.mobilemail[0x45a2]) Exited: Killed: 9
Dec 6 18:35:36 unknown com.apple.launchd[1] : (UIKitApplication:com.apple.mobilephone[0x6ebe]) Exited: Killed: 9
Dec 6 18:35:36 unknown com.apple.launchd[1] : (UIKitApplication:com.chairentertainment.IB2[0x11fc]) Exited: Killed: 9
Dec 6 18:35:36 unknown UserEventAgent[12] : jetsam: kernel termination snapshot being created
Dec 6 18:35:36 unknown SpringBoard[15] : Application 'Mail' exited abnormally with signal 9: Killed: 9
Dec 6 18:35:36 unknown mediaserverd[43] : 18:35:36.366 AudioSessionSetClientPlayState(11064): cannot get ClientInfo
Dec 6 18:35:36 unknown mediaserverd[43] : 18:35:36.532 AudioQueue: Error 'ini?' from AudioSessionSetClientPlayState(11064)
Dec 6 18:35:36 unknown kernel[0] : launchd[11070] Builtin profile: MobileMail (sandbox)
Dec 6 18:35:36 unknown SpringBoard[15] : Application 'FaceTime' exited abnormally with signal 9: Killed: 9
Dec 6 18:35:36 unknown SpringBoard[15] : Application 'InfinityBlade2' exited abnormally with signal 9: Killed: 9
Dec 6 18:35:37 unknown ReportCrash[11069] : Saved crashreport to /Library/Logs/CrashReporter/LowMemory-2011-12-06-183537.plist using uid: 0 gid: 0, synthetic_euid: 0 egid: 0
Dec 6 18:35:38 unknown librariand[11053] : client connection is invalid: Connection invalid

Hover City at night

Hover Biker version 1.0 was just uploaded to Apple for review. Hopefully they get to it before dec 22, at which time they will stop processing submissions for a week. It would be really nice to have my game available on the app store before Christmas. I've put in a night-time level in the game, which brings the number of levels to 6 free levels, 7 premium levels and 1 tutorial level. I keep wondering how well it will do on the app store. I am hoping to replicate Little Crane's success, but as a worst case scenario, I can't see it do any worse than Panzer Class, which does not sell spectacularly, but still brings in money. But the good news is that every iPad sold by Apple this month is a new potential customer.

Wednesday, November 30, 2011

Gameplay Video

Here is a video that shows the gameplay in my new game Hover Biker. I shot it with a webcam pointed at my monitor fed with an HDMI signal of the iPad2 in mirroring mode. So the quality is not that great. I would have liked to record it with a BlackMagic Hyperdeck Shuttle, but BlackMagic is not responding to inquiries about iPad2 compatibility of their product. Too bad, iOS devs could be a large customer base for them. Feel free to critique, suggest or discuss it, over at the Hover Biker thread at the Touch Arcade forums.

The music is again by the highly talented Johan Stolk who composed the score, and played all the instruments as well. Please note how I timed the first long draw on his guitar with the moment that the robot pushes the right throttle lever. I can't stop watching that.

Keep an eye out on App Battleground where there may appear a review of my game, which is now available at the app store.


Thursday, November 24, 2011

Teaser shots from my new game

Hot off the press... some teaser shots of my new game that is currently under development: Hover Biker. In many ways it will be a better game than the little crane that could. Better graphics, more action, and more mass appeal. What has not changed is a first-rate unsurpassed physics simulation at the root of the game.

This time around, I purchased professional 3D artwork for the city environment. Unlike my own art (which we call programmer art in my industry) it has textures applied. The game will feature a very rich city environment that is completely accessible for the player. This is the opposite of a 'game on rails', if your hover bike can reach it, you are free to visit every nook and cranny of the city.

I will release the game with plenty of challenging levels, but just high speed hovering and pulling stunts with the hover bike is a treat in itself. The game should be in the app store for iPad and iPhone this Christmas. I have a feeling that this game could do very well, and is capable of making some big waves on the app store. There is potential to equal or surpass little crane's success.

Wednesday, October 26, 2011

Loading PVRTC textures without blocking iOS User Interface

While working on my new iOS game, I decided to add one of those nice view transitions when you start a new level. At first I was puzzled by the lack of a nice animation, but then it dawned on me why: iOS will only remain smooth, and show its fancy animations as long as you do not block the main thread. When starting a level, I would first load large textures on the main thread. So how to avoid this?

iOS makes it easy to offload heavy lifting to other threads by using Grand Central Dispatch and its Objective-C construct for code blocks. The trick is to decide what to offload. At first I naively did the whole texture creation on another thread. The downside of this is that you now have two threads competing for the same OpenGL context. A way around would be mutex, but there is a more elegant and simple approach to it that does not involve locking the context or adding a mutex.

The slow part of texture creation is not the uploading with glTexImage() neither the creation of the texture name with glGenTextures(). It is the file loading of the image data, and the decoding of the PVRTC that gobbles up cycles. So only the loading and decoding has to be moved to another thread. All the OpenGL calls can remain on the main thread, and no context locking is required.

I expect that most iOS developers are using the Apple-provided class PVRTexture.h/PVRTexture.m which can be found at the developer.apple.com site. Adapting this class to offload the texture load/decode on another execution thread is simple. Just follow this recipe:

First add a new member variable to PVRTexture.h


dispatch_group_t dispatchGroup;

Then, add a static var and a class method to PVRTexture.m


static dispatch_queue_t dispatchQueue;

+(void)initialize
{
dispatchQueue = dispatch_queue_create( "textureLoadingQueue", nil );
}

Next, replace this section in createGLTexture


if ([_imageData count] > 0)
{
if (_name != 0)
glDeleteTextures(1, &_name);

glGenTextures(1, &_name);
glBindTexture(GL_TEXTURE_2D, _name);
}

with just a single line


glBindTexture(GL_TEXTURE_2D, _name);

last, replace the implementation of initWithContentsOfFile with


- (id)initWithContentsOfFile:(NSString *)path
{
self = [super init];

glGenTextures( 1, &_name );

dispatchGroup = dispatch_group_create();

dispatch_group_async( dispatchGroup, dispatchQueue, ^{
//NSLog( @"Loading texture data from file" );
NSData *data = [NSData dataWithContentsOfFile:path];

_imageData = [[NSMutableArray alloc] initWithCapacity:12];

_width = _height = 0;
_internalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
_hasAlpha = FALSE;

assert( data );
const BOOL unpacked = [ self unpackPVRData:data ];
assert( unpacked );
});

dispatch_group_notify( dispatchGroup, dispatch_get_main_queue(), ^{
//NSLog( @"Creating GL texture for name %d", _name );
const BOOL created = [ self createGLTexture ];
assert( created );
});

dispatch_release( dispatchGroup );
dispatchGroup = 0;

return self;
}

Some notes: I added asserts to catch missing texture data and such. If you want more graceful failures, like the original had, you may want to adapt that. Also: with this change you can do some really neat stuff, like starting your game before the textures are loaded. OpenGL will happily draw the scene if the texture data is not yet uploaded to the GPU. The world will incrementally be populated with textures, before the player's eyes. Less Waiting, More Playing: how is that not a win?

I used the same tactic for the creation of OpenDE triangle meshes used for my physics simulation. I simply keep the sim delta-time at 0.0 as long as the triangle mesh has not been built yet: let the player absorb the environment while the game is still doing its initializations.

Wednesday, September 21, 2011

The geography factor in freemium conversions

Or: why Kiwi customers rock.

I have been studying the influence of geography on the conversion of freemium users into paying customers. To do this, I analyzed three weeks of sales data from the Mac App Store for the little crane that could.

It turns out that in New Zealand, the users were very likely to buy premium content for the game. For every four downloaders, one of these would purchase additional content. I wonder if this is caused by the fact that in New Zealand internet access is often metered. This would mean that downloading free apps would already constitute a financial commitment by the New Zealand user, so the step to in-app-purchase is smaller.

As a side note: the Mac version of `the little crane that could' had its biggest market in Germany, followed by UK. So even with low German conversion rates, the bulk of the revenue was generated in the German market.

Sunday, August 21, 2011

Hover bikes

I have been collecting some images of hover bikes strewn about the net. Below is what I came up with. I am toying with the idea of doing a racing game, perhaps with pod racers or hover bikes. I doubt that I have the artistic talent to model a good one, so I may have to get myself one on commission. Drop me a line if you can do something like this in Wings3D at low polygon count.



Hover bike by Mr Lakhwinder Singh Dhillon



Hover bike by Serrge



Spitfire by Joe Ulibarri



Hover bike by C Goddard


Hover bike by ershov


Hover bike by Zack Fowler


Hover bike 'ridon' by Ivan Tantsiura


Tuesday, August 16, 2011

Bram interviewed by Geek Preview

I was interviewed by the blog Geek Preview. You can read about it here, where I discuss the history of the little crane that could and more.


Thursday, August 4, 2011

Domme kamervragen

Die cda kamervragen over kwaliteit van de beveiligings cameras slaan de plank compleet mis. Met simpele statistiek en kansrekening is dit uit te leggen: Het publiek ziet alleen beelden van onopgeloste zaken. Veel beeldmateriaal is van uitstekende kwaliteit... De politie lost de zaak op, en het beeldmateriaal bereikt nooit het publiek. Hoe beter de kwaliteit, hoe kleiner de kans dat het publiek nodig is bij het oplossen daarvan. Dat de kamer zich hier over moet buigen is een schande. Bewijst maar weer eens de onkunde van politici. Wellicht is het tijd voor een technocratie?

Monday, July 4, 2011

Sunny evening in the park

It was such a beautiful summer evening today in Vancouver. Amy, Annelies and I soaked up some evening sun in the local park, and of course I brought my camera. Annelies was enjoying it, as did we. Because of the bright sun, you normally cannot use large apertures, as the picture would be over exposed. My camera however, has a built-in neutral density filter that you can activate. This enables you to get shallow depth of field in bright outdoor environments. Without it, I would have been forced to close the aperture all the way down to f/16, so I would have lost the nice blur in foreground and background. My Flickr photostream has another picture of mum and Annelies.

Friday, July 1, 2011

Canada 144 years old

Today Annelies celebrated her first Canada Day by proudly waving the red and white maple leaf flag. I've blogged before on Canada day, when Canada celebrated its 140th birthday and again at the 141th birthday.

Wednesday, June 29, 2011

X100 first image

So the Fuji X100 arrived, and here is an early shot with it. Taken with lens wide open F/2.0 and +2 Exposure Compensation, ISO 800. I cropped, mirrored and scaled it in GIMP to make it manageable for the blog. I really like the soft focus with it, and the pleasant bokeh.

So you can expect a lot of nice pictures of Annelies soon. I guess I have to sign up for a flicker account now.

Batteries

Today, my Fujifilm X100 digital camera with an hybrid viewfinder arrived from Ontario. This fine piece of equipment comes in a jewelry box, no less. I'm very anxious to test it out, but am currently waiting for the battery to charge before I can begin flashing the firmware and then shoot my first picture. While my battery charges, I was looking into purchasing a second battery as backup. Shopping for batteries is a bit like shopping for an HDMI cable: there are huge price differences for the same model battery. Now with HDMI cables I know that the cheapest cable is just as good as the overpriced rip offs. With batteries, I actually do not know. Here are two pictures of the same NP95 battery. One costs $10 and the other costs $54. Should I get the original one from fuji? Or is the replacement battery just as good? Who knows. I do know that the Dutch consumer report 'de consumentenbond' once tested non-rechargeable batteries and found out that batteries from Ikea were by far the best buy you could make: lasted extremely long, and were really cheap. Certainly not a case of 'you get what you pay for'.

Friday, June 24, 2011

the 8th incarnation

The 8th incarnation of the little crane that could is imminent. I just uploaded v1.7 to Apple for review. It will support multi tasking so that progress in a level is not lost, if you switch apps. Also there is a new level, that lets you clean up flipped over police cars after a hockey riot. It should be in the app store soon, Apple normally approves updates in a week or so.

Monday, June 6, 2011

2007 called

It is so 2007, but hey, I just signed up for Twitter. You can follow me @BramStolk. My intended primary use is communicating with gamers that play the little crane that could. I will be using the hash tag #tlctc for this. What finally made me jump on the bandwagon was today's WWDC keynote announcing full integration of Twitter at OS level. I look forward to using iOS5 and OSX Lion, and of course the newly announced iCloud. I foresee exciting times ahead, and hopefully an imminent end to the monstrosity called Microsoft Windows.

Thursday, April 14, 2011

iOS developers: maybe not a rare breed after all?

So, how scarce are iOS developers. Or maybe, how bountiful? I think I got a rough glimpse on this matter, as Apple's Game Center was shining some light on it. Based on this, I am going to venture a wild guess that between a half and one percent of all iOS gamers have a developer account, and can thus be considered to be developers themselves. If this figure is correct, it is a lot more than I intuitively expected it to be.

To aid developers with the integration of Game Center in their apps, Apple has deployed a dual infrastructure. There are the production servers, for use by the population in general. There is also the Sandbox environment, where developers can submit test-scores, and see if their code is working as expected. Once a developer starts using this Sandbox environment, it is very easy to use the Sandbox by accident for all other gaming as well (thus, not when testing their own app, but enjoying a random app-store hit for instance, to relieve some stress). If this happens, scores from test users show up in the Sandbox leader boards of other developers.

So here are some statistics from the leader boards of my game the little crane that could. On the leader board for the second level of the game (basketball court), there are as of today:

314,960 names (production servers of Game Center)
2,112 names (sandbox servers of Game Center)

This ratio would indicate that 0.7% of all iOS gamers are iOS developers. Now of course, there are some other factors that may skew this measurement. Let me list a few of them for you:

First, there is the fact that some developers actually may log out of the test account before playing my game. I must say it is a lot easier to forget, than to actually switch accounts. This factor would cause the developer-gamers to be under-reported.

next, there is a difference of adoption rate(*): a developer may be more likely to have signed up for Game Center than a general gamer. This is simply because as a developer, he should be aware of these kind of things. Ignoring Game Center impacts a developer harder than it would a casual gamer who may prefer to stay with OpenFeint for instance. This factor would cause the developer-to-gamer ratio to be over estimated.

Last, it must be mentioned that it is conceivable that there has been a problem with Apple's servers. If general gamers were routed to the sandbox server, even for a small period of time, my estimation would be completely compromised, as the developers would be grossly over-reported. If this were to be the case, the margin of error would make my estimate useless.(**)

(*)Speaking of adoption rates of Game Center by gamers: it appears low to me. My game saw well over 1M downloads, yet the most played level in my game only sees 314K names. Is it because the gamers don't bother to finish this level, or do most gamers play without a Game Center account?

(**)This scenario would be unlikely though, as I have been steadily adding new levels to the game. These new levels show a similar ratio. This is evidence against incidental server problems.

Wednesday, April 6, 2011

Work around for xcode 4.0.1 crash in NSATSGlyphStorage

If you encounter a crash each time you try to load your xcode 4.0.1 project, you may be facing the same xcode4 bug that I experienced. I managed to work around it by deleting a file. From the call stack I gathered that the crash occurred during the layout of the source code editor. So deleting the layout info stopped it from crashing upon start up. if it happens to you, delete the file:

SOMEPROJECT.xcodeproj/project.xcworkspace/xcuserdata/SOMEUSER.xcuserdatad

Tuesday, April 5, 2011

Big Crane

Look at what payed us a visit this afternoon. Not the little crane that could, but its bigger brother, the big crane. It is laying some underground transmission lines under Laurel street for BC Hydro, the electricity provider here in Vancouver.

Thursday, March 24, 2011

Help for the little crane

In the next version of the little crane that could there will be a new vehicle. Alongside the little crane, there is now a dump truck to help out our little hero in the new level 'strip mine'. Version 1.3 is in the final stages, so should be submitted to the app store this week, for an imminent release.

Also new in this release will be Japanese and Dutch localizations, and a slightly better handling of the truck. For the non-paying customers, there will be two more levels to play, as 'bridge builder' and 'train station' will now be free.

Tuesday, March 22, 2011

Playing the Toronto stock market

If you have savings that are not tied up in residential properties, and have no debts, the logical thing to do with it is to invest it in the stock market. If you don't, your money will be eaten by inflation, as interest payed by Canadian banks is ridiculously low, and does not even match inflation. Here I document what stocks I bought and why, so that for future reference I can look back on my mistakes. I thought I would do it in public, so others may learn from the mistakes I made as well. I trade my stock at Toronto, because that is cheapest for me, and I avoid the bad currency conversion rates that RBC is prone to offer you.

So the first stock I bought after opening my trading account was a boring stock, just to test the trading portal, and see how buying stock works. The stock was RA or Royal Bank of Canada, as I figured it would be reasonably stable due to its size and steady operations. I bought this for 61.40 on march 9, and so far lost a few percent on it.

The next purchase I made was triggered by the Japan earth quake. In its wake, the markets fell, and the largest losers were nuclear energy related stocks. On Toronto, Uranium One (a large uranium mining company) fell hard during a couple of days. My common sense told me that the price drop was far too large to reflect the actual change of value of the company. This is why I bought UUU for 3.81 on march 15. This turned out to be a golden decision so far, as I bought it at almost the lowest point, and the stock shot up just as hard as it fell: so far a tidy profit in just a few days.

Next up were some utility stocks. I live in Vancouver, and see how much electricity is used here to heat and cool buildings. Frequent harsh winters and frequent hot summers, coupled with the ever expanding city makes me believe the demand on electricity will rise. Even though hydroelectricity is produced cheaply here, it is sold at really high rates to the consumers (you should see the energy bill I had on a 2 bedroom Beach Avenue apt). To find the stock, I typically look for bargains. I want to see healthy business for low price-to-book ratios, with low debts. This brought me to the renewable energy producer Boralex. I bough BLX for 8.46 on march 22. Boralex does hydro and geothermal. I also bought a solar energy technology company Arise Technologies, APV for 0.15 on march 22. With the advent of electric vehicles, electricity should become a hot commodity.

My friend tipped me on the growth potential of companies that work on 3D printing. On Nasdaq, there are Stratasys and 3D Systems corp. Both have sky high price to earnings ratios, so I will hold off for now. But would they ever crash, it could be time to scoop them up as they are potential supergrowers.

So, what are your ideas on the market? I would love to read them, so leave them in the comments. Let me conclude with a warning: never invest with borrowed money, only invest what you can spare.

Sunday, March 6, 2011

Disaster averted

These days, the little crane that could constitutes my livelihood. So it would make sense to take very good care of this product. Well, this morning I almost made a monumental mistake that could have done a lot of damage.

When preparing the 1.2 version update, I had put in some testing code that ignores the purchase made by the customer (the game is free, but customers can purchase extra levels). I was about to upload this version to Apple, when I decided to make one more screen shot of the application. I fired up the game on my iPad to make this screen shot, when I noticed that I could not play the level I wanted to, because it was still locked. That's odd, because I thought I already unlocked the content on that device. Then it dawned on me: could the test code still be active?

If this version had gone live, all the paying customers that downloaded the update would have seen their premium content locked again: argh! And I am not sure if Apple's review would have caught this error, as the in-app-purchase got introduced in 1.0 and I am not sure they will retest in subsequent versions. If they do: kudos to them.

Throughout the years, I have learned that paranoia helps when developing software. A paranoid coder is the best coder. And this is especially true during release time. Anyways, let me conclude with what will be coming in the v1.2 release of the little crane that could:

  • Big improvement in frames-per-second for smoother gameplay.
  • Added level "tower crane".
  • Optimized OpenGL ES2 drawing.
  • Faster fragment shader (no branching).
  • Fixed stutter when first moving levers.
  • Fixed crash when quickly changing the level after you fail one.
  • Disabled OpenDE asserts for faster physics computations.
  • On iPad, prefer interstitials over banners when available.

Monday, January 31, 2011

In good company

I found a list of quite some illustrious names. My game is mentioned along some real powerhouses like Angry Birds HD free in this list of iPad releases on the website of the independent. An honour bestowed on me because of the little crane that could's ranking as the number 1 free iPad app in the United Kingdom. After many tries, it looks like I finally managed to score a hit on the app store.

The feedback from it is quite overwhelming. A lot of rave reviews, but also a lot of useful criticisms. I will be using the feedback to improve the game for a new release. The runaway success took me by surprise. I had already accepted the fact that I made the crane game to suite my own gaming taste, and that it would probably do poorly on the app store, as it would not appeal to gamers in general. Well, luckily I was wrong.

It also taught me a valuable lesson of demand-pull versus technology-push. Before making 'the little crane that could', I decided to develop for the taste of the market. The game 'jump daisy, jump' was the result. It was the game I thought the market wanted: simple gameplay, bold colourful graphics, easy challenges. The little crane was the other end of the spectrum: a very complex game with a lot of controls. A game I personally liked playing, but which I deemed to complex for joe average. So when in doubt: go with your own passions, not on what you think people will like.

The little crane that could is a free game, so why not give it a try? Get your copy at iTunes.


What I thought the market wants versus what the market wants.

Sunday, January 2, 2011

dear mr Jobs

I just sent an email to Steve Jobs. Hopefully he will respond by telling me that Apple will eat its own dogfood.


Hello mr Jobs,

Nowadays my iPad is my primary device.
I am also an iPad developer, and the problem is that I can not use the developer forums with it.

Using an iPad you can only read the forum, but writing a message is not possible, as the input field of the message body can not be activated.
This has been the case since the iPad was released.
I am totally with you on not letting flash polute the device, but I do not think the forums are using flash.

Could you please put some gears in motion so that developers can use their ipad to write a message on the developer forums?

Thx,

   Bram Stolk

Sent from my iPad