Wednesday, May 8, 2013

Rage Runner Postmortem


Rage Runner

Rage Runner is the first major release from Hypercane Studios (that’s us!).  Rage Runner is a fast-paced 3D obstacle avoidance game where the player hurdles down miles of trench as fast as possible while avoiding obstacles.  The levels are hand-crafted (not procedural) and the player is serenaded by some pretty awesome dubstep beats from artists TeknoAXE and Creedo.


Our Vision

When we created Rage Runner, the goal was to make a very difficult game.  We felt that the current generation of gamers have it way too easy.  Being from generation X -  the days of atari left overs and nintendo, we wanted Rage Runner to capture the difficulty of the games from our childhood.
In a nutshell, this meant that when you die, you start at the beginning.  To pass a level you actually have to get better at the game.  There’s no hand-holding in the form of visual cues indicating where to go.  We wanted people to rely on quick reactions and memory to beat a level and also wanted to convey a sense of urgency that would provoke the player to higher speeds.
For replayability, we wanted a sense of true competition within the community facilitated via a highscore server.  Lastly we wanted people to be able to be build their own levels in the game using the same level editor that we built the game with.

Postmortem

This postmortem attempts to analyze what went right and what went wrong during the development of our first game.  We are still new kids on the block in the indie scene and you’ll probably notice this from our game and from the content and style of this postmortem.  As there are only two of us, our comments are labeled.
Developer: Hypercane Studios
Release Date: March 28, 2013
Release Platform: OUYA
Development Engine: ShiVa 3D
Development Timeline: ~ 6 months
Team Size: 2
  • Jacob - Art, modeling, texturing, level design, marketing

Jacob - Christmas 1990

  • Zach - Programming, level design

Zach - Christmas 1990



What went right

Work Style & Being Bros

Jacob: I have heard the phrase a lot in my life that you “don’t mix business with family or friends”. I don’t think that this phrase could be more wrong.  Maybe it has something to do with the profession we have chosen, being in the game industry.  

When making a game, you need constant criticism or your work will never get better.  Being brothers we both speak our mind to each other.  If Zach doesn’t like something I’m doing, he will flat out tell me.  If I don’t like a mechanic he’s made, I’ll flat out tell him.  

But we don’t just leave it at that, we constantly brainstorm to make things better.  Of course we have our disagreements but after some long silences on skype and a quick break, we always work them out.  In the end I couldn’t be more happy in our choice to partner up to create Hypercane Studios and bring to life our visions we have had since childhood, together.

Zach: Throughout my career at various companies, there have always been co-workers that I or everyone else knew to be slackers.  When your partner comprises 50% of the team, there isn’t room for slacking, everyone needs to pull their weight.

Our past life as a hardcore raiding guild.
This is going to sound crazy, but based on playing World of Warcraft with my brother on/off for 5 years, I had complete faith in his work style.  Jake was guild leader, our guild name was Relentless and we were a solid raiding guild for end-game content.  Relentless is definitely the word I’d use to describe Jake.

We are both pretty hardcore guys that are motivated by failure.  We had to be willing to pick up slack on any aspect of the project, even if that meant diving in head-first in a field we had no experience or interest in like marketing.

Having that backdrop of knowing each other so well also made it easy to vent frustrations.  “Dude, this looks like ass” isn’t a phrase you might hear in the professional world, but with us it was the beginning of many constructive brainstorming sessions.
Taking Risks & Hard Release Dates
Jacob: We turned our attention to Ouya mainly because of the developer contest they put on.  We entered the contest expecting that we would not be picked.  This was just a good chance to show our work.  We made an Ouya level in our game using obstacles to spell out the words OUYA throughout the level (Zach built this level, and it took me roughly 3 hours to beat it).
To our surprise we were announced the day 5 winners, which we both couldn’t believe!  Ouya wanted our game to come to their console and were giving us a dev kit to make that happen. This felt like a big compliment that we were headed in the right direction with the game.  We also got a lot of dedicated followers out of this that really believed we were making something that they wanted to play.

