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.
I’m hoping that this was a holdover 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…