All posts by dphrygian

Caches and Cuts

I resumed full-time development on NEON STRUCT this week, and spent most of the week building out the new level shown here (working title: Safe House).

This level introduced a few new technical requirements that I hadn’t previously dealt with. In particular, I needed to add very large lights to the world during play (the floodlights in the images below), but doing so took around 100ms to compute irradiance and rebuild the affected voxel meshes.

To solve that, I added an occlusion cache to the lighting system. When the color of a light changes but its size and shape remain constant, the previously solved occlusion can be reused when computing irradiance. During level load time, I enable the flood lights with zero brightness, effectively just precaching the occlusion. Then, when I need to actually turn the lights on during play, I just change their brightness and recompute local irradiance using the precomputed occlusion.

At the start of this week, I reviewed my schedule for the game and made a couple of cuts to stay on track for a release around February 2015.

The first cut was a level called Tunnels. I had built most of it just before my hiatus, but I was unhappy with its quality and had planned to rebuild it this week. While reviewing it, I realized that its problems weren’t in the way I had built it, but the level’s utter lack of purpose in the game. It was ostensibly a core stealth level, but its fiction required it to be only sparsely populated. The player had no particular objective except to get from point A to point B. And it was a grimy sewer level of the kind we’ve seen in hundreds of games before. In short, it failed at being a good stealth level and it wasn’t even remotely interesting. The obvious solution was to cut it and move on to Safe House (which is designed for stealth, has a real narrative purpose and interesting objectives, and is my favorite level so far).

The second cut was an Act 3 level called Train. I had not started building it yet, but I could see that it would have similar problems to Tunnels. I liked the idea of a mission set on a train, but the constraints of the space preclude a lot of core stealth mechanics. There was no real objective here either, and it didn’t advance the plot in any significant way. Cut!

What I’m left with after making these cuts is 21 levels that I feel very good about (split between 11 stealth missions and 10 “social” levels), and room in the schedule for working on things that aren’t levels, like more enemies and gadgets.

Name of Post

After a brief hiatus to work on a not-so-secret Eldritch update, I will resume development on NEON STRUCT next week. My short term goal is a small friends and family playtest around August 1, hopefully validating that I have fixed the shortcomings of the Vertical Slice build.

Between the hiatus, recent travel to help promote Super Win the Game, some level design work that I’ll have to redo for this playtest, and unproductive days before my Twitter ban, my schedule has been shifted back by about six weeks. I’m currently looking at a content complete date around mid-January.

Timetables and Twitters

During the vertical slice milestone, I mentioned some concerns about my schedule for NEON STRUCT. It’s a bigger game than Eldritch, with around 25 handcrafted levels that each require bespoke scripting and writing. The schedule is tightly constrained by my budget, unless I choose to do some sort of crowdfunding or early access—but I’m not inclined to, for various reasons I may write about later. Dividing the number of levels by the number of weeks remaining told me that I needed to be finishing one new level almost every week. That sounded technically possible, but I worried it would not afford enough time to make the levels good.

Two things have happened recently which have restored my confidence in my schedule. First, I got ahead on a whole lot of tech tasks which I had expected would fill up the last months of development—things like the Mac and Linux projects I mentioned a couple of weeks ago. Second, I found I could significantly improve my productivity by banning myself from Twitter during work hours.

My Twitter problem started around the time I announced Eldritch last September. I had good intentions to stay on top of press requests through the site, and I set up a number of columns in TweetDeck to monitor mentions of the game and my various related accounts. After a few days, checking Twitter for new mentions of the game became an addiction. Eventually, noise about Eldritch died down and I got back to work on new projects, but the habit remained. During long compiles, after each SVN checkin, or any time I needed to switch to Firefox for any other reason, I would check Twitter. I would get stuck there and lose my focus. Over and over. Dozens of times each day.

It took me a while to identify the problem. I knew my productivity was less than it had been during development of Eldritch, but I attributed it to other immutable factors in my life. I finally noticed that I only felt physically tense and stressed about my schedule when I was procrastinating by reading Twitter. When I could actually stay focused and productive, the stress was gone. After that realization, I installed LeechBlock and banned TweetDeck during work hours. The following days were among the most productive I’ve had on NEON STRUCT yet.

So my confidence in my schedule is restored; and more importantly, my confidence in my own productivity is too.

Ironically, I’m now taking a very brief hiatus from NEON STRUCT. I will be traveling to Dallas next week to help Kyle show Super Win the Game at the Minor Key Games booth at SGC. And I’m working on a sssecret project that will be finished very soon and revealed next month.