Zach: I was developing this game part-time, so getting solid time to spend on it was hard to come by.  This usually meant weekends and evenings only.  So, sacrificing 8 hours of freedom to enter a contest that you believe you have zero chance of winning really does feel like a waste of time.
But we did it anyway for the publicity.  I think we had 2 retweets on our entry.  When we were chosen as winners this gave us a very tangible hard release date of March 9.  We picked this date because it was three full weeks before the March 28th market launch.  

Having a solid release date kept us on track
Having a solid date sitting in front of us every day was awesome.  It was a constant driving force that made us ask the question “What is the #1 priority today so we can release in X days?”.  I can see how the absence of a release date could cause an indie project to drag on indefinitely.
Iterative Design & Throwing Stuff Away
Zach: We used an iterative design process similar to Media Molecule’s game jam development style.  From a high-level, we knew how we wanted the game to play but to reach that vision we had to play around in the sandbox for quite some time, tweak things, re-write things, throw things away, etc.
Sometimes you just don’t know whether a mechanic is going to be fun or whether an art asset is going to work until you try it out.  For instance I remember a few trench textures where they looked great as a still image but looked like a strobe light when in motion.
An early prototype of the add-on system was scrapped mid-production.
One major feature we scrapped was the ship upgrade system.  I wrote a ton of code to facilitate this and created a bunch of balanced item stats for various upgrade levels as well.  In the end, we decided this was too ambitious so we scrapped the whole feature.
Being able to look at the project objectively is important.  I was attached to the code I wrote, but I knew that tossing it was going to make our core game stronger.  Throwing away code can be very liberating and it brought a clearer sense of purpose to the features not yet written.
Being Pushed
Jacob: Making Rage Runner pushed me to what I thought my limits were and then beyond.  The game sounds simple enough in theory, but honestly for what we were trying to accomplish in 3D on a tegra 3, it wasn’t easy.
Our game is close up which means mistakes really can’t be hidden at all.  The game is crazy fast which meant the obstacles needed to be easy to see and the trench couldn’t be too overpowering or it would cause a distracting strobe light effect. The poly count had to be under 20k tris which in the 3d world means 10k polys.  
Early textures of the obstacles (except for fan)
I think all these elements combined really pushed me.  If you look at my first trench and obstacle maps, you can see how boring they were.  At the time I thought they were awesome! I ended up getting our tri count to around 12k in total, which is pretty low considering I was around 80k tris on our first build.

An early version of the trench texture
I got a better understanding of how to do texturing after a lot of research and critique and I think my modeling techniques have become more refined for game modeling. I look back now and cringe when I see my old work.  I still have a lot to learn, but this game has got me headed in the right direction. I really love everything about 3D and 2D art for game making and can’t wait to get started on our next project.
Finding Friends
Jacob: I think the OUYA community in general is absolutely amazing.  From the OUYA creators, who will bend over backwards to help in anyway they can.  To the OUYA supporters and the forums they have created.  
Ouya blossomed into a major Indie developer platform and the forums have allowed us to keep in close contact with developers like ourselves.  It’s great to easily find multiple places to bounce ideas off folks or get your work critiqued by people that believe in what you are doing.
Zach: It's good to be part of a community that shares your goals and that has brilliant people making things that amaze you. We all need inspiring once in awhile and it helps to chat with people facing the same problems as you.

