Category Archives: Devlogs

Serialization

As I continued working on loot drops, I found it wasn’t feeling right to have items disappear after leaving a room. I don’t know for sure whether I’ll want items to persist indefinitely (in the current build, they have a ten-second lifetime before blinking out of existence), but I do feel like you should be able to walk away and return and still have a chance to collect something that dropped. In solving that problem, I’ve fallen down a rabbit hole of changes that may allow me to support complete save-and-restore-anywhere checkpointing functionality. To explain why that is, I’ll have to take a step back and talk about how things worked in Super Win.

I’ve described my entity-component system in high-level terms a few times already, but this time I’ll be going a little more in-depth with regards to the internal workings.

My level editor also serves as an entity construction tool. In Super Win, entity construction was done entirely by hand in XML markup; in Gunmetal, some aspects have been wrapped within a visual editor for ease. In both cases, however, the editor outputs definition files for each entity. These definition files consist of XML-like nested key-value pairs, written in a binary format for faster loading. As these files are generic in format, I use them for multiple purposes in my engine. When used to define an entity, each of the top-level tags define a component either in full or in part.

defviewer

At runtime, the game invokes the entity factory to produce an entity based on a provided definition file. The factory examines each tag, producing components as needed, attaching them to the output entity, and giving them a chance to use the input definition data to set up their own properties. At this point, the factory also queries the serializer to see whether it contains any additional data with which to define this entity’s components. If we’re just starting a new game and constructing an entity for the first time, it will not. We’ll come back to that in a bit.

The factory returns the fully constructed entity to the game, where it lives for a while and does whatever it’s supposed to do. (Essentially everything that can be seen or interacted with in the game is an entity, from the player character to enemies to loot drops to doors to signposts to particle effects and so on.) At some point, the entity will be destroyed. This may be because it’s something like a particle effect that has exceeded its lifetime, or because it’s an enemy who has been killed or a loot drop that has been collected, or maybe the player has walked into another room and this entity is being removed from gameplay. As part of entity destruction, each component has a chance to export data about its current state to a component delta structure. This data is passed to the serializer and stored until the next time the factory attempts to construct this entity, at which point the original definition data is supplemented with these deltas in order to restore the entity’s components to the state they were previously in.

In order to distinguish between similar entities which may share the same definition data, entities are assigned a GUID. These is done automatically when entities are placed in the level editor, and (new to Gunmetal) this can also be done at runtime for things that are dynamically spawned, such as loot drops. The serializer looks for the presence of GUID information when managing component deltas. If the entity has no GUID information, it is assumed to be a temporary entity like a particle effect that does not need to be serialized.

Not only does the serializer keep track of information about entities and components that have been created at runtime during the current session, it also handles disk access for saving and loading component deltas. This allows the previous state of entities to be restored on a future session. This was how saved games were handled in Super Win, and will likely be how they’ll be handled in Gunmetal as well.

So (minus one or two details I’m deliberately ignoring for the sake of brevity), these features as described should facilitate the complete saving and reconstructing of any game state. So why did I say it was a rabbit hole? Well…

~~~DRAMATIC PAUSE~~~

Despite the presence of this framework, only two components actually took advantage of this functionality in Super Win. One was the “delete component,” used to flag an entity as having been permanently removed from the game. This is how things like gems and powerups know to stay gone after the player collects them. The other was the “data component,” a component that allows any entity to store arbitrary key/value pairs. This was used for everything else that needed to be saved in Super Win besides existence. The player entity would store the name of the active campaign and map here, as well as the coordinates of the room where the game was last saved and the position of the checkpoint within it. NPCs would use arbitrary data to keep track of the few things they needed to know, such as quest completion status. Maybe one or two other things I’m forgetting.

And that was it. Literally nothing else about the game state was ever saved and restored, either when saving and reloading or just when walking between rooms. This is why enemies and hazards always reset to their original locations, crumbling platforms reappear immediately, and so on. In the original You Have to Win the Game, I actually found that behavior to be advantageous since several rooms were designed such that a mistake could put the game in an unwinnable state. Leaving and re-entering the room provided a convenient workaround to this problem. By the time I wrapped Super Win, it was becoming an annoyance, and as of this week, it’s become completely unacceptable for Gunmetal.

So now I have to go back through all my serializable component classes (sixty-seven at last count) and make sure they write out any relevant data that would be needed to restore them to their previous state when destroyed. For some components, this is trivial. The “spatial component” (more commonly a “transform component” but I’m bad at naming things) can serialize position, velocity, and acceleration data, and that gets me pretty far already. Where things get a little trickier is in dealing with references to other things. When the player is standing on a moving platform, a “basing component” on each is used to keep track of their relationship. These sorts of dynamics are more difficult to preserve. My current plan (which hasn’t been thoroughly tested yet) is to save out the GUID of the thing being referenced. On load, that thing may or may not yet exist, however, so a fix-up pass might be necessary for reinstating the reference once all the participants are present.

