2013-06-21

Super Foul Egg for iPad Released

Finally, after months of procrastination:

This one got straight into the App Store.

Obvious changes from the OSX version are:

  • Two player mode removed (still got a bug in the garbage transmission code);
  • Controls designed for the iPad touch screen;
  • Controls displayed via icons on the menu screens;
  • Pause and exit buttons whist in-game.

Less obvious changes are:

  • Multithreaded AI;
  • All code refactored.

I’ll open up the source code soon.

Give the game a try and let me know what you think!

EDIT:

Source code can be found here:

Apologies for its current scrappiness; adding networking support has meant changes all over the place. I remember reading an article years ago by a developer who suggested that networking should be built into a game from the start rather than added later as it’s a huge pain. I definitely agree with him.

2012-11-20

Super Foul Egg iPad Progress

Hardware test successful! SFE runs on both the standard and retina iPads. Now that I’ve switched it to using standard UIGestureRecognizers instead of trying to roll my own in the Cocos2D touches callbacks, the control system works flawlessly.

Once I’d succeeding in getting the controls working, I was very concerned about how usable and intuitive they’d be. My first few games saw me lose miserably to the easiest AI setting, but after a dozen games I progressed to the point where I can occasionally beat the “hard” setting. I’m nowhere near as good with the touchscreen as I am with the cursors (where I can sometimes beat the “insane” AI), but it proves that the touchscreen can work as an input device for this kind of game without resorting to an onscreen joypad.

Needless to say, I’m planning to buy an iCade 8-bitty joypad and get it working with that.

2012-11-17

Super Foul Egg - iPad

Soon:

Here’s what’s left to do:

  • Pause/exit game;
  • Replace any bitmaps that mention keys with bitmaps that mention touches;
  • Test it on real hardware.

I don’t currently have an iPad to test on. I had a quick try on the office iPad and discovered that the initial control system I’d written was unresponsive and unusable, so I’ve just finished a re-write of that.

I had two options for the control system. The obvious solution was to use an on-screen joypad. However, I detest iOS games that use an on-screen joypad to such a degree that I don’t even bother trying them. A more interesting solution was to try and work with the touchscreen instead of working against it and use gestures.

This is what I’ve implemented:

  • Tap with one finger to rotate the current shape clockwise;
  • Tap with two fingers to rotate the current shape anticlockwise;
  • Swipe downwards with two fingers to auto-drop the current shape (I had to concede that the hated auto-drop makes sense in the context of an iPad);
  • Touch and drag with one finger to move the current shape left and right (it follows the movements of the finger).

These gestures can be performed anywhere on the screen, which means the player’s fingers won’t get in the way of the action.

Unfortunately, I had to remove the two-player mode in order to accommodate this control system. I’m hoping that I’ll get around to using GameKit to allow multiplayer on several devices. Perhaps I’ll get an 8-player mode implemented.

Getting SFE working on a new platform has allowed me to look over the code again. Back in August 2011 I said this about the codebase:

My code probably looks hideous to experienced Objective-C coders as I’ve trampled conventions all over the place.

Just over a year later, I’m pleased to say that I agree with myself. The SFE code is pretty nasty in places. Here are a few mistakes I’ve spotted in the last few minutes:

  • Using #define instead of constants.

C guys use #define. C++ guys use consts. I went with #define because objc is clearly C-with-classes, but consts are better style.

  • Using blocks instead of protocols and delegates.

Blocks are cool! They’re also finicky when doing manual memory management and are an exceptionally good way to end up with cyclic references. For the most part I used blocks to separate out the game engine from the I/O code, which made the code vaguely MVC-like. Great idea (and wonderful for getting the game working on the iPad) but using delegates and protocols would have simplified things immensely and been more conventional.

  • Not cleaning up references after releasing objects.

Try doing something to the live block references in a Grid object when it doesn’t have live blocks. Ooops: crash.

  • Not following standard Objective-C naming conventions.

Pretty much everything should have been prefixed with “SZ” but wasn’t.

  • Following standard Objective-C naming conventions.

