100 Rogues: Ouya Post-mortem
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.
Our devotion to the craft can create incredible works, but the creative drive can just as often beget false hope for a future that might never be worth the cost. From iPhone, to iPad, to Mac App Store, I have been chasing after a successful indie career since the start of the mobile boom. So along comes Ouya, suggesting a future where small developers could make a living making the kinds of games they grew up playing and dreaming of making. In a market that might not be dominated by publishing giants dictating player interest from atop colossal towers of money, it seemed just within reach.
So, can I say if Ouya live up to this promise I've imagined? In short, I'd say it's still to early to tell, although I'm sure many would call that naïve. Will the Ouya game I've been developing over the last year succeed? I suppose 'developing' isn't quite the right word, as technically I've been porting a game I've developed since 2009, but I had to rewrite the whole sassafrassin' thing between August 2012 and August 2013. This will be a bit of a story, you see. The never-ending story of 100 Rogues.
When I heard about the Ouya Kickstarter, it had only been a few months since I was released from employment developing 100 Rogues, and my lifeline as a Professional game developer had been severed. Good riddance, too! I was achieving my life goals, sure, but at great personal cost. And even with three games under my belt I still couldn't seem to get a job at any of the studios I applied to. I faced starting from scratch, again. Either that, or I could just kick back and enjoy the 'temporary' new job in webdev with regular hours that paid nicely. I had just moved in with my boyfriend and was madly in love. Life was good, and no small part of me wanted to just give up the dream and walk away.
And yet... "console game". I fell in love with the thought minutes after learning about Ouya; all it took was a screenshot of 100 Rogues on my ps3 before I was sold on developing on the console. Use of the word 'sold' is deliberate, here; I've accepted from the start that the console might be, intentionally or otherwise, just people selling some dumb kids like me a chance at a dream that would never be fruitful. Nevertheless, after plunking down $750 on a devkit and a few controllers, I downloaded the C++ version of cocos2d, the engine I'd built Rogues on initially in Obj-C, and got to work.
The job had to be simple. Put 100 Rogues on Ouya, end of story. After all, the game was a brilliantly designed, gorgeously animated roguelike that didn't need anything more than what it already had to be an amazing game. The fatal flaw in our first release was that the iOS code was pockmarked by 600% schedule overrun due to feature creep, with 0% of that set aside specifically for testing and debugging. What's more, the game wasn't even written in the right language for an Ouya port. So that's what I would do: rewrite everything, and do it the right way. Put it on Ouya first, then bring the code quality back to iOS, then take it wherever else was reasonable (mobile Android seemed like an obvious first choice). In the off-chance Ouya did end up being a bust, it was still a low-risk gamble as a stepping stone away from iOS.
Fully appreciating the priorities for Ouya, and how I was able to make the port at all, requires a bit more history of my efforts on iOS. 100 Rogues was the result of a partnership between Fusion Reactions and Dinofarm Games. Fusion, traditionally a photography / web development / consultancy shop, hired me specifically for the project. Dinofarm provided the game design, music and art, and were instrumental in play testing and marketing the game. After the game released in May 2009, Dinofarm and Fusion continued collaborating through the first major content update to the game towards the end of that year. In 2010, Dinofarm began work on their second title, "Auro", and Fusion continued making content updates to 100 Rogues, which mostly brought an end to the working partnership between the entities. I worked on it, creating player classes, items, game modes and a puzzle spin-off game called 100 Trials, until Fusion cancelled the project funding in early 2012. The end of 100 Rogues coincided with the end of Fusion's foray into games, but my boss and I struck a gentleman's agreement that I could continue updating the game's software as I saw fit, and he would maintain the Apple Developer account.
Behind the simple timeline of events, 100 Rogues was, as both a product and a process, an unwieldy nightmare because of its perpetual cycle of feature creep. When major feature development stopped at iOS launch in 2009, I began our promised 'content updates', but really the game was still a broken mess. The code was held together by horrendous bugs that were either showstoppers or the result of hack jobs meant to prevent even worse showstoppers. It leaked like a sieve, and we were constantly blowing our texture memory budget. Having even promised and advertised content updates in the game itself, I did the best I could to debug and optimize opportunistically while making good on promises. "We need a monster with better AI? I'll just refactor all the AI, while I'm in there." Somehow that actually worked, and stability improved dramatically the first six months of the game's post-launch life, in this way. At the same time, however, I was piling a ton of new content into the game, complicating the test cases I would need to find remaining bugs.
So, the possibility of repeating any of the 'process' iOS went through from day one absolutely terrified me. If I didn't ship the most stable, bug-free game possible this time, I would be committing myself to another eternity of emergency patches that only created new problems. To calm those fears, I chose to cut all but the set of content most core to the game for Ouya, initially. None of the extra Monster classes, and none but the most basic set of items that I felt confident I could test myself, with 100% coverage, in less than a day. The rest could all be patched in at a pace that was reasonable for my quality assurance practices.
Roguelikes do live or die by their item count and interestingness, though. Even our design, which more emphasized strategic spells and physical abilities, wasn't completely exempt from that. What made it worse was that iOS had a full 2 years of post-release content updates that would be sorely noticed by players familiar with the game. So I plucked from iOS the feature that gave the biggest bang for the buck: stat mods that could randomly generate an "Armor of Accuracy", or "Energized Sword of Health". A few small extensions to item systems could create equipment buffs and easily triple the amount of equipment players could find. Ideally, I still plan to use that same code to recreate the more exotic equipment modifications 100 Rogues iOS had. Stuff like 'a sword that instakills its target six turns after hitting him' or 'armor you can eat to restore health' will be trivial to implement, but timely to test.
There were some additions made to the design, as well. "Fast Play" was an oft-requested gameplay mode that toggled on or off the longer animations in the game. Of course, there's no hard-and-fast rule as to what 'longer' is. You still want players to see continuous movement rather than instantaneous jumping between tiles, and assassins should make a little smoke puff when they teleport in front of you from nowhere, but you don't want to force players to sit through a 1-second bow-draw animation every turn, either. The case-by-case basis of the mode meant it was something I could only reasonably do as I developed, so it was given high priority for Ouya.
The other 'from the ground up or not at all' feature included into the new design was multiplayer. I'd had some experience creating a multi-class 'party' system in 100 Trials, which whet my appetite for a more fully-realized co-op experience. Multiplayer itself would fit well into the streamlined Fast Play mode, and I was extremely excited about the idea of couch co-op hitting its stride again on Ouya. Although the feature itself didn't make it into first release, enabling four players to wander through the levels and stab things, share items, use their special abilities, etc., as a team was only about 20 hours of extra work across the year of developing the port, which was right about where I had estimated. I'm still extremely eager to get the feature into the Ouya version.
Ugly and wrathful, I became during the early planning phase of the project. Being the only person working on the game, at this point, I took a greater degree of personal responsibility than ever. I fought unrelentingly for the hard decisions I felt were necessary in choosing what to cut, what to add, and what to make damn sure I got right this time.
The Dinofarm side of the original team still had a stake in the production, of course, and was entitled to some level of input in these decisions. There were many long, heated discussions needed to make sure the schedule for our already well-reviewed game wouldn't suffer. The possibility of being a launch title on a new console was at stake, and in so many ways I felt we just couldn't afford iterations refining the design or art.
After a few weeks deciding on scope and schedule estimates, as well as processes for feedback incorporating playtesting feedback, development officially began. I'd been in the trenches on this game for years, so it was easy to slip right back into 70+ hour weeks. Coding quickly became adversarial. Reviving the huge swaths of features from the decrepit iOS code base didn't have the same joy of discovery that development had the first time around. It was through-and-through grind as I tore through the checklist of features. More than just the tasks, though, it felt like I was waging war against my former self. The person that wrote the original code was a bleeding idiot. This was my way of killing that man, burning the body and making sure no one would ever know just how awful a programmer he was.
I brought back to life one monster or player class after another, ripping away pudgy, wrinkled bloat from old designs and casting them in lean, hard bodies that would last, that could take a beating and still survive regression. I found ways to unify AI agents under one class (Pets and Bosses became Monsters with some abstracted scripting support to modify their behaviour as needed), while simultaneously removing unsightly bits of parameterization from them. Entire subsystems got replaced by simple features or objects, many of which were provided by newer releases of cocos2d.
I kept a journal that was pages and pages of stuff like the last few paragraphs. Tracking every week of development, I wrote of my struggles as a Homeric Epic, as though every moment counted and any bug could spell destruction to my momentous schedule. It felt as glorious as it did grueling.
More than once I experienced a rage-incurring deja vu when bugs I'd spent weeks on in years past reared their ugly heads in C++, retriggering old woes debugging iOS code. I would code until daybreak just to make sure I never had to come back to those bugs the next time I sat down or ever again. It worked, but the toll it would eventually take on areas of my life outside of the game would be irreparable, I am very sorry to say.
I was, of course, deluding myself by thinking a 'finished' build could actually guarantee me a timely ship. No, even as the game features were completed in December 2012, a full three months prior to the intended launch date, I was unable to see how completely screwed I was, as far as scheduling. The problem? Serialization.
I've had a detestable relationship with serialization since day 1. It was something grossly, horrendously underestimated on iOS, and easily the source of more than 1/3, probably even 1/2, of the time spent debugging.
The most typical problem went something like this: player equips an armor that has a buff that boosts max health. The armor references the buff, the player references the buff, and the buff manages the maxHealth stat of the player. NSArchives, which were used on iOS, are designed to restore references like this when reloading state data, but nevertheless problems arose. The player would save the game, continues it, and unequip the armor. At various times, for various reasons, the buff might not be unapplied at all, allowing the player to exploit an infinitely high max health bonus. It might be unapplied twice, crippling the players max health and almost immediately making the game unwinnable. It might just crash the whole app. Cases like this arose for different types of equipment and different types of buffs. I could never plan a design for this problem on iOS because I had never done serialization before and didn't really know the problems to watch for, and because all the crazy stat-modding stuff was developed over the same three months that serialization was being introduced, planning the requirements was a moving target.
So, I made it a priority this time around to build around the Serialization requirement before any other, and to remove any risk of related complications from my own code. Knowing it to be an industry standard for several applications, I chose Boost's serialization library to do the heavy lifting for me.
That is the single worst mistake I have yet made as a game developer.
It's a gorgeous library, don't get me wrong. All serialization in and out is accomplished in one function definition. It's amazingly clean, simple to use, and fast as hell. It's also completely incompatible with android, and apparently it was up to me to discover that. Of course, my first question when researching boost at the start of the project was "will I actually be able to use this on Android?". And sure, you can use Boost on Android. You can use its threading, date/time, algorithms, asio, all sorts of things. But, unless you know how to write wchar / multibyte conversion functions for target hardware, you can not use Serialization. When the Ouya devkit finally arrived in January, I hit a segfault, and began a four-month long process of figuring that out for myself that you can't.
Or maybe you can! To be honest, I *still* don't know for sure. You see, I spent all that time digging through forums trying to find answers, configuring this or that in the build scripts, and even the experts from the boost mailing list would spend days talking me through some of my problems, looking at my code, before hitting the same roadblock and telling me it wasn't possible on the existing NDK. And, on I went to the next expert that reassured me that last guy was wrong, and that it would work perfectly.
I did have one guy tell me he actually had gotten objects to serialize on his android device. I have no idea how. I didn't ask, because that was in late May, and I'd long since given up and rewritten the whole damn thing myself.
All I do know is that if you google 'boost serialization android' you'll find little more than the graveyard of posts of my desperate pleas for help on the subject, as apparently I'm the pioneer of this particular failure.
The Boost Debacle dealt a massive blow to my morale during the first 3 months of 2013. I was bitter, miserable and exhausted. I'd lost 20 pounds, my boyfriend rightfully resented me for the neglect and tired surliness, and my (now part-time) income was slowly starving me.
Much as I love the game, I've longed to retire 100 Rogues and start one of the half-dozen games I've been designing over the years. But, it's my responsibility as a programmer to not rest until the code is of the highest quality, as much as it is my responsibility as an employee...ish of Fusion Reactions to do everything in my power to make the first massive investment profitable before I can just start something new.
Would Ouya make good on my 1,200+ hours of labor on the port, or any of the time put into iOS? Probably not. Would even a mobile android port bring in enough cash to begin developing a new game? If not, the only sensible thing to do would be to make a PC port and pray for a generous steam promotion or humble bundle inclusion. The gamble would never pay out, but the gamble was always the only option available to me, and I only had more and more investment to lose by just giving up.
It's thanks to two or three supportive people in my life that I was convinced of my ability to carry on and finish the game, because there were many nights I wanted to give up on more than just 100 Rogues.
Ultimately, I did have to give up on it, in part. I wouldn't say I ever completely stopped working, but I cut back to under ten hours a week on it for about a month. I spent more time with friends, got back to the gym, and I forced myself to play games again. Hope slowly returned, and I was able to pick up speed in rewriting serialization.
It was too late to ship on time, by then, however, but I decided my life and happiness were more important.
Pareto's a bitch. Now matter how close I felt like I was getting, there were always more and more little bugs, tweaks and adjustments whose priority was higher that I gave credit early in development. But this is hardly anything specific to my situation, compared to other software projects.
What was different for me, though, was how different these problems *felt*. There had never been a single moment working on iOS that I could conceive of the game as being bug-free. Launching it at all was a means to stop the hemorrhaging of money spent on development at a point where the game was playable. I can't hide from how horribly buggy the game has always been on iOS. Looking back, that's probably why I took the Boost failure so hard; the sense that nothing would ever work right just brought me crashing back to the pressures of perpetual emergency fixes that dominated the life of 100 Rogues iOS.
So it was an utter delight that, while the final months of Ouya debugging weren't completely smooth sailing, there weren't any problems I couldn't find and fix very quickly. My redesigns, planning, everything began paying off when the debugging phase wasn't the gordian knot of hacks to get the newest gold-plated must-have feature into the game. I felt confident in delaying just a few more weeks to really make sure the game was as good as it could be, because I knew the only problems left weren't horrifying ones on iOS that would have taken months rewriting subsystems to fix.
I started promoting the game again. I started talking to people about it, hearing them get excited for it and actually enjoy playing it. I actually took some pride in my work again.
After finishing the serialization rewrite right around the end of May, there was still a solid two and a half months of debugging and polish left to do. Had boost worked out of the box, I could have shipped back in March, before the Kickstarter release. Or, I could have taken the extra month or two just to continue polishing. I did ship with just a few bugs, a few inconsistencies. Familiars weren't as smart as I'd have liked. Exploits existed. Stuff to be left for the first patch, one I could get to when I felt like.
Getting the game from naught to feature complete took about 750 hours from August 2012 to December. At that point, I stopped counting my hours. Being that I wasn't making progress, and generally felt like a failure of a game developer, I didn't see fit to log the possibly hundreds of hours writing forum posts and tweaking build settings in combinatorial fashion, getting absolutely nowhere towards making boost serialization work. I never began logging hours again in May once the serialization rewrite picked up speed and the project began to close, either, but if I had to guess, I'd say the total time for the project broke over 1200 hours (not counting winter's boost woes ).
The game finally shipped to Ouya on August 13. We were rejected after only a couple of hours in review, due to some small issues with overscan boundaries. Ouya seem very keen to make sure games all look good on televisions, which is very reasonable. Our second attempt at submission went through without a hitch, and we were live on the store the next day.
The first week on the Ouya marketplace was weird. I had a couple of forums and communities dedicated to Ouya that I was talking with constantly who were all very excited about the game. I hit up as many review sites as I could, but much to my dismay, there simply weren't reviewers looking to write about the console's games. One site, Day of the Ouya, did give us great coverage, naming 100 Rogues their 'Game of the Week' for its launch week. Outside of that, though? Sure, you could find plenty of opinion pieces or reviews on the hardware as a whole, and maybe a handful about Towerfall, but very few sites featured reviews of individual games.
I'm afraid I'm not going to give the exact sales figures for the game here, but I can say pretty certainly that we weren't exempt from the paltry figures suggested by other developers. Sales on Ouya paled in comparison to our iOS release. However fair a comparison that is, I leave to you to decide.
In any case, proud as I was of the game and the attention it got, our early numbers did nothing to lift the despair I felt for my future career away from 100 Rogues. If investment capital for a new game was to be the goal, 100 Rogues would have to find more new homes. I wish it were different; I really wish Ouya's uphill battle would have been easily won, and that I could just make a living making my games. But there's more work ahead for us all.