Category Archives: Devlogs

A Tendency to Dream

Last week’s mystery Polaroids are courtesy of a week David and I spent on the road visiting Lincoln and Omaha, Nebraska. It’s been ten years since we graduated from UNL, and it felt like a good time to see how the cities have changed, visit some old haunts, and mostly be glad that I don’t have to worry about classes and grades anymore.

I’m continuing to make progress on Super Win speedrun courses. Three of the five courses have been fully grayboxed and need to be tweaked and arted up. One is in the process of being grayboxed, and the last one I haven’t started building at all yet.

oldarcadia

The first course is Old Arcadia. This course requires some long jumps and wall climbing that are only possible with the new coffee cup powerup, which grants a temporary speed boost.

bonehoard

The next course is the Bonehoard. If you’ve finished the campaign, you’ll recognize this tileset from one of the last areas of the game. There are a couple of branching paths throughout this course; the trick will be figuring out which one is the fastest.

dreamcycle

The Dreamscape Nightmare course winds back and forth around a central tower. You’ll have to climb to the pinnacle to find the gear you need to plummet back down to the bottom and reach your goal.

schadenfreude

The Caverns of Legacy will be familiar to fans of the original You Have to Win the Game. This course contains reworked versions of some iconic rooms from that game. This has been an interesting challenge on account of the difference in scale between the two games. I rely almost entirely on 16×16 tiles in Super Win, and coupled with the narrower dimensions (256 pixels across vs 320 in You Have to Win), I’m having to simplify the geometry of these rooms and try to evoke the originals rather than rebuild them 1:1.

Finally, there’s the King’s Gallery, which isn’t pictured here because I have yet to start building it. My idea is to play around with the concept of traversing the outside of a space that was previously encountered, a sort of deliberate breaking out of the world. It’s an idea I’ve had at the back of my mind since the first YHtWtG, but I’ve never really explored it. Hopefully it’ll turn out how I’m imagining.

swtg_flyer_1 swtg_flyer_2

Hey, remember these flyers I did for Super Win that were designed to look like an original NES “black box” release? I’m working on something similar for Gunmetal Arcadia, this time in the vein of ’90s video game ads — white backdrop, serif font, etc. This is obviously still a pretty early mockup, but it’s a good example of the sort of thing I’m going for.

new_flyer_lo_con_for_blog

Reusing the same MIDI-to-proprietary-synth tech in Gunmetal Arcadia as I did in Super Win the Game has put me in a good place to be able to write music off and on for the entire duration of the project rather than having to worry about composing a whole soundtrack all at once close to launch. I’ve already written easily 50% more music for this game than I did for Super Win, and I plan to keep on writing as long as the melodies keep coming to me. Here are a couple of the more recent tunes I’ve written.

I guess this next bit might not be super interesting to non-devs, but since I like to talk about some of the aspects of development that sometimes go unnoticed, here’s a fun thing that happened. While I was out of town, a thunderstorm took out my modem/router. For some reason, this was the one device that wasn’t behind a surge protector, so I guess that’s what I get. To their credit, my ISP replaced it immediately, no questions asked, although I also had to put a new ethernet card in my PC because apparently the surge also blew out the ethernet port on my motherboard.

Anyway, the point is, along with a new modem and router came a new IP address. That’s nothing new; when I was living at my previous apartment and using a different ISP, my IP address would change at least once a year for no reason at all. It’s always been a minor irritant, though, because it means I need to update the URLs on all my local SVN working copies. (As I’ve discussed before, I keep each project in a separate repository, so I’ve ended up with quite a few working copies checked out.) Historically, I’ve always just dealt with this by relocating each working copy whenever I touch it next, but this time, I finally decided to simplify the process. I wrote a script to output the URL of each working copy in a given directory, and if its address differs from a provided target IP, it will automatically be relocated to the new one.

Grab Bag 27

This week marks another special guest appearance from Super Win the Game. I know, I know, I want to go back to writing about Gunmetal Arcadia, but I’m full time on Super Win for now, so that’s what I’m covering. But hey, at least there’s a shiny new header image! I got the random urge to paint a scene from Gunmetal over the weekend, and that’s what I came up with.

valk_leaderboards

Last week, I mentioned that I had prototyped attachment of player ghost data to leaderboard entries. This week, I wrapped up that work and implemented a leaderboard UI. Your fastest time will be recorded for each speedrun course. When playing offline or in non-Steam builds, you can view your own personal best times and race against your own ghost. When connected to Steam, you can view all players’ time and race against any other player’s ghost. All the usual  Steam leaderboard modes (global rankings, personal ranking, and friends’ rankings) are supported.

valk_speedrun_courses

I’m making slow but steady progress on the courses. Level design was one of the most tedious parts of making Super Win the first time around, and I’m definitely starting to feel that slog again, but I’m excited about the new challenges I’ve built. I sort of expected to feel like I had already done everything I could do with the content available, but I’m finding some interesting new ways to piece things together.

