RubyMotion Success Story: A Dark Room
A Dark Room is a very popular text-based role playing game (RPG). Originally web-based, Amir Rajan ported it to iOS using RubyMotion, and very quickly the app went from being the top game in the RPG category to be in the top 5 paid apps in the UK App Store. At the time of this writing it’s on its way to the top paid category of the US App Store.
The game now enjoys a 5-star rating and has been positively covered numerous times in the press.
We sat down with Amir to discuss his experience building this awesome game in RubyMotion.
What is your background, and what brought you to become involved in RubyMotion?
Before I took my sabbatical (I guess you can say I’ve gone independent now), my entire 8 year development career was all .Net development. I used ruby primarily for build automation during my day time job. Outside of my 9-5, side work I did was primarily Rails and NodeJS. I’ve contributed quite a bit to the open source .Net community. I’m a contributor to NSpec (an RSpec clone), SpecWatchr (an auto test tool for NSpec), Oak (a dynamic “poly fill” for C# andASP.NET MVC), and Canopy F# (a Web UI automation DSL for Selenium and PhantomJS).
One of my friends told me about RubyMotion. I was immediately interested given that I had an appetite for “different ways” (better ways) to approach problems.
Why did you choose to use RubyMotion instead of Xcode and Objective-C?
My first few apps that I built (none of which made it into the App Store) were actually built using Xcode and Objective C. Notably, I built a little budgeting app for myself with a Rails back end. At that time I actually had RubyMotion but wanted to have a solid basis of “vanilla” iOS development before making an assessment on RubyMotion.
One thing I saw immediately was the contrast between the work I did on the server side Rails app vs when I went back to Xcode. The hardest things to explain is the “Ruby mindset”: light weight environments, concise workflows, editor agnostic, fast feedback loops, simple API’s… essentially developer happiness.
As painful as it was to work outside of my souped up VIM environment, I completed my budgeting app using Xcode and Objective C for the client side. I did not enjoy the experience. Objective C is verbose, the Cocoa API’s are unintuitive, a lot of ceremony with regards to class definitions. Xcode makes it difficult to work with vendor libraries (try referencing AFNetworking for HTTP communication and Cedar for testing if you don’t believe me). Interface Builder was frustrating to work with too.
Now that I had my perspective, I worked with RubyMotion instead. The wrappers are wonderful (I primarily used BubbleWrap and Promotion). The rake tasks that come out of the box are great. Testing is first class, MacBacon has an RSpec style DSL that I know well and enjoy working with. Package management is solid, and I was able to use Objective-C libraries via CocoaPods. It just felt like everything was thought through, distilled down, and presented in a form that was immediately familiar to me given my Ruby background (and the “Ruby mindset”).
What inspired you to create “A Dark Room”?
A Dark Room is actually a joint venture between myself an Michael Townsend. He created the web version of the game. It went viral on Hacker News and I stumbled across it. At this time I was on a sabbatical, and decided that this would be a wonderful project to take on. I absolutely loved the web version of the game, but it wasn’t touch device compatible. I sent an email to Michael, asking if I could port it to iOS. He said yes! 4 months and 12,000 lines of RubyMotion later, I had a game in the App Store.
How did you begin writing the app, what were your early development stages?
I had some real world experience with Xcode and Objective C. In fact, the first few hours of A Dark Room development was done in in Xcode. I wanted to start fleshing out the engine of the game, and found it rather awkward using OCUnit. I rely heavily on fast feedback loops and incremental evolution. OCUnit did a good job in giving feedback, but fell short when it came to test composition. I refactored often, and what I found was that Objective C and OCUnit just made that an utter chore. I had a copy of RubyMotion, I knew that it had an RSpec style testing framework, and I knew how easy it was to refactor Ruby code. So I put the Obj C version of A Dark Room aside, and fired up RubyMotion.
I was extremely happy with the default template. Testing was baked in, the rake tasks were already in place to run tests. I created a light weight watchr script to run tests whenever I saved a file… everything just gelled really well :-)
As the game progressed, how difficult was it to add and remove features from your code base?
Not knowing RubyMotion, I initially stuck to using “vanilla” Cocoa apis for all my UI work. It was extremely easy to translate Objective C to Ruby. I was able to use all the resources on Stack Overflow whenever I hit a snag. Eventually, I was juggling a number of views and decided to look at ProMotion and BubbleWrap (which I found via the RubyMotion Wrappers site). The refactoring was easy. It amounted to deleting code ;-).
As far as the core game engine, I was able to use all the refactoring techniques of Ruby. All the language capabilities “just worked”: inheritence, class macros, modules/mixins, “send”, blocks, etc. My tests were always running in the background with every change I made.
Your app has been praised as being one of the few games that have are accessible to the blind. What did you do to make sure your app was accessible?
Accessibility changes were surprisingly simple to make. It’s amazing how much iOS does for you out of the box. Most of the first part of the game was already playable via VoiceOver. I ended up using an existing Objective-C open source library called SSAccessibility (it did all the hard work with regards to queueing multiple messages). I used CocoaPods to install the library, updated my Rakefile, and was up and running. The key take away here is that I was able to leverage the existing Objective-C ecosystem. Here is a write up of all the quirks with regards to making accessible apps.
What were some of your greatest, happiest moments during development?
Shipping. It’s hard to believe that the code base was over 12,000 lines. I was happy to get this mammoth out the door.
Were there times that the RubyMotion toolchain was a source of frustration? And how did you get those issues resolved?
I had a couple of instances where RubyMotion would throw a runtime exception without a backtrace (stacktrace). It was always related to the initial load of the app’s UIViews. I’d use git bisect to zero in on what line caused the error. It was tedious work at times.
Will you continue to use the RubyMotion compiler on future projects?
Absolutely. Without hesitation. Idiomatic Ruby wrappers on top of iOS, frictionless workflows, and the “it just works” culture that Ruby fosters, trumps any hesitation I once had. On top of that, I now have a fairly large app to serve as a testament to the platform.