The enum names follow Apple’s official enum naming style (aside from the missing two character prefix), but then Apple have two styles and the official style sucks. It’s impossible to use autocompletion to determine the contents of an enum if the values are named “NSUTF16BigEndianStringEncoding” instead of “NSStringEncodingUTF16BigEndian”.

  • Using “SomeType* variable” instead of “SomeType *variable”.

Nitpicking, I know. I think the former makes the most sense semantically - the full type definition is “a pointer to SomeType”, so the asterisk is grouped with the type name - and is what I use in C/C++. However, I’ve been following Apple guidelines and now use the latter in objc. Apple don’t always follow this themselves, though. The fact that their templates don’t consistently place the opening brackets for a code block in the same place irritates me, too.

  • Protocol names.

“ControllerProtocol”: It’s like backwards Hungarian notation.

  • Fear of singletons.

It’s widely acknowledged that singletons are a Bad Pattern. They can’t be tested! They can’t be mocked! Every time you use a singleton a child dies! Look through most of my code and I’m pretty sure you’ll find that I try to avoid singletons wherever possible. Part of this was a response to the irrational level of hate levelled at the pattern, and part of it was due to the number of issues that singletons cause when working on web applications in .NET (hint: static variables have an application-level scope, not a client-level scope).

On the other hand, singletons are used extensively in Apple’s objc frameworks, and I now use them everywhere too. TDD crowd be damned. The “BlockFactory” could easily be a singleton, accessed via [SZBlockFactory sharedFactory], instead of being injected into every class that needs it like I’m writing some kind of enterprisey abomination.

  • “SZPoint”.

I’m hoping that this was a holdovee from the C++ version, because I can’t think of a valid reason why I’d create a class with identical functionality to CGPoint.

  • Reference counting.

I haven’t seen any examples yet, but this sentence from the August blogpost sounds extremely dumb:

For the most part, I’ve used what Objective-C calls “weak references” - I’ve got pointers to objects without retaining them, the same as I would in C++.

I might try to tidy some of this mess up. On the other hand, it ain’t broken…

2011-11-29

Enterprise iOS Apps

Recently I’ve been looking into the potential of iOS devices in the enterprise, which is surprisingly zeitgeisty. Computer users in enterprises typically have to deal with laptops that take 10 minutes to boot because they’re old, running Windows XP and laden with crufty enterprise junk. Users can’t install anything because they don’t have admin rights, and the IT department doesn’t want to spend its time uninstalling the Bing toolbar and Bonzi Buddy from the computers of techno-illiterates who, like magpies, are attracted by anything that blinks, flashes, glows or moves. They have to deal with IE6 and a virus killer that saps their CPU time and their will to live in equal measure.

A few people within enterprises have bought iPads or iPhones and suddenly find themselves with a computer that doesn’t have IE, doesn’t have viruses, allows them to install whatever they want and is always ready to use. They’ve realised that they can do most of their work with nothing more than an iPad and a Bluetooth keyboard. If only there was “an enterprise app for that” they could dump their bottom-of-the-range Dells with their oversized bag and carry around their iPads instead; hence the need for enterprise iOS applications.

The average enterprise application consists of:

  • An enormous, badly-designed database written by guys who didn’t know how to make databases but who once met the brother of a friend of an acquaintance who’d seen a SQL query a few years ago, didn’t really understand it, but thought it was pretty neat;
  • A vile, enterprisey “business logic” layer, with interfaces that describe factory classes that produce factories that produce classes that aren’t used anywhere in the codebase, because all of that clever planning and abstraction was a counterproductive waste of time;
  • A dumb web UI that allows CRUD operations on the database, cunningly designed to be 100% compatible with Internet Explorer 5 and 6 and utterly unusable in anything else, possibly even implemented as an ActiveX control masquerading as a website for marketing purposes.

Enterprise iOS apps will typically replace this last tier of the application stack. At the very least, apps need to be able to interact with the business logic layer to perform CRUD operations.

If you’ve been smart when putting together your existing systems, you’ll have followed Steve Yegge’s advice and built everything as a service. Want to know which user has the network ID “elb”? Point your web browser at your RESTful HR web service and query /employees/elb. The user’s details will be output in easy-to-parse JSON format.