I’m continuing to support the anaglyph 3D mode going forward, so I fixed up the minimap to play nice with this feature. Depending on whether I foresee doing any more major updates for Super Win in the future, it may be worth refactoring this feature to clean up a lot of copy/paste code that exists across the codebase.

valk_anaglyph_map

Last month, I updated Super Win to include a language option in the menu. The game only supports English by default, but additional languages can be added by players, and a Russian translation is currently available in the link above. I realized shortly after publishing this update that some strings which had already been retrieved in one language were not updating immediately after changing the language. In most cases, continuing to play as normal would fix the problem, and at worst, exiting and restarting the game would always fix it, but I wanted a real solution and not a workaround. To that end, I’ve written a language-sensitive interface that classes may implement if they need to respond to the game language being changed. So far, I’m only using this in one place, for updating key prompts that had already been cached, but in the event that more of these bugs pop up, I’ll have a better way of handling them in the future.

As I’ve been writing music for Gunmetal Arcadia, I’ve rejected a few pieces for sounding too much like they belong in Super Win. I want Gunmetal to have its own unique sound, and even though I’m reusing the same synthesizer tools I wrote last year, I’m trying to lean more on minor key melodies and weird, chaotic compositions. Not everything I’ve written has fit that bill, and a few tunes have been cut. But as I was thinking about new content I could add to this Super Win update, a couple of these felt like they’d be a perfect fit.

This short loop plays inside the Hall of Speedruns, located in the Town of Lakewood. This is where you can access the speedrun courses and view the leaderboards.

This is probably going to be the background music for the “Old Arcadia” course, or possibly one other that I haven’t started building yet. Or both. We’ll see. It’ll go somewhere.

valk_volver_3

This Wednesday marks the third birthday of the original You Have to Win the Game and one year since it landed on Steam. I poked around in the source code a day or two ago to remind myself what state it was in. Last June, as part of the neverending struggle to support a wider set of Linux installs, I attempted to merge in some then-recent engine changes and build a 32-bit executable. It failed, I rolled back the version on Steam, and ever since then, the code in my repository has been out of sync with any published version and not really in a good place to rebuild the game if I had to. So I finally took the opportunity to roll back some of the more problematic changes and at least get back to a state where I can build the game as it appears on Steam today. I don’t know whether that will go anywhere. A few months ago, I considered adding a Super Win upsell screen when starting or exiting the game, in essence to frame it as sort of a demo for Super Win, and I suppose this puts me in a better place to do that, but I’m still on the fence there. On the one hand, it’s kind of tacky. On the other hand, YHtWtG is about two orders of magnitude more successful than Super Win but doesn’t generate any revenue, so it feels like a wasted opportunity.

I’ll be out of town next week as David and I are taking a trip to Nebraska to gather ideas for a future title and visit our college on the ten-year anniversary of our graduation, but I’ll be sure to have something ready by next Monday, even if it’s just Polaroids from the road.

Maps and Ghosts

It’s been another week with a minimum of work on Gunmetal Arcadia, so today I’ll be covering the ongoing updates to Super Win the Game in greater depth.

xan_valk_update_1

For starters, I’ve added a highly-requested mapping feature to Super Win the Game. As in most Metroidvania titles, the map is automatically filled in by traversing the environment. Regions containing gems that have not yet been collected will be flagged on the map with a red dot. A minimap sits in the corner at all times and can be expanded to full size with the press of a button.

Initially, my hope was that I could automatically generate the map images from game data. I even got as far as prototyping an algorithm that would do a flood fill through the world looking for adjacent rooms and drawing the map as it went. Unfortunately, this was insufficient for a number of reasons. It was too slow to accurately determine rooms that the player could walk between; to do this, I would have needed to do a flood fill of each tile in every room, marking space as inside or outside the walls, in order to correctly identify paths between rooms. Furthermore, it would have been impossible for this algorithm to flag rooms as secret areas, as this decision is often based on context and not something that could be easily determined by examining a room algorithmically.

For these reasons, I’ve had to draw each map by hand. In fact, there are two versions of each map, one with secret areas revealed and one without. Once the player has traversed a secret area, the map will show this path, but until then, it may appear as a wall.

I was initially considering only showing the map within dungeons, but I’ve had to expand the scope for a variety of reasons. This decision was based on the fact that many areas of the game (towns, building interiors, various caves and forests accessible from the overworld map) are trivially small and don’t warrant a map, but as I began drawing maps, I realized some areas that I don’t technically consider dungeons — for instance, the icy lake outside the glacial palace, or the exterior facade of the desert ruins — could still benefit from having a map. The final nail in the coffin was the inclusion of gem markings on the map; once I knew for sure I would be supporting that feature, it pretty much meant I would need a map everywhere. The one exception is the dream sequences. These never contain gems, so I feel I can get away with not having a map during these sequences, and I think the exclusion of a map may help to further clarify the delineation between the real world and dreams.

