Game Postmortem

From Art to App

Posted by Vance Feld on October 27, 2016

[0] ForeverScape?

The ForeverScape is an Artwork, an App and a Game. You can also listen to an interview about the app with Matt Groves.

[1] Why Not Native?

As a solo developer working on a side project, there was no way I could master both Android and iOS development in the short amount of time, let alone maintain two codebases. On the other hand, thousands of images scrolling smoothly is a tough challenge for JavaScript on mobile. I knew it would be an uphill battle. However, I got good results despite a few challenges.

The ForeverScape app is a good litmus test, because it pushes the performance boundary. The performance on iOS is great and Android was decent once I installed Intel’s Crosswalk. It ships a Chromium engine instead of the factory installed Android browser. It was only 1/10th of my final app size. I would suggest anyone write their next app in javascript/nativescript/typescript—especially since most apps don't come close to the GPU memory demands of loading and unloading high-resolution images at rapid rates.

I see some shops are still doing native development with 2x developers. Some people argue superior animation quality, some argue native feel... Any of the javascript frameworks can animate transitions (some even use Native Transitions). Honestly, while I do use a lot of native-wrapping modules, I'm more concerned with consistency across devices (less testing) and less maintenance cost since this is a giant time and resource sink for me. As it would be for any company... But the die-hard native devs will downvote any comment that threatens their native Forbidden Palace.

On this project though, I don't feel I spent a disproportionate amount of time on performance compared to other agency-scale interactives I've done. I didn't even crack open WebGL this time, or parallel WebCL like some of my early visualizations. Maybe next time!

One of the common arguments against non-native mobile is, the UI will not keep up with the native conventions as they change. Nativescript changes the game, since javascript wraps the Native UI and not a web view. It's like the native platform becomes the rendering target instead of HTML. It's amazing not going through the browser as a middleman. Skipping the browser to hit the OS is as slick as reaching out to the GPU via WebGL. Liberating! I likely would have picked NativeScript if it was mature and on my radar at the time. It was a race against time, I didn't have a spare moment to do three more POCs. My branch with the most progress was the ionic1 fork. Since I knew angular1 well, and it stood on Cordova, another proven technology, I knew I wouldn't get caught on the ugliest snags. Some other poor soul forged the path with their corpse. At the time of this writing, I saw an Angular2 > ReactNative rendering module which could prove interesting down the road. I will FOR SURE check it out... later.

[2] Challenges of Native Scrolling

Unrelated to Performance

Anyone wanting to do large image scrolling? Native scroll is your best friend. It's as easy as overflow-scroll = "true". You would not know you were looking at HTML as it uses the Native iOS or Android hardware acceleration. The problem I had was not with performance, but the incompleteness of the Ionic scrolling API. Most people would not need accurate scroll.offset() measurements during deceleration. You could rely on built-in bounce back logic. I demanded custom, load-the-rest-of-the-rasterized-tile-sequence-seemlessly while-scrolling-and-keeping-track-of-waypoint-positions. Most apps don’t mutate state based on scroll position all that often….

I’m convinced that it is Ionic not passing the correct events from the Native API. For instance, it may not be passing all the properties of the UIScrollView properly. E.g., UIScrollView --> targetContentOffset. I'm not sure where I should throw the blame dart; Apple, Cordova or Ionic. Chances are, it may just be an Ionic1 issue. Will update.

Basically, my plan was to have INFINITE scrolling in any direction. The math of the ForeverScape allows for scrolling left and right perpetually. In essence, the entire piece repeats, but shifted one row up on the right and one row down on the left. This is done into perpetuity. The idea was to have three containers, and every time you get to the edge, swap the container with the new row-shifted content. I sunk a lot of time getting this right, only to realize there were big bugs caused by lack of deceleration events. I couldn’t measure the scroll offset correctly, and therefore couldn’t use that value to determine when to swap the contents (min,max) cross. I filed bugs and found some existing issues. Maybe one day Ionic, Apple or Apache Cordova (or I) can fix the event pass-throughs. The compromise was to just have 3 static containers. In the meantime, users already complain that the "game is too hard because it repeats at the edges. The periodic, fractilian wrapping is confusing!" Damn straight, it's confusing! How do you think I feel? I guess true infinite scrolling will have to come down the road.