So far, this process has been going well. I have data being correctly serialized for position, velocity, and acceleration, for AI states, for animations, for current and maximum health values, and a handful of other things. That’s gotten me pretty far already. I expect that maintaining this system will be something that lasts throughout the entire development process (certainly if nothing else, it’s going to be something to take into consideration any time I add a new component class), but the initial impact has been fairly mild, as rabbit holes go.

Oh yeah. I wanted to draw a graph of how all these bits and pieces interact. It didn’t turn out very well, but uh.
entity_construction

Momentum

Super short update today, as I’m right in the middle of an exciting tools-related task, and I don’t want to lose momentum on it. Also this week has largely been spent on bug fixes, and those are difficult to write about in any sort of compelling manner except when they’re exceedingly complex to isolate and resolve.

I’ve been working on bringing a few features over from Super Win, including locked doors and pickups. Coins, bombs, ammo, keys, and health can now be collected in the field and are represented on the HUD. The next step will be to drop these from enemies and environmental objects (think Castlevania torches and sconces), and then after that, I’ll probably start implementing NPCs and shops. At some point, factions should start coming into the picture, which is exciting since the faction tug-of-war has been a core promise of Gunmetal since its inception.

loot

I made a small change to the audio synthesizer to reduce pops when notes are played by introducing a brief (1/200 sec.) fade-in and fade-out time on volume changes. This is most noticeable on headphones. A comparison is available here: https://soundcloud.com/j-kyle-pittman/sets/synth-comparison

In preparation for launching a public game feel test build sometime in the near future, I built Gunmetal for Mac and Linux a few days ago for the first time in months. Fortunately, nothing too major had changed or broken; I ran into a case where my GL implementation was failing to set blend modes correctly, but it was an easy fix.

Despite my comments last week on not worrying about scheduling, I’ve been curious where exactly I spend most of my development time — logging hours and estimating tasks have never been a part of my workflow, so by and large, I consider any schedule I could write to be inaccurate by an order of magnitude and wholly worthless. But if I can throw science at that problem, it gets way more interesting. I’ve been tracking my productivity as a function of SVN commits over time since launching Minor Key Games, but I’ve never had any sort of an accurate metric for how long an individual task might take. Starting today, I’m going to be spending some time developing tools to hopefully give me a clearer picture of my moment-to-moment development habits.

Roadmap

I’ve mostly spent this week tuning and fixing bugs in the features that I discussed last week, so rather than go into detail about what I’ve been working on, I thought I’d share some of my ideas for Gunmetal Arcadia‘s road to launch.

As I discussed in that game’s postmortem, Super Win was not the success I’d hoped it would be. A few months later, it looks like it might not be a complete failure either, but at best, it’s a slower burn than is sustainable. I theorized a bit in that article why that might be, and I’m taking steps on Gunmetal to make sure this game performs better. Keeping this devlog is the first of those; implicit in that is that I’m also not being so wary of showing the game in early or incomplete states. Between wanting to show representative “final” Super Win content very early (e.g., for the announcement and teaser trailer barely two months after conception) and not wanting to show too much of “the cool stuff” like the dream sequences and final level, I found myself in a state of constantly crunching to meet deadlines that did little to benefit the game’s visibility in the long run.

For Gunmetal, I’m doing an about-face on that attitude. My modus operandi this time has been to show everything, regardless of how broken and unpolished it is, hence all the placeholder art stolen from Zelda 2 and Faxanadu I’ve been putting on display in this devlog. (Happy news: as of today, I’ve replaced all “borrowed” art with original content. Still placeholder, but not so litigious.)

ga_placeholder

The next step is to start putting the game in players’ hands as early as possible. To that end, I’ll be uploading a short demo soon which will serve to illustrate the current state of core game mechanics. My intent with this demo is to collect feedback related to the feel of these core systems. Does the player move too fast or too slow? Does jumping feel too floaty or too heavy? Does combat feel solid and tactile or papery and insubstantial? Nailing the game feel is absolutely crucial, perhaps moreso than any other single aspect of the gameplay experience, and the longer I wait before gathering and reacting to this feedback, the harder it will be to make changes without inducing unwanted side effects on other parts of the game.

If this is successful, I’d like to continue making these sorts of iterative drops as more high-level systems start coming online. My expectation is that each of these builds would focus on some subsection of the game (e.g., randomized levels, item synergies, and so on), eventually culminating in a more complete, cohesive vertical slice experience.

Looking further down the road, once the game is fully playable and in a position to be polished and tuned, I could turn my attention to pre-release plans. I’ve been debating whether it makes sense to put Gunmetal into Early Access on Steam. My gut reaction to Early Access in the past has been an immediate NUH-UH, but recently I’ve been feeling like it might make sense for Gunmetal due to its roguelike aspects. It will be a while before I can fully commit to that plan; whether it makes sense will depend on a number of factors that won’t be fully visible for some time, and I would want to be careful about properly messaging what that version of the game was (e.g., a nearly complete game, not a partially functional tech demo) and what it wasn’t (e.g., a blank slate awaiting any and all input), but I think it could give me the opportunity to “soft launch” the game in a form that were technically complete and theoretically ready for release but with some extra buffer time built in to respond more aggressively to player feedback, bug reports, and suggestions.