Ducks in a Row

As previously announced, NEON STRUCT will be released early next year on Windows, Mac, and Linux. I don’t think I have specifically said so before, but the plan has always been to launch simultaneously on all three platforms. Like Eldritch, the Mac and Linux versions will be native ports, not Wine-wrapped Windows builds. Unlike Eldritch, I’m not waiting until the game is finished to start working on those versions.

The hardest parts of porting a Windows game to Mac and Linux—writing an OpenGL renderer parallel to the Direct3D one, and replacing certain low-level system calls with SDL—were already done from my work on Eldritch. I had written a few new file system utilities for NEON STRUCT that needed to be implemented with equivalent POSIX functions, but the most substantial thing left to do was simply to set up the workspaces and start compiling.

Another technical hurdle which I wanted to resolve sooner rather than later was Steamworks integration for achievements and stats tracking (and later, Steam Workshop—but probably as a post-release update). That process was mostly painless; the API is simple and fairly well documented, and the sample project provides everything needed to get started even before getting a Steam AppID.

To be clear, NEON STRUCT will not use Steamworks for DRM. As a player, I personally don’t mind Steam’s DRM. I think it is among the most painless, user-friendly implementations of DRM. But as we state in our “Plain English” EULA, Kyle and I believe there is no real value in choosing to use DRM. My intention is that, just like Eldritch, the Steam version of NEON STRUCT will work even if the user is not running Steam.

So, I didn’t get a lot of creative work done this week. But I got Steamworks-enabled builds running on every target platform, which clears up a considerable amount of uncertainty in the latter part of my schedule.

Voxel Veneers

Although it is not a “voxel game” in the contemporary sense—it has neither procedural nor deformable terrain—NEON STRUCT uses an advanced version of Eldritch‘s voxel system for quick and easy level building.

Voxels in this engine function like Minecraft‘s blocks: each one has a singular ID to define its properties, and is textured with up to three quads on it, for the top, sides, and bottom.

This system was perfectly sufficient for Eldritch‘s lo-fi, procedural worlds. But building more realistic spaces in NEON STRUCT, I kept running into a problem. In order to put different materials on each side of a wall, I had to use a two-voxel wide wall. At the 1m³ resolution of the voxel world, this requires 2m walls. It looks absurd and wastes space.

The worst case I encountered so far was trying to put an air duct (because of course this game has air ducts) between two rooms: 2m for the first wall, 1m for the duct, and 2m for the second wall. It was untenable.

Every couple of weeks, I would revisit the problem and try to find a solution. Fundamentally, I wanted to transform the world from an array of volumes into an array of faces so that they could be painted separately. For example, where a north-facing wall met an east-facing wall, each could have a separate texture, like so:

But many other systems—lighting, physics, pathfinding, and more—are dependent on the voxel array. Getting rid of that was not an option, and storing a parallel array of face data seemed wasteful and redundant.

I finally discovered a solution earlier this week. It seems obvious in retrospect, but it took me a few months to arrive at it.

The “eureka” moment was when I realized that I did not need to store a large parallel array of face data to accomplish my intention. Voxels already define their faces, and 99% of the time, I just want to leave those alone. In a few special cases, I want to override the default textures on a particular face, metaphorically applying a veneer over the voxel.

I implemented this as a sparse map of veneers, keyed off a bitwise combination of the voxel array index and an enumeration of the face normal (+/- X/Y/Z). When constructing the hull mesh around a voxel chunk, I check that map to see if there is a veneer for each face, and apply that texture instead of the default one if there is.

Now I can implement air ducts and other cases with much less wasted space:

I have also been using the veneer system to add decorative highlights which would otherwise have required an excessive number of custom voxel definitions.

Because the veneer is applied during mesh construction, there is no rendering overhead for using veneers. And because it uses a sparse array, it has a minimal impact on the file size of a level.

At the moment, surface properties (which are used to pick footstep sounds, for example) are still defined solely by the voxel instead of by veneers, but that could easily be overridden too if it becomes a problem.

Custom Missions and Mods

Just a brief update today to demonstrate the Custom Missions pipeline I’ve been working on. Users will be able to build levels (using the same tools I’m using to develop the game’s main levels), package them up along with any new content they want, and share them via Steam Workshop.