One of the reasons I rejected a minimap when I was originally developing Super Win last year was because the game’s regions are not always logically represented by its map files. Many seemingly disparate locations may exist within the same map file, such as the tutorial, all dream sequences, and the hidden region within Subcon, or the interiors of many buildings across a few different towns. Likewise, some areas that are logically connected, such as the Lair of the Hollow King and the Hollow Heart at its conclusion, actually exist in separate map files. I knew that one of my first tasks would be solving this disparity. This involved tagging every map file or region with an identifying name.

xan_valk_update_2

Ultimately, I ended up breaking down maps into the smallest possible discrete regions, even when these are just a single room, as in the case of many building interiors. This decision led to another problem: once I began marking gems on the map, I found that I wanted to be able to see the total number of gems in a region, but the regions I had defined were too small to provide a meaningful count. To address this, I added another layer of markup to define regions that were part of the same larger logical space. In this way, I could keep track of, e.g., how many gems existed in a town, even when this space spanned multiple maps.

Calculating the number of gems within each region is done at runtime when the game starts up. This is a somewhat intensive process, as the contents of each room must be examined to see whether it contains any gems, whether those gems have been collected, and so on. In the future, once I’ve finished building the new speedrun courses and am certain that content is locked down, I may cache these results for faster loading, but in the event that I don’t, I’ve added a loading screen such that the game doesn’t appear to have crashed or frozen.

There is one remaining problem that I haven’t solved yet, and that is how to handle saved games that were made prior to this update. As it stands, the game would be loaded with no minimap data, so any rooms the player had already traversed would have to be revisited in order to fill in the map. As a partial fix-up, it would be easy to automatically fill in rooms from which the player had previously collected a gem, as I would know for sure they had been there already. Any further fix-ups would have to be guessed at, possibly by attempting to pathfind through the world from known visited rooms to known entry points. Alternatively, I might simply pop up a notification when loading an older saved game explaining that the minimap will not be filled in. We’ll see.


The second order of business is speedrun courses. This goes back to an idea I had early in the development of Super Win, but eventually the underworld region I had set aside for this purpose ended up becoming something of an epilogue to the main campaign instead, and I shelved the speedrun idea for a time.

I’m planning to have a number of speedrun courses, probably five or so, and these will be accessible from the Town of Lakewood right at the start of the game. Each speedrun course will prescribe its own set of gear, so the playing field will be level regardless of how far you’ve advanced in the campaign. You may also find familiar powerups on the course that will last for the duration of the run and will be forfeited upon its completion. Finally, I’ve added one new powerup: a coffee cup which provides a speed boost for a short duration.

I’m currently in the processing of grayboxing speedrun courses, and I’m pretty excited about the results so far. I’m aiming for difficult platformer challenges more in the vein of the original You Have to Win the Game. I also want to provide multiple paths through each course. My hope is that these paths will provide a good balance between difficulty and speed and incentivize repeated playthroughs in the interest of finding and perfecting the optimal path.

From the start, I knew that if I were implementing a speedrun feature, I would want ghosts, but it took some time to figure out a good implementation. I had previously implemented input recording for Gunmetal Arcadia as a solution for an attract mode and possibly for saving and replaying full game sessions. I ported this code back to Super Win, but it turned out not to be useful for ghosts, as wholesale input recording is only useful in the absence of ongoing player input. Eventually, I decided to implement this feature in the simplest way I could imagine, by saving off snapshots of the player’s position at regular intervals. I’m still playing around with the exact rate, but currently I take a snapshot every tenth of a second while the player is moving and also in response to significant events such as jumping, landing, wall hugging, dying, and respawning.

Ghost data is saved to file when the player finishes a speedrun course and chooses to overwrite their previous best time. This ghost data will automatically be replayed the next time the player enters that course, allowing the player to compare their current performance against their previous best.

The next step, and one that I’ve prototyped far enough to have confidence in being able to ship it, is to associate ghost data with online leaderboard scores such that players can choose to race against each other’s best results. Naturally, this feature will only be available for Steam players, but for non-Steam versions, local results can still be saved and replayed.


I don’t yet have a release date for this new content, but as I’ve mentioned previously, it will be available free of charge to all current players and will coincide with a relaunch of the game at a new lower price. Hopefully this will be sooner rather than later; I’m a little over three weeks into this work and itching to get back to Gunmetal Arcadia, but I also want to make sure this is a substantial piece of high-quality content, so I’m trying not to take any shortcuts or do anything halfway.

Meet Your Factions

One of the core promises of Gunmetal Arcadia since its announcement has been the idea of faction conflict. There are two major players in the realm of Arcadia, each with its own set of characteristics and values. As you play the game, the choices you make will affect your standing with each of these factions, and over the course of multiple sessions, the concatenation of previous outcomes will sway the narrative in different directions.

Let’s take a look at these groups and what each represents. But first, an introduction to the race you’ll be playing in Gunmetal Arcadia!

