Things were moving along so well I thought i’d jump a head a couple steps, and get Android builds up and running. Something I knew would be painful, and as expected it was.
Before that I have most of the core logic in the game, it’s not all up 100% but we’re now registering interactions and some of the core gameplay. I guess I’ll explain a bit how I do this. I grab a method, for this example ‘TouchMoved’, this is where I detect if a tile is being selected or not. I then simply take the existing cocos2d (objc) code and translate it to c++. Everything maps about .95:1 a very few exceptions, and those are easy enough to sort out. And then when I hit a method call that’s not implemented, I then add that stub and write out the code for it.
Example (pseudo code), in my ‘TouchMoved’ I have a call within, ‘if touch is valid, then execute draw connection code’, well when I got to that part, the draw connection code wasn’t implemented, so I then stubbed out the m ethos ‘drawConnections’, and then translated the code again from the origin objc to c++. Pretty easy, instead of going top to bottom through the old code, this way I can work in snippets of code of the same logic. Sometimes I find improvements in my rewrite this way, because I can see the flow of actions calling the methods.
I had to write some custom wrappers, because I have an interaction handler which uses touches for iOS devices, and mouse / keyboard for mac. I then use that class to send messages, so my core code doesn’t know / care if it’s a touch or a mouse click, to it it’s the same, and it simplifies the code. I had to re-implement that class in C++, and in there I found a limitation that I couldn’t use CCPoint as an argument to a notification. I then created a wrapper class which is a child of CCObject *, (cocos2d-x root object), which I can now easily pass around between the classes to handle my points. It was simple, clever, and it worked, the way good code should!
Now the wall —
So I decided to build up for android, and to do this I had to create an android project with cocos2d-x, and then integrate it into my iOS code. I’ve done this before with ‘Retro Art Studio’ for Android, but that was ages ago, and I’m using a much later version of cocos2d-x now (2.0.x). The configuration is one of the most painful parts of this whole project, and doing anything on Android. Android is hands down the worst platform to develop for period. It’s not that I don’t like the hardware or anything, it’s just very very difficult to configure, debug, etc, especially when doing this type of coding, where everything is custom drawn. iOS has basically 4 devices, iPhone/iPod normal (320×480 screen), the iPhone/iPod retina (Double resolution 640×960), easy as it’s just double. Then the iPad (1024×768) (very close to the iPhone Retina so we can re-use a lot of layouts), and the iPad Retina (Huge but once again, double 2048×1536). I have a couple extras I through in for Mac, which mainly re-use iPad assets. But that’s it, really 4 devices, some nuances in hardware, but displays are pretty easy to accommodate. Android on the other hand has over 2,000 devices with over 325 different possible resolutions, things from watches, to TV sized components. The other thing is the quality of the hardware / type of hardware is almost always an unknown. You don’t know if it’s a touch screen like iPhone, or if it’s an older one which requires a pen.
It’s easy to just go after the new fancy samsung phones, but still to this day only 15% of android users use the new software (4.0.x at this time), 60% are on 2.3, a really old archaic by mobile software terms software version. Unfortunately 2.3 is still being sold, because it’s cheap and widely used. So as a developer I have to support it, but with it you lose a lot of advanced functionality of the later operating systems, most importantly the ability to detect the screen type. On Android 3.x you can simply say ‘only run on a device that can support X resolution in pixels’, below that, (2.3) they don’t read / honor that flag, so users may install an app not designed for their phone. You have a choice, #1 don’t support 70% of the market (other 10% use < 2.3 still), #2 try to support low-end devices while trying to make high end games. It's painful to be blunt. So, the setup was painful to get cocos2-x to use android, to compile then run using Eclipse, while sharing all the code / doing all development in Xcode. It's something that I have to relearn every time, and I really wish I could document it and make it easier on myself and others going forward, but it's literally 4 hours of just hacking, trying this, modifying that, tweaking here, until it works, then you just back up slowly as it's a thin thin ice you don't want to go near. One last note on differences between iOS / Android in our app: WE parse a 80,000 word dictionary at the launch of the app, it's stored in a NSArray Plist, which is readable by cocos2d-x regardless of platform. On iOS (same code) it takes < 1 second, on Android (4.0.3 tablet) it takes 11 minutes. Ponder that, the hardware is virtually the same, actually I can get it in a couple seconds on an OLD iPod touch, 3rd generation, but a new Android Tablet takes 11 minutes. I'm pretty sure users aren't happy with the idea of a 11 minute loading time, so I'll look at other ways to do that file parsing, just unfortunate as it's so quick and easy on ios. It's not a limitation of android nor the hardware, just the limitation of they implementation. But it's small things like this which will take more time than rewriting a core to the game. Anyway, that's where we are hoping our next update has a basic playable version, but we need to fix this file loading issue first.