In that case, you can give yourself a congratulatory pat on the back and go grab copies of ASIHTTPRequest and JSONKit. All of your systems are already set up in such a way that you can interact with them from pretty much any device that supports HTTP. It’s even easier if they can perform asynchronous requests and parse JSON.

If you haven’t built a service-oriented architecture, or were misguided enough to use WCF and SOAP - perhaps because you wanted to add a piquant dash of vendor lock-in to an architecture designed for heterogeneity - you could do far worse than take a look at Nancy. This is a micro web framework for C# based on Ruby’s Sinatra that will allow you to create RESTful web services, and indeed full websites, with astonishing ease.

The next issue you’ll have is security. What you really don’t want to do is expose your databases to the internet, particularly if those databases contain sensitive data such as employee details, client data, etc. If your iPhone needs to interact with a web service behind a firewall, what can you do?

You have 3 options:

  • Ignore the security issues and expose your web services to the internet;
  • Only allow the app to work when the iPhone is connected to the corporate network;
  • Connect the iPhone to the corporate network via a VPN.

I like to think of the first option as “the Sony approach”. If you don’t particularly value the privacy of your employees or your clients, don’t mind months of downtime when you try to shoehorn security features into a live system and aren’t embarrassed by publically demonstrating your astounding ineptness, this is a very worthwhile choice. On the other hand, you might recognise it as a security disaster waiting to happen.

The second option introduces some complexities. The whole point of a mobile app is that it’s, well, mobile. A mobile app that can only be used at a single location is obviously not amazingly useful. One possible workaround would be to cache relevant chunks of the database’s data on the iPhone. All CRUD would be performed on the cache. Any changes would get replicated to the master database when the device next connected to the corporate network. Obvious downsides are the need to deal with conflicting edits, either by automatic/manual merging or by asking the user if he wants to overwrite the remotely-edited version with his own changes.

It’s a tidy solution, but it introduces another security risk - your sensitive data is now stored on a highly desirable and easily mislaid phone. You could consider encrypting data stored on the iPhone. More extreme possibilities for securing the data include requiring a username and password to start the app (which would be a massive detriment to usability) or setting up the device in Exchange so that it can be remotely wiped if lost.

The third option is the best tradeoff between usefulness and security. VPN traffic will be encrypted, there’s no need to punch holes in the corporate firewall, and the VPN can be accessed from any location with internet connectivity. The iPhone has an excellent built-in VPN client that appears to offer identical functionality to the client in OSX. This solution obviously relies on the company having an existing VPN infrastructure or being open to the idea of implementing one.

The downside is that a lost device now has access to not only any enterprise apps but the VPN too. The risk associated with this can be mitigated by using a username/password combo to authenticate with the VPN instead of using a certificate. Certificate-based authentication happens automatically, whereas username/password-based authentication requires the user to type in his password every time he tries to connect. This might be the most appropriate approach to adopt anyway, as corporations are fond of implementing expiry policies that would necessitate the creation of new VPN certificates every few months. However, the user would need to manually sign on to the VPN each time they used the app. Worse, the iPhone has a habit of dropping VPN connections whenever it feels like it. How often do you want your users to enter their passwords?

The best approach is probably a mixture of the above:

  • Encrypt all local data
  • Set up all iOS devices in Exchange so that they can be remotely wiped
  • Allow read-only access offline by caching data on the device
  • Require a VPN connection for editing data

The VPN can authenticate via certificate for ease of use or via username/password for heightened security/to appease the password policy patrol.

Our enterprise iOS app architecture now looks like this:

  • MSSQL database used as storage
  • .NET-based business logic layer
  • RESTful Nancy web service exposing CRUD operations of business logic layer
  • VPN connection for encrypted, authenticated communication with the web service
  • iOS UI app that caches data locally for offline browsing and allows the user to interact with the web service via ASIHTTPRequest and JSONKit

Vaguely related to this, I’ve added a simple website/web service for distributing enterprise iOS apps to my BitBucket page:

It presents a list of iOS apps in an iOS-friendly website and allows them to be downloaded straight to the device. It can also be used by apps to determine the latest version number should they want to update themselves automatically.