What went wrong
Not Having Visual Target Nailed Down
Jacob: When we first started making Rage Runner we had decided to target the PC.  Two weeks later, we won the OUYA contest.  Developing for PC vs OUYA are two very different things graphically speaking.  It still wasn't clear exactly what the OUYA could handle without having the hardware.
My biggest fear was that I would have to cut down my model poly count or even start from scratch.  We were about 5 weeks into development when Zach finally got ahold of the nexus 7 which would give us our most accurate benchmark.  I still remember that fateful phone conversation.  My throat tightened up as I received the news that basically all the stuff I had done would have to be redone.  In the end we have learned that a game needs a well defined visual target before starting.
Zach: Man was this difficult.  The performance results from the Nexus 7 were a bit deceptive unfortunately.  Nexus 7 resolution is 1280 x 800 whereas the Ouya is 1080p.  So (1280x800) / (1920x1080) = ~ 49%.  That means the native resolution of the Nexus 7 contains only 49% of the pixels of the Ouya.
You wonder why your game runs better on the Nexus 7 vs the Ouya and then you realize that the Ouya is pushing out basically double the number of pixels every frame.  Bad benchmark, how could I have been so careless?
Not Reading Docs & Nailing Down Technical Target
Zach: The built in physics engine (ODE) that ShiVa uses was another point of contention.  At many levels, what I want as a developer are drag n drop modules that let me focus my energy on making a game. The physics engine felt like this at first, weeee I'm applying impulses and forces and things move! Let's use this for everything in the game, it's so easy!
Then one day, level testing at high speeds I found myself passing directly through the center of objects. What the hell? I thought this thing did continuous penetration testing?  Hmm, how does this thing do penetration testing?  Oh, it doesn’t :(
After a few hours of reading documentation and writing some gnarly functions with questionably inappropriate names like doDePenetrate() and doPenetrationPrecog(), I found myself wishing I had rolled my own physics and collision detection. Our game was simply a bad fit for this physics engine and had I known this months ago I would not have used it.
In the end I basically rolled my own primitive anti-penetration system by adjusting ray cast length based on the velocity of objects and average framerate.  It would have been much easier to roll my own physics entirely from scratch but this was realized after I had finished the mechanics implementation using the physics engine, gutting the whole thing was a scary task that I wasn’t willing to engage in.
Not Truly Understanding 3D Game Art
Jacob: When we started working on this game, I had been teaching myself basic 3D modeling for about a year and had never done any 2D work.  I also decided to switch from Blender to 3D Studio Max right around when we started this project.  When I look back now and realize how little I really knew about being a game artist, it always gives me a good chuckle.
I really had no concept of what artists went through to make a game.  I thought, hey, you model it, slap a texture onto it and you are good to go.  I found that modeling was about 10 percent of what I did and the other 90 percent of the time I was screwing with textures and UV maps.
In the end, I wasted a lot of time constantly having to cut down models while learning proper techniques for game making. The amount of knowledge you get from your first game is priceless, and for me it has only made me better.
Not Using Artists to Critique Art
Jacob: When I created my first Rage Runner ship it took me 1 week.  I was sooo proud of it, I spent so much time modeling every detail and then I spent days on the texture of it.  I sent pics to my brother and one of our good friends and they both loved it.
The first Rage Runner ship model.
I then decided to join an artist forum and post my work to get some feedback and possibly some suggestions on improving it.  What was to follow was some major criticism of my work that I wasn't prepared for.  
Most of them said it just looked like a cylinder with wings and that it needed a lot of work or a flat out remodel. This took me into a deep depression for about 3 weeks.  I would get 4 hours of sleep a night, get up and start working on my ship model and textures.  At this point Zach couldn’t understand what was wrong with the ship, he thought it looked fine.  But I just couldn't take the negative criticism at all.  
Being new to the field, I was stressed that I didn't know enough about 3D or 2D, that nobody was going to like what I was making and that I needed to push myself to do better.  Another major thought that was always in my head was, my brother is this genius programmer, and I'm not even close to as talented as him with my art yet.
Not Understanding Engine Features vs Hardware Features
Zach: On the graphics front, I had the naive impression that occlusion culling was supported on the tegra 3. I had very carefully setup my dynamic occluders ahead of time and performance was great on my 5 year old PC.
I felt the fear of failure in the pit of my stomach the first time I fired up a level on the OUYA and saw performance tank. Since our levels are literally straight as an arrow, without occlusion culling, the entire level was being rendered simultaneously. I mean, the whole level existed in the view frustum, so as the level progressed, fps would slowly increase until you flew through the unfinished end into the blackness of 60 fps empty space.
The occlusion culling in Shiva is based on hardware support of the GL_ARB extension. I didn't know, I didn't even think to look.
Programmer Bottleneck for Graphical Prototyping
Zach: Our graphical prototyping process was a frustrating cycle because it was so tightly intertwined with our performance tuning.  Everything looks and runs amazing on the PC where Jake is working and it sometimes took a day before I could test new assets on the Ouya to say whether they were going to work.  
If they didn't work, I'd have to bang my head to determine exactly why. Why is this dropping fps by 20?  Is it the material, is it the geometry, is it our game engine, is it a stray sensor firing in a loop, is it some random AI that I just changed, are we alpha blending too many pixels?  Ultimately I wish I could have decoupled the whole art pipeline from the technical side of things to allow Jake to easily plop in a new model, hit play and see it in game.
Jacob: When Zach gets a model from me he expects it to never change.  He has to add colliders and all this other junk to get it into the game and working. For me this was hard to work around, mainly because I really don’t get an accurate representation of what my model looks like until I see it in the game and moving.


Some finalized obstacles
When I see the model in the game, I can then see all the mistakes or fixes that need to be done.  Most of the time it was just texture stuff, which is fine and easy to fix without replacing a model, but sometimes it’s a UV fix that requires a model change.
It’s a fine line seeing the game from my view as an artist and Zach’s view as a programmer.  I want everything to look as I intended it to look, but Zach just wants stuff to run at 60 fps and move on to the next challenge.  
This just came from my inexperience as an artist, something I strive to get better at.  I still dread the words from Zach, "are you sure this model is final?"  I usually reply with "it should be, but I have to see it in game first".  In retrospect, I think I wasted a lot of Zach’s time just replacing models because I never seemed to be happy.  
Lack Of Thorough Testing Early On
Zach: Our game is hard to test and I didn't have a good test methodology laid out. Often, I wouldn't discover an issue until Jake made a level and used an obstacle in a way I hadn't thought of.
"You can't use those like that" wasn't an acceptable answer since the level editor would allow for all manner of use.  A few times I discovered core mechanics and engine bugs that would have been caught if only I tried rotating a block by 45 degrees.
Showing Pre-Production Video
Jacob: We created one of the hardest games to capture on video.  The game moves too fast and is too dark to get good looking video.  This frustrated me the most, because the game looked amazing and the video made it look like crap. In the end our final Rage Runner Trailer was the best quality we could achieve with these limitations, which ended up being about a 50 percent quality loss when shown on youtube.



We were under the impression that being indie meant that we could have a transparent development process. One where we could have fun and show people early prototypes.  This turned out to be a mistake, we should have been doing updates with screenshots only because of the quality loss on video.  



I know now that people need to see the best possible representation of your game.  If there is a 50 percent reduction in quality, you need to show the game in a form that doesn’t lose quality.  I think our final video count was 10 total, I believe we should have only done a total of 3 videos.  We showed too much of the game, too early in development with bad quality videos that deterred many people from it.  
Being Too Clever On 1 Platform
Zach: I am a very experienced android developer, so I took advantage of the platform and integrated some nice custom functionality on it.
OK, that's great for android, what about PC, Mac, Linux, PS Vita, iOS? This was really stupid of me.  I could have and should have done it all within the game engine using xml, post requests and 2D HUD.  Then I would only have had to write it once.
This is the curse of using what you’re comfortable with.  The Android stuff didn’t take long to do, but now I have to do all of that over again to go to any other platform.  Lesson learned is that if you are using a game engine that exports to multiple platforms then leverage every baked implementation you can.
Only use custom implementations when absolutely necessary and remember that you have to do this on every platform.  
Technical Issues
Jacob: We hit a point in development where things were starting to take shape, I had finally got the ship to where I was happy with it and my texture work was starting to get better.  I had been having a lag issue in 3D max, so I called my brother to see if he could lend a hand in figuring out the cause.  
I was sitting there watching him check stuff out when all of a sudden 3D max froze.  I reopened max and tried to load up the ship model but for some reason the model wouldn't load.
The crash wiped all my project files, all my models, all my textures, EVERYTHING!  I remember hearing a ringing noise in my ears and my chest tighten up.  We recovered a trickle of data with an undelete utility but most of what was lost was gone for good.  
The new 5k ship model.
At this point I almost threw in the towel, I was beyond pissed and stressed.  In the end this is probably the best thing that happened to me.  It forced me to do my 3rd and final remodel and texture of our ship, trench and obstacles. This time I knew more going into the ship, I knew that 20000 polys is ridiculous for a game asset.  My target was under 5k, which I hit, I then did the same with our trench and ended up dropping that to under 500 polys.
We hit our performance mark thanks to file corruption.
As a result of losing my assets our game looks better IMO.  I really put a lot of time into the textures, trying to create my vision that I could so clearly see in my head. It may not be AAA quality yet, but I think this game has got me a step in the right direction.  
Zach: Shortly after Jake suffered from his hard disk corruption, my raid array failed and destroyed all of my data.  Honestly, if I had lost our entire project I would have probably thrown in the towel.  For once in my life, my overly zealous worst-case scenario backup plan paid off.
 
I grabbed one of my redundant git repo copies and was ready to rock without a line of code lost.  Unfortunately in the process I made the horrible decision to install a developer preview of Windows 8 when I threw the computer back together.  This all made perfect sense at the time and was just another way for me to tickle my inner geek and try out Windows 8.
About a month later, my preview copy of windows expired and my computer started involuntarily rebooting every 2 hours (thanks microsoft).  So I literally had to set a timer for 1 hour 50 minutes so I could save my work before the forced reboot.  Amazingly I survived this way for a good month because configuring a new development environment would cost me a full 1-2 days of productivity.  I mean, once you get all your android sdk/ndk setup, your jdk 32/64-bit versions working correctly and your environment variables and build scripts nailed down, it is a lot of work redoing all of that on a whim.
Typical skype conversation:
“What the hell is that noise?”
“shoot, I’m about to reboot, I’ll be back in a few”


Takeaway: don't try new technologies in the middle of a development cycle.
Being First, Being Alone
Zach: It’s not easy being first, it’s very discouraging to search google for an answer only to have your own posts returned as the search results.  The engine we used isn’t very popular and we were the first people targeting the OUYA on the engine.
I had to write the engine integration myself and never saw other references so I was always concerned that maybe I had really screwed something up and we were going to get some horrible controller latency eventually due to controller polling.  Several benchmarks later, I had satisfied my anxiety that my controller polling was good to go.
A frantic post asking for performance help.
We had a lot of performance issues.  Literally every day I was tweaking performance and it took me a long time to flush out all of the small details that were cause our major hits.  I was a little disappointed that I had no help from the official ShiVa folks in this endeavor.


You find benchmarks everywhere but no one talks about how to interpret them from a game design perspective. Like most newb programmers, I wrote a benchmark for the OUYA that gave me raw max poly count at 60 fps. I then stupidly told Jake what our limit was. The problem is that this number doesn't factor in lighting, shadows, physics, alpha blending and AI running in the background.
Simple things like enabling text anti-aliasing in the HUD (something I always did in the past) would cause performance to tank when the HUD element was drawn.  The Ouya hardware didn’t support hardware anti-aliasing, well, I didn’t know that 2D font anti-aliasing was implemented that way.
This may sound naive, but many aspects of a commercial game engine put you into a seat of naivety.  You get used to not having to worry about certain things until suddenly you’re expected to know how the entire universe unravels around a single checkbox down to the hardware level openGL extensions of your target platform.  Annoying and frustrating.
I know now that specific features are tied to specific extensions and I can look for and connect those dots.  What I was missing initially was a description of these things in any piece of documentation, even a warning “make sure your hardware supports this” would have been enough.  I’m less of a newb now I suppose.
Performance scribbles
I spent most of my development time tracking down these magic sliders and checkboxes that were then put on the Hypercane Studios blacklist.  Jake knows them well, they are the forbidden fruit that make your games look amazing but that we aren’t allowed to use: any post-processing like bloom, backlighting, opacity, fresnel, ocean, anti-aliasing, polytrails, burst-maps, normal maps, spec maps, pixel-based lighting, shadows, skyboxes, camera distortion.
I’m not saying these features are problematic in the engine, I’m saying that for our game - the way we travel inside the trench, the proximity of the models and textures to the near camera plane and the rate at which they move toward the player all combine into a result that makes the hardware buckle if any of the above are used.
Horrible Timing & Rushed Decisions
Zach: At some point I realized that there was a major deficiency in the game engine.  In Shiva, you can mark a model as a collider.  Colliders are taken into account in the physics engine as a collision surface and also allow you to cast rays to test whether there are colliders in the ray cast path.
When the player destroys an obstacle with a missile, the collider associated with that obstacle was not getting disabled.  You see, to facilitate immediate level resetting, we simply hide the obstacle, this marks the obstacle as inactive which should have disabled the collider.  It didn’t.
The beta version of the engine fixed this issue and also gave the ability to dynamically create and destroy these colliders.  This was a pretty vital feature for me and we decided to update to the beta engine just for this feature.
Moving to the beta meant that now we only had a single seat for the engine.  Unfortunately at this time, the company behind the engine went into liquidation (I guess this is the non-US way of saying bankruptcy).  As a side-effect their store was unavailable and we couldn’t purchase an additional seat.
So now we were forced down a path where Jake could no longer hop into the project and fire it up or import assets.  This was painful, we had to change our workflow to one where Jake imported and checked assets into the older version of Shiva and then exported them to dropbox where I could import them into the new version.
Dealing with Negativity on the Internet
Jacob: We decided to release alpha footage of our current progress on Rage Runner to the world in December.  At this point we were about 6 weeks into development and couldn't wait to show what we had been working on.
We had positive comments and up votes at the start but then after about a week, the haters came in droves.  This spiraled me into my second depression cycle lol, I just couldn't handle people not liking my art work.  Were they seeing the same video?  Do they know that the models are just basic material not textured yet?  Do they know this is a grey box video?
In the end this negative press pushed me even more to better myself and my models.  But I did lose a lot more sleep over all the negativity that our first video produced.  I learned that people know nothing unless you tell them, most people on youtube have no Idea what it takes to make a game or what a grey box video is.  I really thought the game looked awesome from where I was standing.
Zach: I find it difficult to relate to the graphics-hungry critique of the general population.  I grew up in an era when all games looked like crap and it didn’t matter because they were fun.  The atari could only draw 2 sprites, 2 missiles, a ball and a playfield - if you wanted more than that then you had to live with flicker.  Similarly, the box art of mario is blown up so large you can count the individual pixels.
I don’t understand why all games are based solely on how they look these days.  The Impossible Game was 100 times more fun and engaging than any of the Assassins Creed games.  I still think that the initial Rage Runner models in our video looked amazing and that the gameplay was solid.
Generally the people that post comments have no perspective, no courtesy and no knowledge of what it takes to make a game.  But, somewhere behind all that negativity is probably a real person that’s pretty cool once you get to know them.  I believe that just like every pirate is a potential customer, every troll is a potential fanboy.
Not Having a 2D Artist
Jacob: Before this game I had never done any 2D art.  I did the occasional screwing around in gimp, but nothing major.  I found out the hard way that we really need a 2D artist. I love 3d modeling, UV mapping and texturing my models... but when it comes to cover art and UI work, I really hate it.  
This is mainly because I just don’t have the skill for this stuff yet.  I feel Rage Runner was really missing someone that has an understanding of this art.  When you first load the game it looks like a school project with the main menu.  But when you actually play the game, it looks like a real video game.
I used to be hard on myself because I just had no real vision when it came to the UI and menus. After some research and finding that most game companies have multiple dedicated 2D artists, I felt better.  We are working on improving the main screen and menus at this point jointly, but have both agreed that we just hate doing this type of stuff.
We have talked on the subject in depth and came to the conclusion that we are going to be looking for a full-time 2D artist for our upcoming projects.
Zach: I’m about as left-brained as it gets.  I simply do not have a vision for what a cool UI should look like.  In my mind it would be an awesome command prompt with a black background and green text.  
We need a 2D artist bad, real bad.  Someone with a vision of how the entire game should tie together visually, what color palettes we should use, what font we should use, the typographic layout of our text, how we should transition from screen to screen, etc etc.  
It sounds trivial, but when I’m coding up a new menu and suddenly have to throw text and stuff up on the screen, I sometimes sit at the font menu in a daze for minutes.  I have no objective measure of a good or bad font, I choose fonts based on them being fixed-width so my code lines up all pretty.
Wrapup
When we finished Rage Runner, we had achieved everything we set out to do.  We are still surprised that we were able to create this game.  Overall the experience has made both of us better at what we love to do and we couldn't be happier with our first title.