xan_faction_elves

Tech elves are the native inhabitants of the land of Arcadia. They have an innate affinity for tools, technology, and weapons, and they also possess the ability to outfit themselves with biological augmentations.

Elves may choose to assist one of Arcadia’s factions, or they may remain unaligned. Each of these options comes with its own risks and rewards; factions can provide equipment and upgrades for their followers, but some citizens may respond negatively to members of an opposing faction or those who do not commit to any cause at all.

In the face of a greater threat, however, there is no open war between these factions. Whatever conflicts or tensions exist in that space must take a  back seat to the duty of defending the land.

xan_faction_vanguard

First up, we have the Gunmetal Vanguard.

The Vanguard stands for strength and honor. These brutish warriors value military might above all else. They pride themselves on crafting the finest weapons and armor in all the land.

Members of the Vanguard are well-versed in melee combat and prefer to approach combat situations directly, sword in hand.

As an unaligned tech elf, you may pledge your allegiance to the Vanguard and receive their sigil, the Vanguard’s Hammer. This item imbues its holder with great strength and constitution.

xan_faction_seekers

On the other side of the coin, we have the Seekers of Arcadia.

The Seekers represent knowledge and intellect. They are scientists and engineers, keenly interested in understanding, manipulating, and augmenting the inner workings of all things.

Acolytes of the Seekers prefer to analyze combat encounters and choose the smartest approach from all available options.

A neutral tech elf who choses to be allied with the Seekers will be granted their sigil, the Lens of the Seekers. This item amplifies the abilities and stats of its wearer.


In the future, I hope to do more of these short lore posts — this week, my return to Super Win necessitated it, but it also aligned with some writing and narrative development I’ve been doing as I start planning promotional material for future events. Maybe next time I’ll take a look at the rogues gallery of the Unmade Empire, the primary antagonists of  Gunmetal Arcadia.

The Lucas Factor

Between the new game modes, Mac and Linux ports, and updated Steam release I did for You Have to Win the Game and the free DLC David did for Eldritch,  a common trait that’s emerged across Minor Key’s releases to date is substantial post-launch support. When I finished Super Win the Game, I had no intention of adding any new content; the game said what I wanted it to say, and that was that. Nevertheless, opportunities have arisen in the months since launch to bring me back to that game, from the anaglyph 3D mode for the IndieBox release to recent changes to better support fan translations. I haven’t been documenting that work on this blog because it’s not directly related to Gunmetal Arcadia and I wanted to stay on message.

This week, though, I’ve found myself with nothing to write about because I haven’t done any work on Gunmetal Arcadia. I’ve been focused on some new stuff for Super Win, and as that has impacted the development of Gunmetal Arcadia, I want to  discuss it. I don’t know what form this blog will take next week, or whether I’ll have returned to Gunmetal by that time, but I have another few days to figure that out.

I’m planning to showcase Super Win the Game at regional events this summer just like I did last year. This time, though, since the game is already complete and released, I’m in a place where I can be more flexible in how I choose to demo it. Last year, the demo was essentially just the current build of the game with saving and loading disabled. It would always start from the beginning, optionally with a tutorial, but without a clear indication of what the game would become, either in terms of mobility upgrades and platforming challenges or in terms of narrative.

In discussing ideas for a new demo with David, I first considered launching the demo build in a state where the player already has a few upgrades and starts at the entrance to one of the dungeons, as this would be a better representation of the gameplay experience. Then I thought about building a new demo level, possibly cobbled together from scenes from the actual game, that would be a small, finite space that could more immediately convey the experience of the full game.

A few days later, I woke up in the middle of the night and had the idea to promote Super Win at shows by turning this demo level into a competition. Beat the best time and win a free Steam key! And then that quickly turned into, hey, as long as I’m tracking the time that the player spends in a level, why not turn that into a real game feature? And that led me to write up a design document for a new speedrun mode, and for the first time in six months, I was excited about Super Win the Game again.

I prototyped the skeleton of a speedrun mode in a day, with options to choose from a number of courses, each of which may prescribe a number of upgrade abilities that may be granted or removed for the duration of the course. In this way, I can build levels with specific abilities in mind and not have to worry about when the player might visit an area or which upgrades they might or might not have and whether they could get stuck. This opens the door to a purer experience, less diluted by adventure/RPG trappings and more directly focused on the fast-paced platforming challenges that have been the core of the Win the Game titles.

So I guess that’s the official announcement. A new speedrun mode is coming to Super Win the Game! I don’t know when this content will be ready for release, but I’ll be figuring out that messaging in the near future. I’m obviously motivated to get back to working on Gunmetal as soon as possible, but I also want this content to be substantial enough that it’s not just a blip on the radar. It’s easy to imagine this would be a “major update” in Steam terms, and it could be timed alongside a sale, but I’ve already seen how Super Win performs on sale, and it’s not amazing. It’s enough to get by, maybe, but that’s it. (Thanks to the magical intersection of statistics and public-facing APIs, you can see how well it’s doing on SteamSpy.) So then I started thinking, how could I make this a bigger deal? And one of the things that came to mind would be to go back, address some of the most frequent complaints with the game, make it the best, most polished version I can, add some new content for everyone who’s played the game already, and then relaunch it at a new low price.