In the meantime, I expect I will be showing Gunmetal Arcadia in some form at events this summer.  I took a playable demo of Super Win to several events last year, including RTX, SGC, and QuakeCon. I’m planning to attend some of these again, and possibly others as well. (I’ll announce dates as soon as anything is confirmed.) Whether I bring a playable build of Gunmetal depends largely on what state the game is in at the time. The worst case scenario is that it’s simply not ready to show and I just demo Super Win again (and maybe also Neon Struct), but at the very least, I should be able to bring a trailer and some promotional materials. I have the advantage this year of being able to fall back on that option, meaning I won’t have to crunch to complete a demo, an experience that I felt was severely harmful to Super Win. I spent the entire dev cycle on that game worrying about development time and crunching towards milestones only to land ahead of schedule and unsure of what to do next. This time I’m just not worrying about that, or really anything else. I know how to make games. I know I work fast. I’m not going to beat myself up over it.

Grindstone

I’m back! Well technically, I was back from my honeymoon last Monday, but I had already scheduled that post in advance, so this is the first new material I’ve written since getting married and traipsing around Europe.

I chose to spend this week knocking out a few tasks that had been looming overhead for a while, the last few things that need to happen before I feel like the complete set of immediate player actions exists in some form. The first of these was to alter the size of the player’s bounding box in response to crouching and standing. Historically, my entities have had one primary collision primitive that never changes in size or relative location, which is why holding the down button in Super Win just makes the character tilt his head down rather than crouching. For Gunmetal, I wanted to have a proper crouch that could be used to avoid enemy shots, and that meant tackling this issue.

crouchcoll

My editor now has a list of primitives which may be associated with animation sequences. At runtime, the game looks for changes to this setting whenever the current topmost animation sequence changes (as I mentioned in a previous blog, multiple prioritized sequences may be playing at once, with the highest priority sequence being the one seen on the screen) and toggles the appropriate collision primitive for that sequence.

crouchcoll2

There are still a few lingering issues left to solve here. For instance, I’m not doing any checks to see whether the new collision primitive is fully encompassed by the previous one; if it’s not, we run the risk of intersecting solid geometry and falling out of the world. (Consider the case of standing up after being crouched beneath a low ceiling. In this case, the full-size standing collision primitive would intersect the ceiling, and, in the absence of any proper handling, we could walk or jump through those blocks.) But in the general case, at least, this is working correctly, and I’ve been able to prove that crouching under projectiles will function as intended.

The next major feature I worked on this week is an extension of the palette swapping feature I implemented for sprites a couple months ago. I can now apply this same process to every 8×8 tile of each tileset in order to palettize environments. This is another feature that I contemplated for Super Win but rejected due to time constraints. For Gunmetal, this should be a huge win in terms of coaxing a variety of aesthetics from a smaller number of tilesets.

palettes

On the game side, this works a little differently than sprite recoloring. Each sprite is rendered in a separate draw call, so I can simply set each of the three palette colors as shader parameters prior to drawing. By contrast, each layer of the environment is drawn all at once in a single draw call, which means all the colors for each 8×8 tile must be specified somehow. My solution is to aggregate all the palettes into a texture atlas (shown below in PIX) and then index into this texture with a new texture coordinate channel added to the environment’s vertex buffer.

subpalatlas

In fact, with a little more work, this pattern could be generalized to encompass sprite rendering as well, such that I could draw all the on-screen sprites in a single draw call. This would depend on packing every sprites’ sheet into another texture atlas and maintaining a fixed-size dynamic vertex buffer whose vertices could be allocated to each sprite’s quad, in much the same way I handle  font rendering. Sprite rendering isn’t a bottleneck at the moment, however, so I probably won’t go down this road, but it’s certainly interesting to think about.

I did some minimal work on Saturday to faciliate vertical attacks while airborne, a la the downthrust and jump thrust attacks from Zelda 2 (or the pogo attack from Ducktales, or from Shovel Knight, or whatever). I’m not 100% sure this feature will make the cut — this depends largely on whether it feels necessary once I have more representative combat spaces blocked out — and it will need some further attention to make it feel good, but I wanted to hack it in there in some form, as it’s one of the last immediate player actions I’ve been considering.

vertatt

Finally, I’ve started implementing a HUD. I don’t know for sure yet what information I’ll want here, in part because I haven’t yet decided how some game systems will work (e.g., will secondary weapons consume ammunition?), but since I’ve been working on combat recently, it’s important to at least have health represented in some fashion. I’m toying with the idea of displaying enemy names and health on the HUD, which isn’t necessarily in keeping with the style of the classic games I’m imitating, but I think it could be nice for bosses at the very least. Theoretically, a minimap might be a better use of that space, although depending on the size and topography of the levels, a minimap might not be necessary for this game.

