Here at Demiurge, we can move around a lot from project to project. That’s not always the case, but if you like variety, there’s plenty of it here to go around. For a while I had been on some of our newer projects, but recently I moved back onto Marvel Puzzle Quest for a short stint. Seeing our 3 year old codebase for the first time in over a year made me realize how far our tech has come since then.
Back in the day, Demiurge did a lot of contract work. This meant jumping in and out of large, unfamiliar codebases and being both efficient and effective. The opportunity to work with a lot of different tech gave us a good sense of what can go wrong and what can go right. These insights went into the work that Demiurge did when making our first in-house game, Shoot Many Robots. The end product of that work included our in-house engine, Seoul Engine.
At that point in time, Seoul Engine was mostly C++, with Scaleform using ActionScript 2 for the UI layer and some C# tools. It was set up for a 3D side-scroller and came together as we developed Shoot Many Robots. Mostly, we added only what was needed, so it ended up missing some “nice to have” features, but it let us get by.
The next time Seoul came into the spotlight was when we started working on Marvel Puzzle Quest. We modified Seoul Engine to make our 3D engine into a 2D engine and ported it to iOS and Android. We also added a RESTful server backend. We swapped out Scaleform for Iggy as our Flash VM, letting us use ActionScript 3 instead of ActionScript 2, and Flash Professional became our only editor. Now that our game would be almost 100% UI content, we wanted to make sure that we could make that content quickly.
Finally revisiting those “nice to have” features from Shoot Many Robots, we added the ability to hotload the UI .swf files while the game was running. This tech also applied to our data and configuration files. This let artists change the way a button looked and then immediately see the effect in-game after publishing the Flash Professional .fla file. We could also change any ActionScript code and update the behavior of the UI screen without closing the game. Since all of our game was data and UI heavy, this was a significant portion of the code we were changing on a daily basis. This was great considering how long it can take for the debug version of our game to start up.
However, along with the good came some bad. The hotloading wasn’t magic. We needed to author the screens in such a way so that when they were hotloaded, they would return to a reasonable state. We also had to manually deal with dependencies. If a UI screen, such as the dialog screen, relied on some data, such as dialog text, it would be great if the screen reloaded when you hotloaded the text. This was possible with our tech on MPQ (the dialog screen example isn't theorectical), but it required that we add those hooks manually each time there was a dependency.
Since this was new tech and we were working on a live game with a schedule, that didn’t always end up happening. For example, a popup might receive an event which tells it what layout to use, or it might consume some game state which indicates its layout. Either way, if that event or state isn’t saved, when the popup gets hotloaded, it lost that information and would display a default layout. Often this meant closing and reloading the popup manually to restore the desired state. Not quite as bad as having to restart the game, but not ideal either when getting the popup to open again might not be trivial. We were also tied closely to Flash Professional and this meant we had to publish .fla files every time we made any ActionScript code changes.
Since Marvel Puzzle Quest, we’ve taken our ability to hotload assets even further. On Puzzle and Glory, we replaced Iggy with our own stripped-down Flash runtime and replaced ActionScript with a Lua VM. This led to some technical and efficiency advantages, which you can read about here, but also served as a foundation for improved hotloading and faster iteration. Writing UI code in Lua meant we no longer had to publish the Flash Professional .fla file when making logic changes. Having our own Flash runtime also meant we could integrate dependency tracking into its core, improving hotloading accuracy and speed, and eliminating (many, but not all) cases of a hotload losing UI state, requiring a manual refresh.
Recently we have taken the benefits of iteration along another dimension as well by architecting our tech such that more gameplay code happens on our servers. We can easily swap out a server with updated code and have the client reconnect without ever having to close. This applies both to developers being able to iterate on gameplay changes, but also to the players getting new content without us having to release a new build through the mobile platforms’ stores. On a recent prototype I was working on, where we are using this kind of architecture, I had my local client build running for days without closing, allowing me to make changes to gameplay, both server and client side, without a hitch.
Moving back onto our older project where our iteration tech was in its infancy really made it clear to me how much our workflow has improved now that we made the iteration loop cleaner and encompass a larger part of development. Getting those fast feedback loops is key to being effective at making a game. It makes development faster, keeps you focused on what you’re working on, and facilitates the larger iteration loops that go into game design. Our tech has (unsurprisingly) evolved to our needs over the years and faster iteration has been a primary focus of new engine features. Throughout our projects, that focus has returned its investment many times over in development efficiency and we don’t plan on stopping anytime soon.