So, that’s an interesting thing. I feel like I’m well outside the window of a price drop looking like an upfront pricing failure, but of course I’ve talked in the past about how I think the original launch price probably was misguided. And no matter how many reviews and reviewers agree that Super Win is worth its asking price — and most have — I just can’t seem to shake the disconnect with the public perception that a pixel art platformer is an easy thing to make and should be cheap, if not free, by necessity. Hopefully this new price, whatever it may be, will better align with consumer expectations. But that’s only half the story. Lowering the price also makes sense in the context of Gunmetal Arcadia. After seeing how Super Win performs (and also observing numbers of other genre-similar titles on Steam Spy and getting a feel for where the ceilings lie), I’ve been feeling like Gunmetal needs to debut at a lower price than Super Win initially did if it’s going to be any sort of a success. But that’s a difficult and confusing thing to do in light of the fact that Gunmetal will be a larger game than Super Win in terms of scope and ambition, and pricing it lower risks creating the perception of less value, of this one being a step down from the last. My hope is that by preemptively dropping the price on Super Win, I can then launch Gunmetal at an appropriate price: higher than where Super Win is now because it is a bigger, better game, but lower than where Super Win originally was because I’m starting to think that’s just too much to ask in 2015 for what I do.

I don’t have a timeline or a specific list of features for this relaunch. I’m going to run with this idea for as long as it’s exciting and try to make it the best thing I can. I can say for sure that by popular demand, I’m adding a minimap. It’s already done. I finished it on Saturday. More may be coming depending on how I feel. But there are a few things this won’t be, and I want to establish that as early as possible. I’m not doing a hardcore mode. I’m not doing a cat mode. I’m not doing a remixed campaign. Those ideas worked in You Have to Win the Game, but they aren’t things that I consider to be core to the series, and I’m more interested in finding things that work for this game rather than retreading the same ground.

Likewise, there’s always the fear of running into “the Lucas factor” and wanting to fix up every little rough edge while I have my hands back in that codebase. I’ve made a few tweaks to the CRT sim between Super Win and Gunmetal, and it’s easy to imagine that I might want to port those changes back to Super Win. But the danger is, if I’m constantly sharing every relevant change among all associated games, then it will take me longer to finish new games, the new games won’t be as fresh and exciting as they could be, and it will be harder to pin down a definitive version of each game. It’s probably better to save the new stuff for the new game and allow each shipped title to remain representative of what I wanted to make at the time it was made. It feels a little silly to talk about my games in these terms when, for instance, I’m only a few months out from releasing Super Win, but at the same time, it really hammers home just how much progress I’ve made on Gunmetal in that time, that Super Win feels like such a distant memory.

To ramble a little bit longer, I was certain in early 2012 when I was closing in on the finish line of You Have to Win the Game that it would be the last indie game I ever made. Once I finished that one, I thought, I would be done, I would have made that one game that I’d be known for, and I wouldn’t have to kill myself crunching all the time like I’d been doing. And to be fair, nearly three years later, it’s easy to think that You Have to Win the Game will in fact be the game I’m known for, if I’m known for one at all. And that’s cool. I still think it’s a great game. I think it’s a more concise, more focused experience than its sequel was, and I think it hit a sweet spot where it was substantial enough that its low, low price of free felt generous and attractive.

I didn’t think I could ever feel good about Super Win the Game after its launch. I was burned out on working on it, talking about it, and trying unsuccessfully to promote it. It was anathema for a long time. It’s hard to say what changed, but I’m happy to be over that. It took half a year, but I’m finally proud of Super Win again and excited to be revisiting and updating it.

Player Awareness

Today’s update is going to be super short because I spent the majority of the week doing some post-launch work on Super Win the Game. But I’m making up for it with a ton of GIFs, so.

This week, I continued working on new enemy designs which have brought with them a handful of new AI features.

GunArc 2015-04-06 02-29-32-590

First up is some sort of bug thing. It spits acid? I’m still trying to figure out what the common theme among the enemies is going to be. I’m thinking some sort of insectoid alien species, but we’ll see.

GunArc 2015-04-06 02-38-19-943

Turrets also spit acid, at least for now. They will also turn to face the player, which is the first bit of player-aware AI code I’ve written. My expectation is that enemies will largely be able to function autonomously with no need to be aware of where the player is or what they’re doing, but there will be a few exceptions, and this is one of them.

GunArc 2015-04-06 02-38-43-284