hud_mockup

I’m reaching an exciting point where the individual systems I’ve been working on are starting to coalesce into something that resembles a game. I suspect sometime within the next few weeks, I’ll be able to publish a small demo as a means of collecting feedback on the feel of core mechanics, the first step in a plan to involve players in the development of Gunmetal Arcadia all the way to launch. I’ll be talking more about this plan and a roadmap for the future next week, so stay tuned!

Implicit Narrative

There’s a question that comes up all the time when one is presenting a new game, and it can be a surprisingly difficult one to answer: “What’s this game about?” The reason this can be such a difficult question is because it is often implicitly asking, “What is this game’s story about?” And the answer to that question is almost completely orthogonal to what I find most exciting about games.

narr_smb

Super Mario Bros. doesn’t have a story — when I say “story,” I’m referring to an explicit narrative, what we might think of as “plot.” Super Mario Bros. has a premise: “King Koopa has kidnapped Princess Toadstool and Mario has to save her.” But what that game is really about at any given moment is running, jumping, stomping on enemies, and avoiding hazards. Yes, the premise provides some motivation and context for the platforming action, but I’d be hard-pressed to say the game is really about its premise.

What we know of the story in Super Mario Bros., we know because we see it while playing. We know that King Koopa has imprisoned others besides the princess because we encounter them at the end of each castle. If we dig deep enough, we even find that the “King Koopas” encountered at the end of each castle are decoys, although this is never explicitly stated in the game itself.

Classic games often employ this sort of implicit narrative. Perhaps this is because gaming originated as something closer to a sport (think Pong), or perhaps it’s because the fidelity to convey more intricate narrative simply wasn’t available to early developers. Certainly the NES had its fair share of narrative-driven RPGs, and the SNES even more so, but it wasn’t until the CD-ROM era, when characters could be fully voiced, that I thnk we started seeing a trend towards the majority of games having an explicit narrative.

To be clear, I’m not saying either one of these is better than the other, but as both a gamer and a developer, the elements of games that I value the most tend to be external to explicit narrative. There are always exceptions, and I think some of my favorite moments in gaming have been when the narrative and gameplay integrate seamlessly, as in Portal‘s false ending. But if I had to pick a side, it would always be gameplay over narrative. This is perhaps obvious in the context of the Win the Game titles, particularly the first, in which only the names of rooms and occasional messages on the walls provide any sort of establishing context. I tried to inject a little bit of explicit narrative in Super Win because I felt like I had to, but I’ll be the first to admit that I’m neither interested in nor terribly capable of writing interesting characters or events.

narr_sm

Let’s look at another example. Super Metroid has a premise: “Ridley has stolen the last Metroid and taken it back to Zebes.” That is, if memory serves, the only explicit context provided for the adventure that follows. When we encounter the remains of Mother Brain’s glass chamber, we understand very clearly that this is the same location as in the original Metroid, some years later — a great example of mise-en-something storytelling, probably. When we reach Tourian and see Metroids again, we understand that Ridley has been breeding or cloning these creatures, and we encounter one of the game’s few narrative moments, albeit one that is told without words. The baby Metroid, now mutated to monstrous size, recognizes Samus as its mother and spares her life, returning again to aid her in the final battle.

narr_is

I’ll mention one last example, because it’s apparently the only game I play anymore and one that is highly relevant to Gunmetal Arcadia. The Binding of Isaac has a premise: “Isaac is hiding in the basement to escape his fanatical mother.” As in many classic games from which Isaac clearly drew influence, our protagonist does not speak, nor do we encounter any friendly speaking NPCs to give context to the environment. But where Isaac does a fantastic job of establishing its lore is in the design of its items. It would be easy to simply name items after their functional role: “damage up,” “health up,” etc. But in abstracting items from their functional use, Isaac crafts a richer and more interesting world. Isaac uses tears as a projectile weapon, so many weapon upgrades are things that might make him cry, from toothpicks to keep his eyes pried open to a torn photograph of what we may assume was his family prior to some separation. The use of pills as unidentified items (think potions in classic Rogue-likes) lends some flavor in its own right, but we when find the “Mom’s Purse” item, and it’s full of pills, that tells us something about her character as well. Isaac‘s lore is often grim, offputting, and offensive, but it’s revealed in a way that is smart and effective, and I think that’s worth celebrating.

narr_ga

Gunmetal Arcadia has a premise: “Arcadia is being invaded by aliens, and we have to take the fight back to them.” This is just about as barebones of a premise as it gets, and it’s for that reason I find it difficult to say what the game is about. To me, it’s about 2D hack-and-slash combat in procedurally generated environments. I understand the importance of a strong premise as an emotional hook that potential players can latch on to, but I’m far more interested in building a world and developing a lore organically through the things the player encounters than I am in plotting out a narrative arc or writing robust characters.

