This week was an exciting one, as a number of systems in progress coalesced and I saw the promise of what Gunmetal Arcadia will become begin to appear.
As I showed in last week’s video, I’ve been getting animations for melee attacks wired up using sprites from Zelda II as placeholder content. I continued working on melee combat this week, adding collision checks and knockback in response to hits. This prompted me to migrate a system of inertia and friction which had previously been roughed out specifically for the player character in Super Win the Game up into the base game engine so that any entity can take advantage of it. In Super Win, the player normally has no inertia; movement is instantaneous and corresponds 1:1 with player input with no ramp-up or ramp-down time. The one exception is for walking on ice, in which case there is a great deal of inertia to make surfaces feel slippery. For Gunmetal Arcadia, I want a slight amount of inertia on normal surfaces, not only for the player character but also for enemies and NPCs. Surfaces can now define a friction scalar relative to a default value, and any entity with a physics component will react to this friction and set its inertia accordingly.
The next big feature I worked on last week is one that’s been cooking in my head for a while, and that is palette swapping. This is a feature I wanted for Super Win, and I did some rudimentary prototyping of it for the NPCs in that game, but I’ve now made it a real first-class feature with editor integration and everything.
The process begins with source art authored as I intend it to appear in the game. In this example, I’m using the Wayfarer sprites from Super Win.
This content is drawn using the standard 56-color NES palette with an additional palette entry for transparency.
When I load a bitmap into the editor, it is analyzed for validity; it should contain no more than four colors, and one of these should usually be the transparent color. The opaque colors are then sorted by brightness and reassigned indices 0, 16, and 32, which are the top three entries in the leftmost column.
The editor then resaves the bitmap with these indices. It will remain in this state all the way until it is loaded into the game.
When the bitmap is converted to grayscale, the original color palette is also saved to editor data, where it may be previewed and updated.
These changes are also reflected in the entity construction tool.
When packaging content into a format the game can use, the editor saves the bitmap with the grayscale indices alongside the colors for the palettes specified in editor data.
When the bitmap is loaded into the game at runtime, the palette is altered to swap the grayscale entries (indices 0, 16, and 32) to be pure red, green, and blue colors.
This allows the sprite shader to isolate each color of the sprite by looking only at the red, green, or blue channel. These components can then be multiplied by the palette colors provided by the editor, and the end result is the recolored sprite as we expect to see it.
A couple of notes on this: the grayscale version isn’t actually necessary. I could just as easily alter the palette to include the red, green, and blue entries within the editor so that the bitmap could be used exactly as it is when loaded into the game. However, doing this at runtime is trivially cheap, and leaving the bitmap in a grayscale form makes it easier to view and modify in case I need to go back and make changes to the sprite. Another alternative would be to leave the source art intact and map the original palette indices to new palette indices, but I kind of like altering it because it helps me to think of my source art as not being associated with any one true color palette.
It’s also worth noting that as I am strictly enforcing four color sprites, I could minimize file size by saving the bitmaps as 2-bits-per-pixel, but at the resolution I’m dealing with, reducing file size is a non-issue at this time.
This feature is exciting for a number of reasons. Along with sprite mirroring in shaders and various other changes I’ve been making recently, it represents a better, fuller, more robust implementation of a feature that was hacked into Super Win. It opens the door to a number of cool features that are evocative of retro games: rapid palette swapping to produce a flashing effect when taking damage, altering enemies’ palettes to represent variations on similar archetypes or “champions,” possibly even doing some fullscreen palette swapping trickery to “fade” screens in and out in discrete increments as was often seen on the NES. It may even be the first step on the road to character customization, which is something I wanted to do in Super Win but had to abandon because it was beyond the scope of that game.
The last thing I’ve done this week is to split out the player character entity into separate representations for the side-view action scenes and the top-down overworld map scenes. This was done in the interest of code legibility. This player character implementation began its life in You Have to Win the Game and grew out of control throughout Super Win to incorporate a number of disparate features. By using separate entities to represent these different states, I can manage the code more easily and also avoid some of the hassle associated with keeping a single entity alive throughout transitions to and from the overworld map. In Super Win, the player entity is constructed once when the game launches and destroyed when the game is closed. All changes to the player’s state, from saving and loading games to moving between levels, are represented in that one object. I’m moving away from that pattern in favor of one where the player entity is destroyed and rebuilt with relative frequency and persistent data is maintained external to that entity.
Implicit to this change is the notion that an overworld map will be part of Gunmetal Arcadia, and indeed, that’s something I’ve been considering. I haven’t decided exactly what this will look like; it’s possible I’ll go for more of a “board game” sort of map a la Super Mario Bros. 3, but in any case, I do expect that individual levels will be connected via an overworld map. I’ll figure out exactly what this means as I get deeper into the roguelike design of Gunmetal, but some of the questions that I’ve been pondering are whether to allow backtracking, how many branching paths may appear, whether or not some branches are clearly labeled as easier or harder, and so on.
The next few weeks are going to be spent on some tasks unrelated to Gunmetal Arcadia, so I’m not sure what next week’s blog will look like — it might be a good opportunity to ramble about high-level design a little more as I did last month. Stay tuned!