At the moment, these tools are only supported on Windows (because that’s where I do my development), and that is how I expect to ship them in early 2015. But they should be fairly straightforward to port—the editor is built into the game’s executable, and the other tools are simple command line utilities built from the game’s shared codebase—and I would aim to bring them to OS X and Linux shortly after.

(Just to avoid any confusion, the game itself will ship simultaneously on Windows, Mac OS X, and Linux; and custom missions can be downloaded and played on all three platforms. Only the tools to build missions will be limited to Windows.)

After downloading, the missions will populate this menu on the title screen. All sorts of other mods are supported too, and will be applied automatically just by putting them in a Mods folders. Incidentally, this should streamline the process of localization compared to Eldritch, as translators will be able to test their own changes immediately instead of waiting for me to create a new build.

The Road to Vertical Slice, Part 5 of 5

I’ve wrapped up my Vertical Slice milestone this week. I intended to conclude this series of posts with a postmortem of the whole month, but I haven’t yet taken time to reflect on the current state of the game or figure out exactly what I’ve learned by doing this. I suspect that my current schedule is mildly untenable and I may need to scope down, but that’s a topic for another day.

As I mentioned in the brief update last night, the game is now NEON STRUCT: Die Augen der Welt, or simply NEON STRUCT where the subtitle won’t fit. The new name evokes “cyberpunk brutalism”, fits more neatly in small logos, and is easy to say and remember.

On Tuesday, I spent fourteen hours overhauling my engine’s save/load system. Eldritch had very minimal save/load needs: a single slot managed exclusively by the game instead of the player. (For debugging, Eldritch also had a quicksave/quickload function, but it was compiled out of the shipping game.) For NEON STRUCT, I wanted a player-facing save/load system that would allow players to save anywhere and retry sections of the game.

NEON STRUCT now formally supports quicksave and quickload (as first-class inputs, rebindable on the controls screen). It has a rolling autosave which periodically checkpoints the player’s progress into a cyclical buffer of autosave slots. (Hat tip to Tom Francis for doing that in Gunpoint and making me ask why every game doesn’t do it!)

Finally, there is a fixed number of savegame slots for the player to manage. I wanted to allow an infinite number of savegames, but my UI system doesn’t support scrolling lists. Without that, there’s not a great way to render an arbitrary number of items. Separate pages of 10 savegames each? It’s a solvable problem, but not one that seemed worth the time right now. If this turns out to be a real problem in testing, I can revisit it.

Aside from the big save/load feature, this week was mostly about finishing things that had slipped through the cracks in past weeks. I added readable news terminals, tablets with keycodes to discover, static deco meshes, character configurations, diegetic music, and more. There’s a lot more of this to do to meet my self-imposed “shippable quality” criteria, but I feel I’m on the right track.

In the late hours of Friday night, I finally whipped up a collectibles system. I knew since before this sprint began that collectibles would be an important part of levels in NEON STRUCT. They provide an irresistible incentive for a player to explore a space, and they are extremely low cost to add to levels. But the feature got deprioritized again and again, because it was uncorrelated with anything else I was doing and because I wasn’t sure what kind of MacGuffin would make sense for the player to collect.

I finally chose geocaches as the collectible object. Maybe it was the lack of sleep, but I loved the irony—by signing geocaches, the player is willingly leaving a permanent record of her presence, in a game about trying to keep her presence a secret from systems which would record it without consent. I don’t know yet whether I will incorporate that into the narrative and systems, or just allow it to exist for the curiosity of those who notice the dissonance. Ramping up the enemy population in response to the player’s engagement with collectibles might create some interesting friction and feedback?

As I continue to write quest dialogue and incidental narrative, I am trying to let the tone of the game find itself, rather than prescribing it. The principal subject matter (right to privacy vs. mass surveillance) is important to me, but I do not expect or intend that the game will be a comprehensive statement about the real world version of that topic.

NEON STRUCT is an adventure story, set in an alternate history world with a deliberately 1980s sci-fi vibe. (“2015 as envisioned in 1985” was how I described it at inception.) It has something to say, but it needs to be entertaining as well. It does not need to take itself too seriously, but it does need to depict the subject matter in an internally consistent way. And because it’s a video game, it has to harmonize with the gamut of player behavior.

At the moment, I am settling into a comfortable place where the narrative—like the visuals—is a colorful, minimalist stylization of reality. Incredible things are allowed to happen because it is a work of fiction. Technology can be magic in this world. As long as the story is consistent in the way it deals with things, and as long as it does not muddy the message, I am comfortable letting it be more fantastic than realistic.