That’s not to say I have zero vision for Gunmetal‘s world. There are some core underpinnings on which I hope to build a tangible in-game lore. The premise involves the player’s homeland being attacked by alien invaders, and my intent is that over the course of a run, the player will venture out into the wild and ultimately destroy the alien menace at its core. (And then maybe they’ll return home, just to put a nice pretty bow on the obvious hero’s journey.) But then we have to ask, what is the world of Gunmetal Arcadia about when it’s not at war? And that’s where I’m hoping to establish an interesting implicit narrative through the use of items, locations, NPCs, and so on. The world is divided into rough halves of those who favor technology and those who favor magic. These factions are not in direct conflict with each other, or at least not right at this time, but they have a tense and tenuous balance. The ongoing war provides a unifying catalyst for those who can put their differences aside, while the most zealous among each group see it as reason to cling even more rigidly to their tenets. (Putting it into writing, I realize that perhaps this sounds like a fairly on-the-nose metaphor for a real-world science-vs-religion debate, so to be clear, that’s not my intent, nor am I interested in making those kinds of statements in a video game.) What’s exciting to me about this concept is the world it will allow me to build, one in which steampunk tanks piloted by heavily armored marines can exist alongside elves and pixies and spellcasters. As I may have mentioned before, Faxanadu is my primary point of reference for Gunmetal‘s art style, and I think that sort of dark fantasy (or at least as close to dark fantasy as the NES could muster) will play well with the lore I want to build.

So, what is Gunmetal Arcadia about? Take your pick.

Entity-Component System

Several years ago, after graduating from the Guildhall at SMU, I began writing my own game engine based on the rendering engine I had developed as part of the curriculum. This has been the basis for nearly every indie/hobby game I’ve released since, from Arc Aether Anomalies back in 2008 to Super Win the Game last year, and it’s something that I am constantly growing.

I’ve written about the motivation for rolling my own tech in the past, (notably in the “About” text in You Have to Win the Game), so I’m going to gloss over that today and instead focus on one of the biggest changes I’ve made to my engine over the last couple of years: the inclusion of an entity-component system.

Let’s jump back in time to May 2011. I had recently rolled off the  Duke Nukem Forever team and was looking forward to having some time to start working on a new side project. This became The Understory, an ambitious mix of first-person dungeon crawling, procedural level generation, and Metroidvania item progression. I worked on it for about four months before realizing that (1) the game was ridiculously overscoped, and (2) I had coded myself into a corner and would have to rewrite a lot of stuff if I were to make any more progress. I abandoned The Understory, though some of its ideas would come back in the untitled dungeon crawler I worked on in late 2013 (also abandoned) and now in Gunmetal Arcadia.

A month or two later, I decided to start up a new project, one that would be smaller in scope, and in which I could tackle some of the development problems I had encountered on The Understory. This would become You Have to Win the Game.

Right from the start, I knew I needed a better plan for authoring game entities. In The Understory, I had tried to write a classic OO-style entity hierarchy, with all my entities being derived from an abstract base class and virtual functions everywhere to differentiate things from each other. This failed spectacularly, as I ended up wedging in “bool IsPlayer()” sorts of functions all over the place. I needed a more flexible system, and the entity-component model felt like a good choice.

It took me a while to get a good feel for the scope of a component. Some of my early tests had physical properties (position, velocity, acceleration, etc.) each split out into their own components. In retrospect, this was obviously silly, as these properties are wholly dependent on each other and should all exist in the same component.

In You Have to Win, I had some minimal hooks to allow myself to initialize components from markup in a few very specific cases. This allowed me to define templates for things like bouncing hazards and bullet shooters. I could then instantiate these templates via another markup sheet that would define the entity’s position in a room. I had a rudimentary level editor built into the game with which I could draw maps, but entity placement had to be done through external text files and build scripts. Tuning rooms was a slow, tedious process.

When I started working on Super Win, it quickly became clear that the editor I had developed for YHtWtG would no longer suffice, and in building a new one in C#, I was also able to tackle the problem of placing entities directly within the editor. This also led me to find a more general solution for the problems of saving and loading entity data, culminating in a unified serialization path for all entities.

In Super Win, I began moving in a direction of having all components be entirely defined by XML markup. (In Gunmetal Arcadia, this is now the only way to define a component.) Eventually, the amount of markup text I was having to parse just to start up the game became a bottleneck. To address this, I wrote a new binary file format containing nested key/value pairs and a command line tool to convert XML or INI files to this format. This removed the bottleneck and allowed XML markup to continue to be a feasible option for defining components.

In Gunmetal Arcadia, I’ve begun abstracting away large parts of the XML markup behind a visual editor interface. I had already done a little bit of this in Super Win, specifying sprite sheets and entity positions automatically under the hood, but for this game, I’m trying to completely eliminate the large amounts of markup required to script NPCs and enemies. As I mentioned in last week’s post, one of my eventual goals is to have a visual interface for every component, such that I never have to think about the markup at all, but I’m not yet sure that’s a reasonable goal for Gunmetal.

