Writing a Video Game Using SceneKit in a Month
On September 18th, 2015 I received a small box from Apple. What followed was a 7 week barrage of coding, re-coding, re-working and entirely re-thinking what I wanted my first game on the Apple TV to be.
At the outset I knew that I wanted to write the game using SceneKit. The SceneKit API isn’t so much a “game engine” as it is a collection of individual tools to build a game. Instead of having a dedicated IDE to work in to place items and attach behaviors you have to write all of those things yourself. In most cases you would be able to get a working prototype off the ground in something like Unreal Engine in just a couple of hours. For this project though, I wanted to both see what Apples API could do, and I wanted to reinforce my recent learning of many of the other APIs that Apple provides by writing a “native” game.
Xcode does provide a few tools that allow you to preview your models and reorganize the hierarchy of items inside of a scene file but they are nowhere near as feature-full as something like Unreal Engine or Unity.
On Discovering You’re Full-of-it
The entire process of building my first game in SceneKit for the Apple TV has been a study in naïveté. Because I knew that I was going to be doing the project (at least almost entirely solo, shout-out to my testers!) I started making notes in one of my many sticker-covered notebooks for a simple jump and smash style action game. Something that would evoke Zelda, top-down adventure with shield and sword. These games are great because you can build relatively simple systems independently and then let gameplay emerge from a more “open-world.” This means that the player brings a lot of the value to the game itself and I knew I was going to need all the help I could get.
Once I started working with the character animation tools in MODO using simple trees as a starting point and importing them into my Xcode project it was clear that trouble was a-brewin. Nothing worked the way it’s supposed to. Skeletons weren’t bound to the right mesh items, animations and mesh locators all had incredibly weird, arcane looking names. I’d never spent any time with the Collada file format and this added a third layer of stupidity to every single thing I tried.
Because the animations in the files weren’t working the way that I thought they should I started writing scripts to automate changes in the XML code that the files are made of. I spent so much time on this that after a week I realized that I’d barely gotten my game any further along than just opening the Apple TV box and plugging it in. I had to make a decision: Either I continue beating my head against the rock of character animation before I could even start making a game that I want to ship in thirty days, or just change course completely.
I surveyed what I’d gotten done so far then promptly archived the repo and started over from scratch.
Look to the Past to Find the Future
I went back to my notebooks for a while until I found some stuff I’d written back in 2009 for a game I was helping out on called “Elementus.” That game was a match-3 style puzzler written in C#/Unity. I mostly did the art until we got into crunch to try and ship it for a competition and we ended up making a ton of compromises that I’m not sure any of us were ever really happy with. The core concept is not anything new, you have a (shooter|puck|cannon) on a circular track that fires spheres into a center peg attempting to make matches to clear pieces from the board. In Elementus you would clear a stage when the board had no pieces left. Pretty simple.
Making games and products in general is so much about compromise it almost hurts to think about it. Because I wanted to ship something quickly to get it into the store within the first week of public availability of the new Apple TV I decided that there wouldn’t be time for designing levels like we did with Elementus. In fact I think that one of the big reasons why that project didn’t really do as well as it should have was because we spent far too much time “designing” things. In my new game I would take the approach that the player is the “villain” and the game would get exactly as complex as they wanted it to by increasing their score. The longer you play, the harder it gets, simple.
And Away We Go
I set to work writing some basic routines to get me access to a frame counter from the rendering delegate in SceneKit. Using a “tick” structure like this is pretty common in games and the majority of your game logic resides inside of a single function. There are always opportunities to move things out of the main game loop to events, which dramatically improves performance, but at the early stages I wasn’t worried about that at all. My first take at the game concept consisted of a series of concentric rings circling a center peg by multiplying a base number of “sockets” times the index of the “ring” away from the center of the board.
This early prototype also contained a shot mechanism that used kinematic animation to drive everything. Every piece on the board had its position calculated “by-hand” every single frame. At the start I had three colors of spheres, Red, Green and Blue. In the space of that first weekend, I was able to load my game onto the TV and shoot new spheres into the center of the board and I even had a rudimentary “matching algorithm” built that was absolutely terrible. For reasons that would seem obvious to anyone with a math degree calculating the neighbors of a point on a circle against another circle with a semi-arbitrary number of points on it is incredibly unstable. Some points in the structure would line up perfectly while others were just wildly out of whack. Even the distances required a margin of error that made things feel sloppy.
In addition to configuring the number of items in each ring, I built some transitional stuff that would allow me to change the number of spheres on the board dynamically. This made for some really cool effects, but gameplay suffered every time I changed the values. Additionally, performance was already in the drink because I was doing too much work in the main game loop.
While iterating through the number of dots that I wanted on each ring I kept coming back to having 6 items in the first ring. This yielded the highest success rates in my neighbor matching code and something about it just felt-right. It would be another week of trying to make concentric circles work before I realized my mistake; I should have just based the whole thing off of a hexagonal grid to begin with. Still, going back to the benefit of making snap decisions that cause you to throw away a ton of code, I persevered.
Throwing the Dynamo
On the 21st of October I threw away nearly 70% of the code I’d written and started writing a basic Hex Grid layout in Processing. I had risen to the level of my own incompetence (thank you Miles Denholm.)
If you haven’t ever tried Processing but you’ve always been curious about writing code I can’t recommend it enough. There’s even a great book by Daniel Shiffman “The Nature of Code” that has examples you can transcribe to do some amazing stuff. I love to write code in Processing before I move to the target language because things are really simplified in the Java-like language and you can be up and running in sixty seconds displaying pixels on the screen. This has huge advantages over the treatment of different Windowing systems, Event handling API and whatnot.
I was headed to Dallas for a conference over those couple of days so it seemed like a great time to pack in a little extra “research and development.” I wrote the initial Hex grid code on the plane and had very little time on the ground until Thursday night when I got shooting working again. Friday was a total shut-out with the big conference ending party but I was able to make a simple neighbor-finding algorithm and made matching work over breakfast in the hotel Saturday morning before my flight. At the airport I caught up with one of my co-workers and his first reaction to the game I was making was “wow!”; I knew I had something.
The amount of effort until that point in the project seemed like a pretty big deal. I was basically pulling two full working days per day to get the game into a testable state so it was with great excitement that I was able to send a beta test out to my close friends Sunday evening.
Wrapping it Up
I’ve been doing software development for a really long time and yet it always seems to surprise me that just when you think you’re finished, there’s another mountain of work yet to be done. The next two weeks were filled with a flurry of bug reports and suggestions from players using an iOS build of the game that easily doubled the value of the product I was making.
I met my primary goal of submitting the game to Apple for review on the 4th of November. Over the following week I dealt with the usual issues of either the reviewers or myself misinterpreting the rules for approval for both the menu button as well as the play buttons. I added support for different screen sizes on iOS that I hadn’t considered viable devices and I spent some time working on a trailer (which you can see at the front of this post.)
Creating a game in a short amount of time is a fantastic project to undertake. You’re forced to learn new technology in a compressed period of time and that causes you to focus on just the most valuable parts. In addition to what I’ve learned about SceneKit I also feel like I hit a new point in the mastery curve of decision making. Things that weren’t vital to gameplay got left on the floor to make room for revision of the pieces that make the game more fun.
I hope that the game does well in both app stores and I’m working on a Mac OS X port of it now that shouldn’t take too long. If I had this project to do over again, I would have started with OS X as the principle platform and then worked on porting to devices once I felt I had enough “game” in my game. This way integration testing would have been inconsequential as it would be just a local build. Working with the different iOS devices isn’t really a complicated affair but it does require a lot of cable switching. Elyxir is a simple game but it looks good and it is a lot of fun to play. Why not grab a copy for your Apple TV or iPhone and share your high scores on Game Center?