I was ambitious in my goals last week, but it’s paid off. I’ve got a preliminary title screen, scenario selection, and a whole lot more under the hood.

I started by moving away from JSON Schema. Sounded good on paper, but I found myself in an anti-pattern, fighting the Godot way of doing things. I have now formally structured into classes (which I had before) and Godot-managed resources (instead of dynamically creating them at runtime).

I added some more effect types, including piercing, allowing me to create a new opponent. Effect resolution is cleaner. I brought back recycling as a device. There are visual representations of the stacks, like the deck count, spent, and discard. There’s a generator device, the first passive buff.

One of my goals was to introduce pauses in animations, and I didn’t succeed, but I made a lot of progress towards them. Part of the problem was how things were getting queued and who owned what queue. There was a global queue of tasks, but if you queued up an effect animation and the combatant was destroyed before it would play, the game would crash. I’m taking different approaches moving forward, which includes making nodes responsible for their own animations, leveraging AnimationPlayer for queing, and a more formal state management system.

After doing some research, I had ended up writing my own state management system, and it was pretty robust. There were signals and hooks, transitions, the whole nine yards. It was clean, but there was a lot of overhead, and when I wanted to reuse what I had, I researched what alternatives there were - again - now that I was more familiar with Godot.

Godot State Charts solved many of the problems I was having and provided me with a cleaner foundation. I tacked it onto Cards, which made them easier to manage. Then, I tackled the overall game adjudicator. Talk about working on the engine to work on a lightbulb; it’s like I had completely disassembled all the engine components and dumped them in the driveway. The refactor took a solid chunk of my weekend, but it included an ah-ha moment when suddenly the game started compiling again and it just… worked. That felt really good.

I’ve relaxed some of the tight coupling I had between the frontend and backend and better compartmentalized the logic. Now, the frontend is listening for specific exit and enter events and is responsible for handling how it reacts to each, rather than the back-and-forth “are you ready?” “I’m ready” dance I had.

With that out of the way, I implemented scenarios, along with a UI for selecting scenarios. This is paving the way towards play testing.

I also redid my focus navigation system (another reinvented wheel); I kept Controller Icons in place, but focus is now handled completely natively (with some help). That also meant redoing how collisions worked, so no more Area2D and Control refactors.

I think the video speaks for itself; the game is feeling more coherent. None of the meta aspects are in there, but I’m spending the up-front time with the core game loop. If that sucks, who cares what the plot is?

This week, I need to implement opponent sequence offsets, a passive shield device, a third opponent type, damage amplifiers (instead of mutating cards), and I’ll take another swing at animations (attack, hit, dodge is a good start). If I’m successful at the animations, I’ll try some preliminary sound effects.

It’s not done by any stretch of the imagination, but it’s looking more like a Game, and that feels good.