One of the hurdles I’ve yet to completely overcome is the notion of scripting game logic with markup. I have a pair of related tags, <action> and <query>, which are recognized by a number of different bits of code and which allow me to, in essence, make function calls or branch on conditions in a script-like manner. This served its purpose well on Super Win, and I’ve reused it a few times already in Gunmetal, but the internal syntax for these tags is often inconsistent and lacks any sort of reflection to clarify their usage. In the future, I hope to standardize these in some way, at the very least by enforcing a consistent syntax, but also — if I’m really dreaming big — possibly by going so far as to provide a C-like scripting language that could either be translated into known tags or converted to bytecode and processed directly.

It’s clear that my entity-component system is not finished, but it’s getting better with every game and is becoming a fundamental, defining part of my game engine. I haven’t really talked about the actual code here, but as I’ve gotten accustomed to programming within this environment, I’ve made a number of improvements to facilitate safe, fast, concise access of components and their properties from wherever I need them. I can refer to components or entities by generic handles that abstract away the actual pointers and gracefully deal with problems like objects being deleted while something else is still trying to reference them. I can resolve references to entities or components of a specific type given either an entity or component point or a generic handle. This flexibility has been invaluable for writing the sort of code that entity-component systems naturally encourage, the sort of code that doesn’t care specifically what it’s looking at but knows how to deal with particular types of components which may or may not exist.

Combat and AI

This week, I finally started working on two related systems that have been lingering in the “stuff I really need to do” pile for way too long. The first is combat; although I started prototyping a melee weapon and testing its collision against the environment and other game entities last month, I hadn’t yet completed the loop by funneling these collision results to a health component and reacting to damage correctly. The second is AI; in order to start testing damage against the player, I needed a simple placeholder enemy who could move around and inflict damage on touch.

When I was working on an untitled, unreleased dungeon crawler prior to Super Win the Game, I had written a few components releated to the concepts of health, damage, knockback, etc. Most of these had been sitting unused for over a year and had never really reached a shippable state, so rather than revisit each of them, I chose to rewrite all of them into a single new component that would manage all of these elements at once. Ever since moving to an entity-component system (and perhaps the origins of that system will be my next blog), I’ve been trying to find the right scope for each component. I find that when I break things down into the smallest, most granular level, I end up with a lot of dependencies and communication between components, and that feels bad to me. I like it when components are able to function autonomously. There will always necessarily be some interaction among components, but in this case, nearly every piece of functionality in each of these components was dependent on another one, and it made more sense to unify them into a single component.

So now I have one component (still called a “health component”) which manages the entity’s current and maximum health values, receives damage from external sources, sets stunned and invulnerable states in response to damage, and tests whether incoming damage is valid based on entity allegiance, invulnerability, and so on.

The second feature I worked on this week for AI. I’ve been dragging my feet on this one for a while; along with UI and collision, AI is one of those systems that I’ve historically had difficulties implementing. When I was working on the Win the Game titles, I was able to avoid implementing AI by treating the enemies as “hazards” that would simply bounce back and forth between two walls forever, but for Gunmetal, I’m going to want a variety of enemy behaviors, and I will benefit from making it as easy as possible to author and maintain those behaviors.

For now, I’ve chosen to script AIs with markup in largely the same way I did in Super Win, but with some additional rules for choosing a random action from a weighted set.

ai_behavior_sets

This is a first pass. It’s highly unlikely this is the implementation that will ship in Gunmetal Arcadia, but it’s a start. Looking back at my previous post on animation tools, it’s easy to imagine how I could produce this markup from a visual interface. In fact, I’ve been debating whether to extend the editor’s entity construction tool to encompass all components such that I never have to author any markup by hand. That might be a little too ambitious for this project, but if I continue reusing these systems and this editor for future games, it could be worth the time investment.

Secondary Weapons

This week, I’ve been working on another facet of the core player actions in Gunmetal Arcadia: secondary weapons. These will be an alternative to the standard melee weapon and will encompass a variety of ranged attacks in the vein of Castlevania‘s knife, axe, cross, etc. Only one secondary weapon can be carried at a time, and each will have its own advantages.

In terms of implementation, I was able to leverage the attachment point system I wrote recently to spawn new entities at a certain time during an animation and at a specific location relative to the player sprite. Unlike the melee weapon attachment, however, the secondary weapon sprite is not fixed in place; once it has spawned, it is free to travel through the air and collide with whatever it wants.

One of my goals with secondary weapons is to facilitate a number of different play styles by modulating their behavior with other effects, in much the same way as items can synergize in The Binding of Isaac. So for instance, a basic throwing axe might be upgraded to pass through enemies after it hits them, bounce when it lands on the ground, and inflict fire damage. Or a throwing knife might split into two smaller knives that each home towards enemies. This technology doesn’t exist yet, but as secondary weapons start to come online, I will be building with modular effects in mind.