Likewise, I’ve added player proximity tests to allow these hanging slime spawners to trigger when the player walks underneath them. I also used this functionality to create a spider enemy that behaves similarly, waiting until the player passes by to drop and attack. This required an extra bit of AI work to support a change in state from hanging motionless to dropping and moving around. To solve this, I add the ability to nest behavior sets within other behavior sets, effectively producing something akin to a standard behavior tree.

GunArc 2015-04-06 02-50-34-269

Finally, I’ve been reacting to feedback from the first playable test build. I’ve reduced the intensity of falling gravity, tweaked movement inertia a bit, removed player knockback when striking enemies with a melee weapon, and made bombs way less bouncy. I don’t yet know when the next public test build will be ready, but hopefully these changes will be a step in the right direction.

Insight

Welp, it’s been fun, but Bloodborne came out this week, which means Gunmetal Arcadia is paused indefinitely. (Not really but yeah but not really but yeah.)

For Super Win the Game, I created a dialog tree system for NPCs, signs, and various other pop-up dialog boxes. This system could display text and present the player with options which would branch the tree. It could also query the game state and branch depending on the results. Some of the more complex uses of this system were the jeweller and fortune teller NPCs, whose responses would change depending on how many gems the player were carrying, which items they had collected, and so on.

I’m reusing this system in Gunmetal Arcadia and updating it to hopefully increase its functionality while reducing some of the wordiness. In Super Win, each tree was authored once in the editor and never changed at runtime. For a known set of content, it was reasonable to make a query for the presence of each and every powerup in the game, but for Gunmetal, I’m trying to build with flexibility and scalability in mind. I don’t know how many items and upgrades I might have, so handwriting queries for each is out of the question. What I’m doing instead is making dialog trees able to be dynamically authored in code. The content I write in the editor can now contain markup indicating that the construction of the tree should be delegated to code, and additional markup can be passed to that code to specify exactly what is desired.

A snippet of a dialog tree in Super Win that queries against all known powerups.
A snippet of a dialog tree in Super Win that queries against all known powerups.
A dialog tree in Gunmetal Arcadia that delegates further construction of the tree to code.

In Super Win, dialog box options were typically limited to two or three choices (most often “yes” or “no”), but for Gunmetal, I anticipate using dialog box options for displaying lists of gear that the player may wish to buy or sell. As these lists may contain any number of items, I’ve added support for scrolling through a set of options that occupy a fixed number of lines.

GunArc 2015-03-27 01-52-23-878

After adding medusa heads last week, I continued working on new enemy designs this week, starting with two versions of enemy spawners. This prompted me to solve a problem that’s been lingering for a while. When I wrote about my entity serialization solution recently, I mentioned that a fix-up pass might be necessary to restore references between entities when loading serial data. This week, I finally tackled that problem as part of implementing correct enemy spawner behavior.

Spawners will generate new baddies up to a specified limit, but after the player kills one of these enemies, the spawner can produce another. To facilitate this, either the spawner must keep track of references to its offspring so it can determine when they’ve been destroyed, or else the offspring need to keep track of a reference to their spawner so they can notify it when they’re about to be destroyed, but in either case, a reference must be maintained in order for this system to function correctly.

GunArc 2015-03-27 23-58-17-251

As part of saving and restoring references between entities, I’ve had to reconcile two similar but distinct features of my engine: handles and GUIDs. Handles are assigned at runtime and are unique only for the duration of execution. These serve as a safe wrapper around pointers. When an object is deleted, its entry in the handle table is removed, which allows any remaining handles to that object to correctly fail a NULL test. GUIDs are unique values which identify objects that have been placed in the editor or spawned at runtime and which can be serialized. GUIDs persist beyond a single execution and are used by the serializer to associate data with a particular object. All entities and components have handles, but only entities that need to be serialized contain GUIDs.

Saving a reference to another entity involves simply saving out its GUID, as this is sufficient to locate the object if it exists. In the general case, this is trivial, but there are two problems we have to deal with:

  1. We want to save a reference to an entity that has been removed. We have a handle to this entity (as it did exist as one time), but we do not know its GUID, which is the thing we need to save.
  2. We want to load a reference to an entity that does not currently exist. We know its GUID, but as it does not exist, we cannot get a handle to it.

I went through a few iterations in solving this, and I’m pretty happy with the solution I’ve landed on. Any time a valid serializable entity is destroyed, a record is made of its handle and GUID. When that entity is rebuilt, we can look up its previous handle value from its GUID and reuse it such that any handles that pointed to the old instance of this entity will now point to the new one. This record also allows us to retrieve a GUID for a entity that no longer exists as long as we still have a handle to it, even though that handle no longer points to anything. This solves the first problem described above.

In some cases, this is also sufficient to solve the second problem. If an entity once existed but has been removed, we can look up its old handle from its GUID when we load a reference. That handle will not point to anything yet, but whenever the entity is rebuilt, it will assume its old handle value, and the handle will become valid.