NEON STRUCT

A brief announcement before tomorrow’s conclusion of the Vertical Slice story: Die Augen der Welt is now NEON STRUCT: Die Augen der Welt.

All future posts will be made here at neonstruct.com/blog. If you were subscribed to the feed for the blog at dieaugenderwelt.com, you will need to update your subscription to this one.

The Road to Vertical Slice, Part 4 of 5

As I approach the final week of the vertical slice milestone period, I am feeling more confident about my schedule. I still have a lot of art and sound to create next week, but the third level is mostly complete and the last few systems I intended to include in this milestone have been implemented.

I took an unexpected detour into new post-processing effects while trying to establish a mood for this third level. In contrast to the soft neon glow of the previous level, this map needed a murky, grimy feel. I added a film grain effect and a simple chromatic aberration that separates the RGB channels around the edges of the screen. My first pass at the film grain was a multiplicative filter, but that caused brighter parts of the screen to show the most grain, with darker regions showing almost no change. The effect I wanted was that of high ISO (or film speed), where most of the grain is visible in the poorly lit parts of an image. I switched to a subtractive filter, which pulls out proportionally more value from darker colors than lighter ones, and it gave me exactly the look I desired.

A few weeks ago, I had disabled dynamic voxel lighting because it was getting very expensive to update. There were noticeable hitches in the framerate whenever a door was opened or shut. (This was not a concern in Eldritch, because it had fewer lights with smaller falloff radii; but Die Augen utilizes light and shadow for its core game mechanics, so it necessarily has a darker ambient term and many more shadow-casting lights.)

Last night, it occurred to me that I could make a very simple optimization to reduce the amount of voxels I needed to relight when occlusion changed. The performance improvement was incredible—in the scene shown above, the time to recompute lighting when opening the door dropped by a factor of almost 50.

Finally, I implemented a couple of less exciting but quite important systems this week. Shown above is the signage system, which displays a short string when looking at an object in the world. On BioShock, we called these “art subtitles”, and they are a simple way to localize art assets with text baked into them. For Die Augen, they are also a low cost way to label rooms and provide directions.

Shown below is the new objectives screen. It is only a player-facing model, not a formal game system—under the hood, quests are implemented in an ad hoc fashion, and their scripts notify the objectives screen to add, remove, or update objectives.

My next week will be spent decorating and polishing these levels, writing and rewriting dialogue to provide clear player direction, and adding a bit more “juice” to hacking, takedowns, and the like.

The Road to Vertical Slice, Part 3 of 5

One reason I wanted to create a vertical slice for Die Augen der Welt is to discover how long it would take me to build three levels (and their respective assets) to a shippable state. With this data, I will be able to meaningfully evaluate the scope of the game. If I can build these three levels in five weeks, then I can reasonably estimate how long it will take to build another dozen or so levels.

Currently, I’m not filled with optimism about the schedule. With two weeks remaining in this milestone period, I still have one whole level left to build, a big pile of art and sound assets to create, and a few low priority systems that may not make the cut for this milestone. On the bright side, most of the work I’m doing this month will be reusable in later levels; and systems work in particular is taking a much bigger chunk of my time this milestone than it will in the future.

The biggest new feature I added this week is a security system, comprising a network of CCTV cameras linked to central alarm boxes. Each can be hacked. Hacking a camera disables it, but does not silence the alarm if the player has already been spotted. Alarm boxes will be difficult to access, placed behind locked doors or surrounded by guards; but the reward for hacking one is commensurate to the challenge: it silences the alarm and disables all cameras on its network.

This week, I also began building out the first “social” level in Die Augen. These are small interstitial levels between the core stealth missions, where the player can recover her health, restock her inventory, and learn about the world from friendly NPCs and news terminals.

I started building the level with only a vague idea of its structure—not a best practice!—and have been figuring out a lot about the nature of social levels in real time. The worst thing these levels could be is a glorified menu screen for healing, shopping, and narrative. Instead, I’m beginning to think of them like the hub levels from any Deus Ex game: open spaces to explore, hidden nooks to discover, brief questlines to resolve.

My goal is that these social levels complement the stealth levels on several axes. Stealth missions are tense, social areas are relaxing. Stealth gameplay is predictable and consistent, social gameplay is unexpected and unique. Stealth systems offer freedom of player choice in a smaller domain, social systems offer prescriptive choices in a larger domain. Stealth levels are constructed pop songs, social levels are improvisational jams.