I haven’t yet determined whether these secondary weapons will be limited by hearts/mana/whatever arbitrary resource as they are in the Castlevania series. I imagine that will come down to testing and tuning, and in the absence of enemies, I’m not there yet.

In addtion to the secondary weapon, the player will always have access to a cache of bombs. Bombs can be placed on the ground or thrown from a distance and will inflict radius damage to both enemies and the player. More importantly, they can also break through certain surfaces.

Destructible terrain is something that I wanted to do in Super Win but didn’t make sense for a number of reasons. In that game, I constructed the visible mesh and collision mesh for each room once upon entry and never allowed them to change. Anything that needed to be dynamic was necessarily built from an entity object, including crumbling platforms and the “ghost blocks” that can be toggled on with the aid of a powerup. With the recent change to make collision dynamically generated only when it is needed, there was one less hurdle. I can now simply alter the underlying tile data, and the collision automatically updates to match. The visible mesh still needs to be updated, however. My expectation was that rebuilding the entire mesh would be too slow, but I figured I would start there and optimize where I could. As it turned out, rebuilding the entire visible mesh is fast enough that it does not produce a noticeable hitch even in a slower debug build. I have optimized it a bit by queueing up all changes to the terrain for a single frame and only rebuilding the mesh once per frame, but even without that optimization, I did not experience any loss of performance. Theoretically, larger rooms might take long enough to rebuild that it would be worth subdividing the visible mesh into smaller portions and only rebuilding the ones that have changed, but I can cross that bridge when I come to it.

Bottle Episode

Today marks my first devlog post of 2015 and roughly three months of development on Gunmetal Arcadia. Feels like a good time for a recap and a look at what’s next.

The earliest seed of the idea for Gunmetal Arcadia that I can find dates all the way back to May 2012, just weeks after I released You Have to Win the Game. I sent myself an email with the subject line “Short-form procedurally generated Zelda 2 dungeon crawler” and some notes on what this might entail. I didn’t pursue the idea at the time, but it stuck with me. It wasn’t the right choice for Super Win, but as I was demoing that game and pondering future projects, it came around again. This time, I described it as “Super Win with combat” and cited Battle of Olympus as another point of reference. I also wrote down “Ghosts of Arcadia” as a potential title. The “ghosts” part of this title was a nod to the idea that previous sessions would influence future sessions, possibly even with previous characters appearing as literal ghosts a la NetHack.

A few months passed. I continued to take notes on this concept and play more NES games for inspiration. Eventually, I decided that I had already exhausted the concepts of ghosts and dreams in Super Win, and I landed on Gunmetal Arcadia as a title that more accurately represented the game I envisioned.

I set up this blog at the very end of September, just before Super Win launched, and I created a repository for Gunmetal a few days later. I was in the process of moving to a new apartment, and I knew I wouldn’t be able to spend all my time working on a new game, but I wanted to hack out some features to immediately distinguish this game from its predecessor. I started with game feel, finding the appropriate weight and sense of movement for the player character.

It was around the middle of November that I had finally settled into the new place and hit the ground running on full-time Gunmetal dev. Some of my first goals were to revisit the toolset I had developed for Super Win and level it up for my Gunmetal needs. I expect this will be a continual thing throughout development, especially as I tackle procedural level generation at some point in the future.

The last month and a half have been a scattershot series of feature adds roughly centered on growing the set of actions available to the player on a moment-to-moment basis. I’ve discussed melee combat and ladder traversal in previous entries; this week, I also added destructible terrain and bombs. Bit by bit, the number of things you can do in my test level is growing, on top of whatever features already existed in Super Win (doors, dialog boxes, collectables, and so on).

There are some notable omissions in the current feature set. Although I have a melee weapon that collides with the environment, I don’t yet have enemies. I don’t have powerups. I don’t have any concept of health bars, damage, dying, or permadeath. I don’t have procedural level generation; that will likely be one of the last features to come online, as I want to be able to prove I can make a single handcrafted level fun before attempting to make random computer-generated levels fun. Three months in, there’s still a lot of things that need to happen before this starts to feel like a game. And that’s probably fine. I don’t have a specific timeline for this project, but my experience with previous games has been that the upfront feature implementation tends to move quickly and goes the furthest towards establishing a quality bar for the game. I don’t want to get into Super Win postmortem territory, but I probably could have spent more time building features for that game, and I want to make sure I give Gunmetal the time it needs.

One last note: I tried streaming some live development last week, and it was pretty fun, so I’ll probably give it another go at some point. I haven’t yet figured out exactly what day or days will work best for that, but you can follow me on Twitch if you’re interested in checking it out.

Grab Bag 3

I kicked off this week of development with a feature that I’ve been wanting for some time: attachment points. When I brought placeholder assets from Zelda 2 into my editor a few weeks ago, I was able to start testing melee combat feel, but I knew I would need some additional features to accomplish everything I wanted to do.

