Fields of Steel Stretch Forever

"And yet. I know so much, and care so little. Defeaned by chatter, weighed down by revelations - I am all, but wish to be none."

  • Terminal getting pensive about their quest

The Games Foxes Play

(complete source code - mirror | view all previous posts | play 0.4.3 online in browser on itch.io!)

Hiding behind a crevice to escape a passing-by patrol of robots in Cogmind, taking two steps forward and one step backwards to clear the Elven Halls in DCSS... There's a lot to like about sprawling roguelike maps, with their many twists and turns presenting opportunity for crafty adventurers.

So, when I looked at my own game, and considered the loop of "clear square room of all enemies" -> "move to next room" -> "repeat", I couldn't help but feel something was wasted. Due to the structure of the tutorial I initially built my game from, when a room was left, it ceased to exist and entered a state of stasis until the player visited it again.

I couldn't tolerate this any longer.

Fields of Steel Stretch Forever

This has been quite the neuron-frying rework, but TGFP now has full-floor, interconnected maps! The layout is still based off square rooms linked with each other, but the most important feature is that entities other than the player can now move wherever they please.

The implementation proved quite challenging. First, to properly generate a unified map, I randomly generate a 9x9 grid of "walls" and "floors" with no isolated floors, then pave each "floor" with a prefabricated vault, chosen at random among multiple possibilities. Finally, I scrape the data from each "vault" and build a single giga-room (>6000 tiles!) from the extracted data. I was expecting this process to turn my 128 MB VRAM, 8 GB RAM laptop into a miniaturized sun, but everything somehow remained perfectly fluid!

Then, to actually display the giga-map, I thought "let us just render every single tile and move the whole map around when the player moves". Bad idea. There was the miniaturized sun I was after.

Finally, I settled for a 30x30 grid of "projectors" which dynamically update every turn to reflect all tiles in range 15 of the player. It's just like DCSS - the player always remains at the centre, fully enabling any narcissistic tendencies the user may have!

Following this implementation, I struggled very hard to bring back the zooming animation from last week. Initially, it was skewed and caused an annoying lag spike at the end. I worked 5 hours to fix it, butchered my game completely beyond repair and had to undo all changes. Fun.

In the end, some performance testing revealed that the big memory-hog was the function assigning sprites to every single tile, including the black space between the rooms. All it took to fix the lag was a single line of code in the graphics engine: "if tile is not in play area, return".

Cyan Suns Burn the Horizon

The scope for the coming months is... a little imposing. I have a significant addition I wish to add to the core gameplay loop, and I also want to overhaul the pathfinding algorithms from basic-baby Greedy Manhattan Distance to something a little more appropriate for a 81x81 map. So far, the only things tanking my performance have been graphical issues - the back end has never caused any problems. From what I've read about the nightmare A* & friends can be, I expect this may change soon.

I sometimes regret a little choosing JavaScript to get started (but I think harder languages would have demotivated April 2022 me, even though I would be able to handle them now). I am getting frequently trolled by "undefined" types parasiting my data and coming out 5 minutes later to break everything. But, on the other hand, I am massively benefiting from the lack of compile times (offset a little UI element by 3 pixels and instantly see the difference!).

These next weeks will either be glorious or a train wreck. No in between.

Controlled Opposition

"What divides Unhinged from Artistic is not so different from what separates carbon from diamond. In each strike, the artisans of motion inject a part of their selves, expressing passion through pain as their canvas."

  • flavour text of "Polish Rage To Sheen", an Artistic Function that delays the execution of a spell until the next basic attack

The Games Foxes Play

(complete source code - mirror | view all previous posts | play 0.4.3 online in browser on itch.io!)

Well, I'll be honest. I had this whole giga-rework planned of my enemy placement system, with some wild ideas thrown into the mix - such as every single denizen of certain rooms spontaneously transforming into other types at certain intervals. I tried to get started on implementation last Saturday and Sunday, but all I did was stare blankly into my monitor as if the protagonist of my game had stolen my soul. Something was wrong.

My previous design idea was probably doomed from the start. Multiple annhiliated features already rot in the virtual graveyard that is my Git history, and I did not want another to join them:

  • It would have been tedious to learn all these enemy types, a major flaw of DCSS & co. with the "oh, you died to eels? just use a wand of flame! oh, you died to Nessos? just use a wand of polymorph!"

  • It would have taken dozens of hours to make, when it isn't even linked to the two core mechanics of my game.

I have to retain some humility and remember what my game is really about: the Axioms crafting system and the Harmony system. Everything else should derive from one of these!

It is after a deep introspection session while I was turned into a floor puddle and listening to new age music that a revelation came to me: Why do work when you can have the player do it for you? Tongue in cheek, I attest, but this design philosophy has served me well so far - I wasn't sure how to make interesting dungeons, so I allowed the player to design their own layouts, and I wasn't sure how to mass produce interesting spells, so I devised this entire magic-crafting system ("Axioms") that has now wormed its way into "Core Mechanic" status.

Controlled Opposition

First, I've cut down the amount of different enemies down to a measly 6. It was a tough choice choosing which would be the chosen ones, but I ultimately settled on a mix of some of my favourites, alongside some simple ones which I judged would make a good introduction to the game's mechanics. Each of these 6 representatives have been polished to fully utilize the game's Axiom system.

For example, Greedswept Felidols now contain the Axiom "ONDEATH","EGO","DEATHCLICK","CLICK","EGO","SUMMFELIDOL". This means:

  • ONDEATH: When this creature dies...
  • EGO: On the tile it stands on...
  • DEATHCLICK: And considering that all future CLICK blocks will be triggered by entities dying on top...
  • CLICK: Set down a trap on that tile, triggered only by death due to DEATHCLICK. The trap contains EGO, SUMMFELIDOL.

The Axiom ends there as CLICK is an endpoint. So, the Felidol has been reduced to glistening purple shards on the floor, grasping at the false life they once had... Until the player slays a different enemy while it is standing on the trap!

  • EGO: On the tile it stands on...
  • SUMMFELIDOL: Summon a new Felidol!

Thematically, the Felidol is grasping the soul of the defeated to reassemble itself. Technically, this Axiom is completely mutable, and nothing really stops the system from replacing "EGO" with, say, "BEAM" and removing DEATHCLICK AND CLICK, thus shooting forth laser beams of Felidol summoning. As the protagonist of my game would say, desire separates what is from what is not!

I concocted a lot of plans on where to bring this next, but as there is approximately a 10% chance that I will drop this entire idea and go back to the drawing board, it will be the topic of a future post. They say game ideas are a dime a dozen, but honestly, good ideas are surely worth more than that.

Until then...

Daydream Vertigo

Not only are Dreamscapes now directly accessible from the Soul Cage (the room they used to be in, the World Seed, will probably be removed), there is now a dizzying zoom animation for entering and exiting them! Initially, only the hologram would enlarge, which looked quite poor. Thank you #roguelikedev on the Discord for the much superior suggestion!

Screenshake effects have also returned, to my great amusement. Time to make some explosions!

I was really expecting this to be difficult - and was pleasantly surprised at how simple it turned out to be. It is giving me hope for some other eye candy here and there, such as less jarring transitions when passing through airlocks, or perhaps the ability to zoom in and out of the game view!