The one remaining case is when we load a reference to an entity that has not yet existed during this execution. In this case, there will be no record of its old handle or GUID, so we need to reserve a handle value for it instead. Whenever the entity is constructed for the first time on this execution, it will assume that reserved handle value, and everything will work as usual. This solves our second problem case.

GunArc 2015-03-27 23-54-40-788

I’m still not quite at the point where the entire game state can be saved and restored exactly as it was, but this gets me one step closer to that goal and also validates some of my earlier assumptions about how development would go as I continue building new content.

Horizontal Slice

My last couple of blog entries started off with “it was a slow week” or “I didn’t get any real work done” or whatever, and that’s indicative of a loss of momentum I had been feeling as the sorts of tasks I was focused on were thinning. I’m reaching a point where a large majority of moment-to-moment gameplay systems exist in some form, and that left me wondering what to do next.

On Thursday, I plotted out a list of rough milestone definitions that will help me better understand what I should be working on and how it will help me reach a shipping state. Up until now, my pattern has typically been to prototype a single instance of each thing: one melee weapon, one enemy, one boss, and so on. This was done with the understanding that I would necessarily have to revisit these things in the future as I expanded the set of content.

I’m calling this my vertical slice. It’s not really a vertical slice on account of the fact that it’s missing some core elements of the high-level roguelike experience, but I don’t feel like those features would make sense to prototype yet in the absence of a wider array of content to pull from. Most of the immediate gameplay systems can be demonstrated in the current build, so…”vertical slice.”

The next step is to go horizontal and increase the breadth of content. For the foreseeable future, my tasks will consist of building new instances of the same sorts of things I’ve prototyped in the past: weapons, enemies, playable characters, and so on. My expectation is that as I produce more content, I will identify failings in my tools or places where I can better generalize code to support everything I want to do. I’m not done building features, and I don’t expect any milestone to completely displace the preceding tasks, but I do expect the workload to shift. I’ve already seen a shift away from editor, tools, and engine tasks to gameplay code over the course of the last few months. For this milestone, I anticipate spending more time in my editor and art tools producing content versus coding up new features.

At some point, these tasks will start to thin as well, and I’ll transition to the next milestone. I don’t have a good name for this one. Maybe alpha? We’ll see. This will be the point where I have a wealth of content and I can start assembling it into randomized levels. This is where I’ll start to see the roguelike nature emerge and where I’ll be able to get a real sense of the scope of the gameplay experience. As with the preceding milestones, I would expect to see some overlap in the nature of tasks here; it’s hard to imagine that implementing randomized levels wouldn’t bring new feature and content needs along with it, but those shouldn’t dominate my workload.

If that’s my alpha, then my beta will be to balance and tune the existing content, implement whatever lingering features haven’t found their way into the game yet, and try to find and enhance the long-term appeal. Some of the core promises of what Gunmetal Arcadia is probably won’t show up until this milestone. The concepts of faction conflicts and how each game session will shape the next have existed in my head since before I started keeping this blog, but I probably won’t be able to implement those in any real, meaningful way until the game is nearly complete. I can already tell that will be a stressful milestone, and one where it will be easy to want to cut corners. I can’t afford to do that.

Once I’m happy with the beta, I can think about release plans and whether it makes sense to put the game into Early Access at that point. I can imagine there would still be a fair amount of tuning and balancing to be done, especially as more players get their hands on the game. Regardless of how I release the game, the taskload for this milestone should consist strictly of bug fixes, polish, and balancing. The game should be feature- and content-complete at this point. Any features or content that have been cut can be evaluated for future updates, but my goal at this point should be to produce the highest-quality release candidate I can.

Post-launch, who can even say? In a perfect world, there would be enough interest and revenue to be able to continue supporting the game after launch with new updates and expansions. That will all depend on how well the game is received on its way to launch and beyond.

I haven’t attached dates to any of these milestones. I’m bad at estimating task durations, and too many specifics are still up in the air anyway. If I had to make a gut estimate, I’d say I’ll probably have wrapped up the horizontal slice by July when I do the expo rounds. Alpha feels like it’ll take me a few months, which would put beta near the end of this year, and then I could be ready for release early next year. But I don’t trust any of those estimates, and neither should you.


That turned out to be a whole blog post in itself, so I’ll just quickly go through some of what I worked on this week.

I wrapped up the boss prototype from last week, which involved refactoring my attachments system to better support attachments existing across multiple animation sequences. In theory, this puts me in a good place to attach armor or decorations to the player character, although I haven’t prototyped this yet, so I can’t say whether there would be any stumbling blocks there.

There are now three primary melee weapons in the game: a dagger, a short sword (the one from the previous test build), and a long sword. These all inflict the same amount of damage at the moment but vary in range and speed. They don’t necessarily all feel good to use yet, but I’ll be playing around with these values and more as I continue adding weapons to the game.

GunArc 2015-03-21 15-02-02-365