link_sword

Link’s melee animations have his weapon drawn into them. This means Link can only use this sword, never an axe or a hammer or a lightsaber. In Gunmetal Arcadia, I want to have interchangeable weapons, which means the weapon art asset needs to be decoupled from the player sprite.

link_wo_sword link_sword_only

This introduces a new problem: aligning the weapon sprite with the character’s hand. If my art assets were locked down and I knew they would never change, I could hardcode this offset, but I’m trying to avoid those sorts of quick, dangerous hacks in this game. (Also I have no actual art assets yet.) The right way to tackle this problem is to provide data to position the weapon sprite in the appropriate location regardless of what my sprites and animations look like.

Enter attachment points. This system allows me to specify named points on a sprite which may exist only on one frame, or across an entire animation sequence, or for the entire duration of the sprite. Regardless of the scope of the attachment point, its location may vary per frame, as well. Using this system, I can place an attachment point on Link’s hands for the appropriate frames of the melee animation. At run time, I can look up the location of this point and spawn the weapon sprite at this location. When this frame ends and the attachment point is no longer in scope, the attached weapon sprite is automatically removed.

Compared to Super Win the Game, I’ve been moving away from relying mostly on implementing features in XML markup and towards providing an interface for facilitating features for this game specifically. To that end, I augmented the attachment point editor with a feature for automatically spawning an entity and associating it with the specified attachment point. This allows me to handle combat mechanics almost entirely through the editor and will make it much easier and faster to add new content in the future.

link_attach

As a test, I replaced Link’s sword with a battle axe. Fun times.


A few months ago, I gave a talk at the Dallas Society of Play about the CRT simulation in Super Win the Game. You can find the slides and some source code from this talk here:
http://superwinthegame.com/dsoptalk/

One of these slides mentioned that I had considered an interlacing effect but had rejected it due to its framerate-dependent nature. In giving this talk a second time last month, however, it struck me that I was already using a couple other framerate-dependent effects which can be automatically toggled off or reeled in when vertical sync is disabled. Since then, I’ve had a note to myself to at least give it a try, which I finally did on Friday.

The good news is my plan for implementing the effect worked exactly as I’d imagined. The bad news is it’s a little hard on the eyes. Maybe not too surprising. Nevertheless, it fits within my target Shader Model 2 instruction count overhead, it’s easily tunable, and it adds a fair amount of authentic retro grit, so I’m leaving it in for now.


The last big feature I worked on this week is another one that I’ve been sitting on for a while. I’ve had a note on my whiteboard for a month or two that says simply:

ladders

Ever since I set up the physics for Gunmetal Arcadia, it’s been apparent that vertical traversal will be significantly different than in Super Win. In that game, the jump height is moderately high from the start, and it can be amplified with a double jump and wall jump. By contrast, the jump height in Gunmetal is fairly low and gravity pulls harder on the downswing. There may or may not be powerups to increase jump height or add double jump or wall jump, but it’s clear that in the base case, jumping is not going to be a significant means of reaching higher ground.

Ladders and stairs seemed like the clear choice for diversifying levels by adding some vertical elements without requiring the jump height to be higher than I wanted. The question then was how to implement these. Ladders and stairs (of the NES Castlevania variety) tend to be a little awkward to implement because they add modal gameplay rules. For instance, while climbing on a ladder or stairs, you typically won’t be affected by gravity, you may not be able to attack or perform other standard actions, you’ll play a custom animation that may have some rules of its own, and so on. It represents an odd circumvention of normal gameplay systems, and that makes it a little more difficult to implement and more prone to introducing bugs.

stairs

My original idea was to implement ladders and stairs both in the same way, by placing invisible “mount/dismount” entities at the top and bottom of the path and specifying an animation to be played while traversing this path. I prototyped this implementation but ultimately rejected it for a number of reasons. It felt bad to only be able to mount a ladder from the ground, as opposed to in the air. It made dismounting from the top of a ladder difficult, and it required me to hack in some fixes to prevent the player from falling through the top of a ladder.

In light of those difficulties, I pushed stairs to the backburner and decided to focus on ladders, as they are the more interesting and versatile tool. Rather than using invisible entities to toggle the climbing mode, I added ladder tiles as a new type of world tile. For reference, other world tiles include solid blocks, harmful blocks, shallow ledges, water, and so on. Ladders are now a new kind of tile which the collision code can query and react to. They can be stood on and jumped through just like shallow ledges, but they can also prompt the player character to enter climbing mode when the proper criteria are met.

I’ve looked at a number of examples of ladders in 2D games, from classic NES games to modern platformers and roguelikes. I’m using Faxanadu as my model for how ladder traversal should work in Gunmetal Arcadia. In particular, I’m allowing horizontal movement while attached to a ladder, which allows me to use a string of ladder tiles in a row as “monkey bars” for bridging long gaps.