Blood, Sweat, and Kremlinks

Fall of 2013, America was a storm of marriage desanctification, selfies, and Grumpy Cat. Somehow I stopped twerking to “What Does The Fox Say?” long enough to have an idea for a game – a top-down twin-stick shooter. At that point HTML5’s canvas element had recently gained support in all major browsers. Adobe had dropped flash support for Linux and Android, and the writing was on the wall for other operating systems. As someone that had previously written his games in Flash and ActionScript, I was at a crossroads. I’d been writing ActionScript since the Macromedia days, and while I was also reasonably competent with JavaScript for web UI/UX, the process of using it to draw and animate on an HTML5 canvas was still “black magic” to me. A few HTML5 canvas/JavaScript game engines had sprung up already, but I’m the kind of person that really likes to understand things from the ground up. I made the decision to write my engine from scratch.

I’d written engines from scratch before, but they were generally for smaller, less ambitious games. However, my thinking was it’s a top-down scrolling 2d tile-based engine, how hard can it be? I envisioned gameplay similar to one of my SNES favorites, Super Smash TV. Rather than Smash TV’s chain of mostly-identical square rooms, though, I wanted a series of maps, and enemies with real pathing AI. Not just open arenas, but alleys and corridors; maps that would’ve been at home in 2.5d games like Wolfenstein or Doom but in a top-down two-stick universe. It would’ve been a linear, story-driven thing. Science fiction film noir – a space-faring bounty hunter that gets drawn into a web of murder, police corruption, and mad science. Shades of Blade Runner and Shadowrun but with blocky pixel graphics reminiscent of the 16-bit era. A whole alternate history reality grew out around it – a universe where the cold war went hot in the mid-80s. The name “Fistful of Kremlinks” is an obvious homage to Sergio Leone, owing to space western influences like Firefly. A “kremlink” was a blockchain currency developed in the former Soviet Union in the 2030’s by a mysterious, mostly-anonymous engineer. If you’re asking “how would you end up with a fistful of virtual currency?”, consider your character is a high-end assassin and many affluent people in this universe embed their private crypto keys on subcutaneous chips – a mental picture begins to form that gives the phrase “blood money” new depth. Each map would involve gunning your way through the baddies to uncover another piece of the story that would lead to the next location. In concept, it would’ve been my magnum opus. In reality, it was never finished.

Multiple Tile Layers, Multiple Z Levels, Parallax Scrolling

Front row seats

The engine was compositing several different layers of tiles in real-time. Some of this was to facilitate dynamic alternative or decorative tiles, kind of like decal layers over the main tile layer. Some of it was to cut down on Z layer calculations – for tiles that I knew would always be in front of the characters, I could place those tiles in a layer that always overlays the sprite layer and not have to calculate their Z height over and over. The most noticeable use, though, and the primary reason I did it, was for parallax-scrolling. In this clip, you can see I used it to add a layer of decaying ceiling tiles to an abandoned movie theater, placing the camera viewpoint above or inside the crumbling roof. It was a neat effect, but I think ultimately doing all that compositing in real-time in addition to the lighting effects is what really brought out the shortcomings in the way I was rendering and led to slowdown and framerate issues.

“Dynamic” Lighting

You are likely to be eaten by a grue

It may be a little grandiose to call it a lighting engine, but it did have a system that used masking to allow for ambient light changes on a map, and have things that glow and flash. It’s most noticeable on dark levels, like this asteroid mine. Here you can see the glowing headlamps on the miners and the muzzle flashes lighting up the cave. I also used it to give the player a little flashlight that swung around and followed the cursor. Pretty effective visually, but like I mentioned, compositing these lighting masks along with multiple tile layers really pushed the limit of what HTML5 canvas can do in real-time, tens of times a second, while the browser is also chewing on all the math to facilitate the gameplay.

Monster In-Fighting and Non-Enemy Sprites

Prison mining colony riot
Zombificating an innocent bystander

Sprites could have different dispositions toward the player and towards other sprites. In the first example there, the prison mining colony riot, the miners hate the player, but they also hate the guard robots. The guard robots hate the miners but will ignore the player – unless the player damages them. In the second example, the zombies hate both the player and the nearby civilians equally – they’ll gladly chomp on whichever is closer. If they kill the civilians, though, the civilians join the ranks of the undead. I’ve always really appreciated how much life is brought to a game world by in-fighting and different enemy factions. The idea that characters aren’t entirely defined by their relationship to the player but also to other characters in the world makes both the characters and the world more cohesive and interesting. What I didn’t consider is that also adds a lot of edge cases and unknowns that make balancing encounters and debugging enemy AI much more difficult. In the second example there, you can see that while one nearby civilian in the lower left (correctly) runs around panicked when he sees another civilian killed, the one closest (incorrectly) just stands there. It’s probably just a minor bug, a greater-than sign somewhere I meant less-than, but the time taken to debug and fix tiny problems like that adds up, especially when you get into interactions between non-player entities. At times it requires recreating scenarios that can’t be reproduced easily without writing a lot of purpose-built code that’ll be ‘thrown out’ after debugging is done. You put in a few hours of coding, and what you have at the end is an enemy AI that’s slightly smarter, but in a way that will probably be imperceptible to the player in almost every instance. It’s a slog. It’s the perfect scenario for unit testing, but the code wasn’t structured well for that since I didn’t plan for it in the beginning.