I added a “Medusa Head” sine-wave-traveling enemy to my test map. This required a couple of new features that I hadn’t yet supported; these things need to be spawned dynamically on a timer, whereas my existing placeholder enemy (the slime) was placed by hand. These also don’t collide with the environment and don’t need to be serialized when leaving a room and returning. Because they spawn indefinitely, I’ll probably also want to limit their loot drops, but I haven’t yet looked into that.

I’ve started refactoring items and upgrades into a more generalized “equipment” system. This will handle primary melee weapons, secondary throwing weapons, salable items like gems, stat upgrades, and so on. I’m in the process of figuring out how to dynamically author dialog boxes in order to list inventory contents from the status screen or when selling things to a shopkeeper.

Wall Chickens

It’s been a bit of a slow week getting back to normal development habits after GDC, but I did manage to start prototyping some features that I’ve been wanting for a while.

Continuing with the serialization work that I started a couple weeks ago, I implemented a method of preserving a record of the existence of entities that have been dynamically spawned at runtime. Previously, I was keeping track of the GUID and data definition file associated with any entity that were dynamically spawned in each room of the current map. This data is now written to the serial resource for each room of each map in order to preserve these records across map transitions and saving/loading. This is the final piece of the puzzle needed to facilitate complete saving and loading of any game state. In the future, once levels are randomly generated, some additional data will probably be required to ensure the level is correctly rebuilt when loading (e.g., a random seed or complete Mersenne twister state), but for the test maps I’m working with right now, this gets me pretty far.

I don’t know for sure whether I’ll want any instant death traps in Gunmetal Arcadia (it will depend, I suspect, on finding the right balance between challenge and frustration when tuning difficulty), but in case I do, I added a pair of features that should be familiar to Zelda II fans: bottomless pits and crumbling blocks. In Super Win, I used entities as crumbling platforms, but what I really wanted for this game was to be able to paint tiles on the map as I normally do and have some of those automatically crumble in response to the player stepping on them. Since I already tackled the issue of altering and rebuilding the world’s collision and renderable mesh while working on destructible terrain, it was a short leap to repurpose that code to support crumbling tiles.

GunArc 2015-03-10 18-38-59-229

The second half of that feature is the bottomless pit. In Super Win, I had a few cases where the player could jump off the top of the screen without automatically scrolling to the next room, when no room data were available in that direction. To support bottomless pits, I simply made this change also affect falling off the bottom of the screen, and then I added a new type of tile which does not block movement but which automatically kills the player when they cross it while traveling in a specified direction. Lining the edge of the screen with these tiles ensure that the player dies when falling off the screen.

I was able to repurpose this new tile type for another instant death trap which may or may not make the cut: Spelunky-esque walkable spikes. In the Win the Game series, spikes are implemented as solid blocks that cause damage regardless of which direction the player is traveling. Now I have the option to implement spikes which the player can safely walk through and which only cause damage if the player falls onto them from above (or whichever way they are oriented). I’ve been wanting to avoid leaning too heavily on features from the Win the Game series like spikes, but this feels like a good way to come up with some new and interesting scenarios rather than simply retreading the same ground.

As soon as I started implementing destructible terrain, I knew that I would want to hide loot inside walls. I threw together a quick prototype of what this might look like earlier this week. Right now, every tile has a 100% chance to drop loot, which is silly and obviously not what I’m going to ship, but it’s fun to see in action. There are still a number of unanswered questions here, e.g., will I want a global drop rate for random loot, or does it make more sense to place loot drops inside tiles by hand. (Or both?) In any case, this gets me one step closer to having wall chickens, so that’s cool.

GunArc 2015-03-11 00-50-35-828

The last couple of things I’ve done this week have been super quick prototypes just to make sure things will work as I expect. I threw together a test of what a dialog-driven NPC shopkeeper might look like based on the jeweller from Super Win. As it turned out, my dialog system had been broken since late last year when I made a change to decouple core game data from campaign-specific data, and this gave me a chance to find and fix that issue.

xan_shopkeep

I’m not sure yet what the complete shopping loop will look like; there are a number of dependencies that I haven’t solved yet (e.g., what does the player’s inventory look like?), but that’s becoming one of my top priorities. I’ve done a little bit of work on figuring out how upgrades to variables like jump height can be applied to the player based on collectable items, and I’m hoping to be able to generalize those patterns in a way that is conducive to building a wide variety of upgrade items very quickly.

The most recent feature I’ve been working on is one that’s been looming at the back of my mind for a while: bosses. Exactly how ambitious I get with bosses remains to be seen, but at the very least, they need to have weak points. I’ve prototyped a boss monster using two separate entities, one for the body and one for the head (the weak point). Even in this relatively simple case, trying to get these two entities to look and feel like one cohesive thing has introduced a number of complications, and I’m not yet sure whether this pattern will hold up in other cases. But for a first stab at it, I’m pretty happy with how this has turned out, and I feel more confident that bosses will be a feature I can ship with.

GunArc 2015-03-14 17-01-01-630