[3] Screwed By Zooming

I will put it this way. Zooming screwed me. I didn’t think zooming would be a big deal. Native pinch on native scroll in Safari Mobile or Android work fine! Big mistake. I merrily went about solving other problems and knocking out features. I was probably teetering on that awkward precipice of “proof of concept” and "there’s no turning back.” Well, I almost turned back. In hindsight, I wonder if I should have… I'll face-barf this in another post.

Due to the discovery that native scrolling in Ionic does not support pinch-to-zoom, or any zooming at all I was at first in denial and tried every CSS hack in the book until 3 AM. Then I was in shock. I couldn’t bear to look at code. Had I backed myself into a corner? I would have to start over again. I will (likely) drunk-rant about how I solved this in a future post. I may even solve it better one day.

[4] The Joy & Danger of Solo Development

I got dinged early on in the ForeverScape App project. By early, I mean an attempt made 2 years prior. I completely threw out all the code. I wasted a couple months. Had a game prototype. But I got squashed by the weight of performance and memory management issues outside the emulators and intel chipsets... I had chosen a technology still in it’s infancy for mobile development. HaXe, if you’re curious. I think if I were making your average 3/4 perspective platformer or 2-D scroller I would have been fine. I would have found the documentation I needed to dig out of a low-level GPU issue. I could have used any off-the-shelf game engine for HaXe, BUT... People often ask, why didn’t I just use an off-the-shelf mapping SDK? Well, because the ForeverScape is periodic. I

don’t know of many software developers, in my circle or beyond, who have dealt with non-symmetrical periodic tessellations, let alone build a framework around it. It just does not fit well with your typical 2-D matrix system. I’ve tried to hack it into a tiling library once and it failed miserably because the core of the entire grid system relies on square (3,3) transformation matrices with an eventually discreet, non-symmetrical or terminating boundary relative to the axis. MASHING. IT. DOES. NOT. WORK. OUT. IN. THE. END. I had to roll my own.

What Worked Well

  • For a side project, weekends and evengings and a lost short vacation or two, < 10 months dev time is pretty good.
  • No devs with differing opinions. "Go fuck yourself," means just that.
  • Can't blame the designer or art director. That's also me. Get your shit together and experiment with more filters you boring, right-brained asshole!
  • Use self-idiomatic shorthand for maximum output (assume self is maintenance dev).
  • Less need for refactoring for absolute clarity. Therefore less need for total code coverage.
  • Realization that the art project dies with me, just like the code. Man can take neither code nor art to the grave.
  • Appreciate the pain of physical labor.

[5] What I’d Do Differently

  • I’d spend more time in the POC and research phase. Picking a technology is crucial for a solo developer since you can’t divert more resources and eyeballs to solve a pinch point. It's hard to resist jumping in.
  • It can be hard not having a team with whom to bounce off ideas. My closest friends and lover, while brilliant, cannot be assaulted with a constant barrage of life-shattering or idiotic ideas. That's what work is for. Friends can't (and should not) maintain a professional composure with you (all of the time). If you held this same corporate distance between you and your loved ones, you'd have no friends. This is my passive aggressive apology to any devs I may have made cry, any coworkers I may have had awkward conversations with due to body odor or my lover I may have made curse my name because I'm an idiot.
  • I would have taken better notes to have a better post-mortem. Maybe make an app that saves my phone-text todo notes in git form (invisibly) for future playback in a CLI to video renderer. For now I merely have screenshots of the recent few iterations.
  • Be more grateful to those around me who call me on my shit, make me have fun and make me laugh.
  • ENOUGH...