Having spent essentially my entire Thursday writing code, I felt like doing something completely different on Friday. I had a mental image of cartoony rendition of Vireo jumping and striking a slime, and I wanted to see whether I could capture it.
I started with a quick notepad doodle and went through a few iterations of scanning, printing a light image I could trace over, refining, and repeating. Once I was happy with the shapes, I scanned it one last time and traced over it with vector shapes. I made a few more changes to the shapes once it was in that form, replacing the pointy edges of the sword with rounded ones and shifting arms and legs around to look a little more natural.
The design and colors were based roughly on the painting I did earlier this year for the promotional flyers, with a few superficial differences. As I talked about in a video a couple weeks back, I don’t consider myself an artist, and part of that is that I don’t really do character concepts in advance, preferring to make things up as I go. So it’s nice to have a few (mostly consistent) references for my lead character now.
Having already been through the whole process of sketching, refining, converting to vector, and coloring for Vireo, the slime monster went substantially faster.
I don’t really know what I’ll do with these characters yet. I’m not happy enough with it to make it my cover art, probably, but I might paint in a backdrop at some point and maybe it can be a wallpaper for the Steam trading cards system or something.
I made some extensive changes to my synth tools back in June, but I hadn’t had much of an opportunity to put them to use until this week, when I finally wrote my first complete piece of music using these new voices. I’m super happy with how it turned out. Take a listen:
On a subjective level, I think this piece has a really strong hook, but even from a strictly technical perspective, there’s so much more going on here than what I was capable of doing when I wrote the music for Super Win the Game. I had no support for different instruments or voices in that game; I could set the duty cycle of the pulse waves per channel, but that was about the extent of it.
For Gunmetal Arcadia, I’ve leveled up my tools to allow more expression while still staying roughly within the limitations of the 2A03 sound chip. I’m still limited to the usual four channels, but I can author a variety of different instruments that may be played on each channel. (I’m ignoring the DPCM channel for now, but that may change at some point if I decide I really need some good drum samples.)
In total, there are seven different instruments in this piece. The lead voice was my attempt to recreate the sounds of Zelda II‘s temple theme. It is a pulse wave with a 12.5% duty cycle and some pronounced vibrato.
The descending toms are a fun one. These are played on the triangle wave channel and are created by doing a very quick pitch shift from a full octave above the target note. These are typically played over the same noise channel bursts that I use to approximate kick and snare sounds. Because these occupy the triangle wave, they are mutually exclusive with the bassline, but that didn’t really create any problems on this particular piece.
I experimented a little with the bassline in this tune, as well. The volume of the triangle wave can’t change, which limits its versatility compared to the pulse waves, but I tried to give each note a little bit of a punchier sound by again doing a quick pitch shift. This one is much faster than the tom’s, and it creates a sort of hard blat on the attack. It’s a sort of digital, synthy sound, not terribly natural, but it’s at least a little more interesting than a vanilla triangle.
The sort of creepy sounding swells in the first part of the tune (the “verse,” as I tend to think of these things are following a pop song verse-chorus-bridge structure) use pulse width modulation, dynamically altering the duty cycle of the pulse wave to create a sort of “swirling” sound.
Moving on to game work, I’ll start with a quick thing from a little over a week ago that didn’t make it into last week’s blog.
I have no plans to include the sort of fully submerged swimming bits like in Super Win the Game, but I did think it would be useful to have some swampy shallows like in Zelda II, something that can impede movement and create tension.
When I first set up the Gunmetal Arcadia codebase, I nuked all the swimming code from Super Win, so I ended up selectively bringing back little bits of that.
Super Win defined two different types of fluids: water and “toxic” (a catch-all for acid, lava, or anything else requiring an additional powerup to enter safely). I haven’t yet brought over the code related to toxic swimming, as I’m not sure whether this will apply to Gunmetal, and I’d almost certainly want to represent it differently if it did. I can imagine a scenario where I might want Metroid-like lava that inflicts damage over time. That feels like a more useful alternative to the instant death lava pits of Zelda II, as I already have a few instant death opportunities in Gunmetal.
I was hoping to create two types of flying enemies this week, as I tweeted in advance of the work, but ultimately I only had time to do the first. (Whenever I get around to it, the second will be something akin to the bats in Zelda II, something that hangs on the ceiling, only dropping to attack when the player gets near.)
For this one, tentatively called the “hoverfly” and using a placeholder asset that I previously used for my Medusa heads, I disabled physics (gravity) and decoupled horizontal and vertical movement. Vertical motion follows a sine wave, not unlike the Medusas, while horizontal motion is based on the distance in x-coordinates between the hoverfly and the player. It accelerates faster when it is far away, but its maximum velocity is capped to prevent it from reaching ludicrous speeds, and it is only allowed to turn around once it is a certain distance from the player, so it can never hover directly overhead. This forces it to strafe back and forth, and in conjunction with the bullets (fired only when it is facing the player), this feels like a good enemy that can create tension when used in conjunction with other, more immediate threats.
This was my first case of aiming shots at the player that aren’t affected by gravity. I previously discussed the case of shots that are affected by gravity in an earlier blog, and I mentioned this case in passing. It’s a simpler problem, but one that I hadn’t yet had cause to implement.
I already have ladders for facilitating vertical movement (and have had them for nearly the entire development of this game, going back to last December), but there have been a couple instances in my test maps where I’ve really wanted elevators for one reason or another.
Fundamentally, this didn’t seem like a difficult problem. I already had moving platforms in Super Win; the big difference here would be that I’d need to alter their movement based on the player’s posture: crouch to move down, look up to move up.
Where this got a little trickier is in how my collision system handles collision response.
When you take an elevator up, I have an invisible blocker sitting at the top of the shaft that only the elevator itself can collide against. It hits this thing and stops and the player disembarks. The problem I was encountering was that, even though the elevator would appear to be flush with the adjacent floor, the player would get stuck on the corner and would have to jump to leave the elevator.
I knew exactly why this was happening as soon as I saw it. My collision system defines a small value as the thickness of all collidable surfaces. (To provide a sense of scale, this is 0.015 pixels in Gunmetal Arcadia.) In practice, this means that in normal cases, colliders should always stop 0.015 pixels away from each other, but they are able to correctly handle colliding anywhere within this buffer space. Once they are actually physically intersecting each other, no collision result will be produced, and the objects will phase through each other. This helps to account for floating point imprecision, but in this case, it was also creating a bug. The elevator would stop 0.015 pixels below the adjacent floor, and the player would catch on that tiny edge.
My fix for this ended up being a bit of a one-off hack, but given how unlikely it is to encounter another bug of this sort, I didn’t feel like a more general solution would have been appropriate. The elevator gets a callback when it collides with something, and in response, it rounds its own position to the nearest integer (which in this case also means the nearest pixel). This makes it flush with the adjacent floor so the player can walk safely between the two. It also puts it flush with the invisible collider, as close as it can possibly be without phasing through.
Since I’m dealing with axis-aligned (and frequently integer-aligned) bounding boxes, some of these systems are perhaps a little aggressive for what this game needs, but it’s never been my goal to support 2D platformer games exclusively, so it’s important to build with other use cases in mind.
Finally, I checked off a longstanding TODO and brought over some screen shake stuff from Super Win. My biggest use case was for bombs, but I’ll probably also use this for boss death effects and maybe one or two other things. I’m not really a huge fan of the proliferation of overblown screen shake among indie games recently (yes, juice it or lose it, but maybe show a little restraint?), so I’ve tried to keep this fairly quick and conservative. It’s a little difficult to tell in the animated GIF below, but the shake is also quantized in time, only updating every two or three frames. This gives it an interesting sort of “chunky” feel that, to my eye, is a little more authentic to NES games and feels more stable than wild rubberbandy screen shake.
A couple last things. I’m planning to take some time off for paternity leave starting in another week or two. I may still be working on the game when I’m able (I mean, that’s kind of what I do for fun), but I can’t make any guarantees as to what my blogging and video production schedule will look like. If nothing else, my Twitter should stay active.
Sometime in the extremely near future, I’m also going to be putting together a first draft of materials for a GDC talk next year, so I may devote a video log or two to dry runs of this material to get comfortable with it and solicit feedback. Stay tuned!