Game Over?

In addition to writing the code for the engine, I also drew – pixel-by-pixel – tens of tilesets for different environments and hundreds of frames of sprite animations. It may seem macabre, but the death animations are some of my favorites. Most everything else is just a short loop – walk down, walk left – but the death animations could be a little more extravagant. The tank pictured here was a mini-boss, the lighting in the animation when it’s defeated is some of my favorite pixel work I’ve ever done. I also recorded a soundtrack – I really loved the idea of dynamic soundtracks, different musical elements that are layered in real-time to build a musical backdrop that rises and falls with the intensity of gameplay. I had over thirty tracks of music that could be combined in various ways – thumpy ambient/industrial stuff that hearkened back to the kid that wanted to be Charlie Clouser when he grew up. But by 2017, after three years of working casually on it, I’d started losing momentum. It was more and more obvious that some bad development decisions I’d made early on were hamstringing the game engine. I spent less and less time on it, and eventually washed my hands of it completely. It’d been a learning experience and a fun hobby, but it’d never be a game. I tried really hard to get comfortable with that. Sometimes I succeeded. I’d learned so much in the intervening time, though, and I really loved the little universe I’d started creating. It seemed like a shame for all the work I’d done to never be used for anything.

Once More, With Feeling

A common topic of discussion among tabletop RPG types is the difference between intelligence and wisdom. One example I particularly like is “intelligence is knowing a tomato is a fruit, wisdom is knowing not to put it in the fruit salad.” An addendum is that constitution is the ability to eat the fruit salad with the tomato in it, but I digress. Another is “intelligence is learning from your mistakes, wisdom is learning from other people’s mistakes.” By that definition, I’d say I failed my wisdom check on what happened next. I learned nothing from famous vaporware like Duke Nukem Forever and Daikatana. I actually decided the solution was a new engine. In early 2019 I set to work on a blank slate – I kept all my assets, but the engine was going to be rebuilt from the ground up. That was the decision that ushered my project from development purgatory into a personal development hell. In theory, I knew all the things I’d done wrong the first time and could go back and do it right the second time. In practice, starting from the ground up killed my remaining motivation, and doing it “right” just illustrated for me how much more I’d bitten off than I could chew. This was a project that either needed a team of more than just me, or should’ve been built on existing open-source libraries. I toiled for a few months on my rewrite, but another factor is that the realm of casual games changed a lot between 2014 and 2019. Browser-based games aren’t the rage they were in the era of Cookie Clicker and Kingdom Rush. HTML5/Javascript ended up not being a direct replacement for Flash/ActionScript – instead things went more mobile – a browser-based keyboard and mouse game isn’t where casual gamers are anymore, they’re on mobile platforms with touch controls. In response, casual indie games are increasingly built in engines like Unity that make it easy to play games on whatever platform the player prefers, with whatever controls they have available. By 2019, my all-Javascript in-browser game was starting to feel like a relic – in a post-Flash world I’d zigged Betamax whereas everyone else zagged VHS. As of today, the second engine is even more unfinished than the original one was. I got fed up, I didn’t even look at it for over a year.

Bring on the Carnage

As of now, I’m still undecided if this blog entry is a game announcement or a postmortem. I have made peace with the idea that my browser-based space saga will likely never see the light of day. The setting may be used in future projects, and I may eventually tell the story in some other way – maybe a game, maybe not; if it is, I won’t be writing my own engine this time. But I did think it was kind of a shame I developed a game for over five years off-and-on and didn’t have anything playable to show for it. An idea stirred – I had created a map that was just a square arena, a la Smash TV. It was essentially my “is it fun?” sandbox – when I needed to tune weapons or enemy behaviors, I ran the “Arena of Carnage” map as a way to playtest. The simple map means a lot of the more intricate challenges in collision detection, line-of-sight, and enemy pathfinding could be sidestepped. This small one-room map with flat lighting also ran fairly well in the old engine, as it was, without any further optimizations. I was struck with the idea of releasing “Carnage Mode” as a standalone game – significantly less ambitious than my original vision, but nearly finished already. So I went back to the old engine, spent a couple weeks tying up the loose ends, and the result is Fistful of Kremlinks: CARNAGE MODE – available for free on itch.io.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.