I recently discovered the Svelte web framework. Its approach seemed quite interesting, so I decided to dive deeper and work through their interactive tutorial (which is a really well-designed learning experience).
It got me hooked.
I started simple and made a very basic note-taking app, which is literally just a bunch <textarea>'s slapped together. I've been using Tot on macOS for a while, so I wanted to have something similar on my Linux machines.
The FPS project joined the big pile of unfinished prototypes and I’m working on a new thing again.
It’s (supposedly) much simpler and it’s 2D. A non-traditional tower-defense game with roguelike elements (I could never get away without some roguelike elements).
Non-traditional part is a having a big focus on freeform tower positioning that affects and changes the path that mobs need to take to get to their target, as opposed to usually having a fixed path in traditional tower-defense game. I’ve been prototyping and testing this approach for a while and (at least for me) it adds a whole new level of depth to positioning and interaction with the map.
I have a bare-bone prototype already, including some essential pieces, like:
map interactions for placing towers
recalculating the paths mobs based on changes in the map
system for creating various map “actors” (i.e. towers and mobs) with different stats and actions
modifiers (upgrades) that can be added to towers to change their stats
timed status effects (buffs/debuffs) that also can be added to towers to modify their stats
Looks like I have all the basic building blocks ready, so next step is creating the initial set of towers and mobs.
I'm currently working on implementation of various trait effects for the player character and after going through a few possible methods to do this, here's what I came up with.
since I'm heavily using Godot's Resource classes for generating and storing all types of data for in-game use, I have a StatsRes class (i always add Res suffix to classnames if they extend the base Resource class) that serves as a container for base character stats like max health, move speed and so on.
in a similar fashion, i'm also storing traits as resources of a TraitRes class so that I can create new traits through Godot's visual inspector by simply creating and a new resource file of type TraitRes. In order to do that, the TraitRes class needs to export variables that need to be editable through the inspector by using a certain notation like:
# this will show a "Max Health" input field in the inspector
# that accepts integer values
export (int) var max_health := 100
[TO BE CONTINUED...] (actually, I never got back to it)
as planned, i tried to spend some time over the weekend planning my designs instead of programming... it didn't go well.
although i have some understanding of where to move, it's hard to formalize the direction for now for a few reasons: 1) i guess i'm not skilled in game design enough to be able to pre-construct an elegant solution on paper; and 2) i actually prefer designing from the bottom up.
by the 2nd point i mean it makes more sense to me to start shaping up various smaller parts and mechanics, make some simple implementations and try them out. some of them will feel right and most definitely will lead to more discoveries along the way. this is a more natural process.
so instead of thinking too much i decided that the game (in its current foggy vision of being a roguelike FPS) clearly needs some sort of character development. this immediately sparked a bunch of ideas on how it can be implmented and how other parts might work with it.
as I don't want to spend too much time digging into specific solutions, I came up with a rather simple trait-based system where the player can choose from a variety of traits that modify certain stats and maybe have some special effects like adding an extra weapon slot or allowing to see the exit on map from the start. The goal is to add gameplay variety where the player can tweak a bunch of variables at certain points in a single run and get different results.
i've already implemented the bare functionality for this, so next step would be integrating it into gameplay by creatign a bunch of initial traits and figuring out at which point during a game run the player should choose the next trait.
Last few evenings/nights/mornings I've been mostly working on random parts that were unfinished.
The weapon system is now fully in place using a state machine pattern, so now I can actually create all kinds of different weapons including projectile-based instead of only instant hitscans. That was fun to work on as I like implementing and using state machines.
I also made a very useful in-game debug panel that works in isolation. Every class can now have a "debug_info" dictionary that it updates with keys that I want to track and emits a globally defined signal whenever the values are updated. The debugger is just a separate autoloaded UI panel that listens to that signal and updates the UI on every change. This way I can track any debug info inside the needed class as just a dictionary and don't have to create one-off implementations to show it on the screen. It's been very helpful while working on the weapon state machine. It's worth spending time on custom tooling as it can save a lot of pain in the long run.
Yesterday I read an article by Derek Yu where he describes two types of "death loops" that people often get stuck in while working on games. Even though nothing i read there is new, it made me realize that I've been neglecting the work on actual gameplay for a while now. So I decided to hold off from spending too much on any non-core-gameplay parts for now. My "brain dump" column in Trello is overflowing with random gameplay ideas that I've been collecting and I want to process it to have an understanding of where to move. The plan is to spend some time this weekend on writing a rough outline of how I want the main mechanics to work and synergize.
Refactoring day. After wrapping up the initial work on steering AI, I decided to switch to something less challenging for a moment and refactor the weapon system. I don’t think this game will have too many weapons, but I want each of them to be distinct and a serve a specific combat situation better than others. This means I’ll need a highly configurable weapon creation system with various parameters affecting the behavior.
Technically, I decided to utilize Godot’s Resource classes for this: each weapon will be a resource with a bunch of parameters. This resource is then passed to the main Weapon class which handles all the setup internally from resource’s variables.
I’m done with the main parts of this already, but I still need to add ability to create projectile-based weapons, since currently all player weapons are basically instant hitscans. I’m also toying with the idea of creating homing projectiles now that I have the steering system in place, it might be fun. Once the weapon system will be ready, I’m planning to make enemies use it as well. So that some elite enemies can use powerful weapons and have a chance to drop them on death.
yesterday i spent most of the day tracking a weird bug with the physics of AI agents. that's the disadvantage of using a 3rd party library — if something isn't working as expected, you might spend hours hunting for the origin of the problem and trying to make it work. in my case the weirdness was the result of Godot engine defaulting to negative Z axis as "forward" for some of its built-in methods, while the steering framework I use expects it to be positive Z. the fix was a 5 min work, but tracking the issue took most of the day :/
i'm tired of working on AI steering at this point. as i mentioned before — vector math and physics isn't something i'm very good at. for now, the enemies have a pretty straigforward state machine that is easily extendable and can interact with the steering agent implemented in an enemy. so enemies can switch between following their target (player), slowing down when target is close, moving away when target is too close and so on... that's more than i need for now.
not much progress today as i didn't really get a chance to focus.
i've fixed some issues in the Agent's class state machine (i.e. enemies), but still struggling to get all the state transitions to work properly. thinking i'm gonna leave it as if for since they're not the top prio at the moment and get back later when i'll need to work on the navigation and pathfinding.
this is an experiment. i saw a similar log on the web and it felt like a great idea, so i'm gonna start one too. just planning to dump out my brain here by the end of day, if i managed to work on something that day.
so... happy with the result of work today. managed to finally figure out how to implement the godot steering AI framework for my specific use-case. not fully working yet, but that just needs execution and polish.
next up going to refactor all the AI movement and state machine code to use the new steering behavior, that should be now much easier to tweak and grow upon.