Thursday, May 20, 2021

Fading Light Devlog 1

Welcome to my current project, my second game, named Fading Light. I started working on Fading Light in November, roughly around the time I finished Containment Breach and it's now in a playable state, if an unfinished one. A lot of the names and terms are subject to change, including the name of the game itself. You can download and test out an early pre-release build (PC only, for now) from my Google Drive here. If you do test it out, let me know what you think! It's still incomplete in many ways but it is fully playable on its one map. I would also be happy to hear any suggestions, ideas, or bug reports you might have.

Fading Light is a reverse tower defense: you customize waves of units and the path they follow through the gauntlet of towers that the AI builds every round. Gameplay is split into distinct phases, during which you either prepare your wave by buying units, upgrades, and abilities, or you cast spells to assist them as they travel.

The idea has been floating around in my head for years, with the theme inspired by my recent games. I didn't want to make another sci-fi game in a row, so Fading Light is a fantasy game. Furthermore, it keeps with the theme of playing as the "monster," which also feeds into the reversal of the typical tower defense formula, by having the player's units be themed around fey and druids. The enemy towers are currently stone structures that could be of human make, though I'm interested in doing an art pass later on to add some flair and personality to them. The concept started life as a sort of fantasy solarpunk world with an ecological message, and though this may emerge later as I add polish, this idea is currently all in my head.

Development so far

The first thing I did was port over and rework my code from CB that handled target acquisition, bullet firing, and destructible units. I also started with the enemy patrol code and refactored it into a path-following script pretty quickly. Within a day or two I had units moving through the path and towers shooting at them, but to make it a game with interactivity I needed to start writing brand new code.

Right from the start I knew there were a few systems in Unity I wanted to learn how to use: Scriptable Objects and the Observer Pattern. So I set about researching these topics and implementing them as I went. In a nutshell:

  • Scriptable Objects are lightweight containers that hold data which you define once in the Unity editor and then can read later at runtime. They're handy for defining things like different types of units, weapons, power ups, terrains, etc. You have a generic base prefab that reads the data off the Scriptable Object and customizes itself based on what it finds. This saves time and space by reducing the need for totally separate prefabs for every different enemy type, for instance. It also makes IDing objects easy: just compare which Scriptable Object they're reading from.

  • I mentioned the Observer Pattern in my Containment Breach Postmortem. It allows you to write very self-contained and disentangled code by having objects called publishers fire off events that other objects called subscribers react to independently. Publishers don't keep track of or care about who subscribes to them, they fire the event regardless without needing references to the myriad of objects subscribing to them. You can think of an event like launching a flare into the sky: any observer can see it, what color it is, and where it is, but the launcher doesn't need to specifically notify any one observer to shoot the flare. It just does it and forgets about it.

I use these two systems all over the place in Fading Light, both because I'm deliberately practicing using them and because they are genuinely so, so useful. My code is still far from perfect but right from the get-go it was so much easier to expand and refactor scripts compared to CB. The code is just easier to read, write, and understand, especially a few weeks or months down the line if I need to refactor something. In coding your past self is usually your own worst enemy and you need all the help you can get figuring out what the heck you were thinking two months ago or whatever.

It was clear from the outset that Fading Light was going to require a much more extensive user interface than CB did, particularly during the Planning Phase when you are buying things from a shop and arranging them in a specific order. Unity's UI objects aren't complicated but everything about them works slightly differently than manipulating GameObjects in world space, which took me some getting used to. But once I got over the hump I found it surprisingly easy, if a bit tedious, to put arrange and hook up all the buttons, text fields, icons and slots, etc. Implementing drag-and-drop was a pain, and it's a system I'm still unhappy with so I'm dreading having to inevitably go back and refactor it to allow for dragging units from slot-to-slot (instead of having you sell and rebuy them to move them). But it works for now and has a decent enough if imperfect user experience so I moved on.

Currently, there is one static map that you can play on, but in the future I'd like to add procedural map generation to Fading Light. Likely this will take a very restricted form, but it should add some replayability and variance to the game. Failing that it will contain probably 10-20 handcrafted levels by the time it's finished, or perhaps some combination of the two. I will go into more detail on how this works in later devlogs as I'd like to chronicle my proc gen journey as I undertake it.

Coding the AI for Fading Light has also been an adventure. CB barely had any; enemies would patrol along their route or rotate in place until they spotted the player, then stop, pivot towards them, and shoot in a straight line. Truth be told, Fading Light's isn't that much more complex, but it's very different. Towers are easy: if they lack a target, they search for all units within their weapon's range and line of sight, then pick the closest one as their target until their line of sight to it is blocked. They shoot at their current target until they run out of ammo, at which point they lose their target and begin regenerating ammo. However, determining where towers get built took a bit of headscratching and iterating upon. The approach I've gone with is still somewhat naive, but it works okay.

How it works is that each round, the AI gets a budget of points. It then figures out what tower types it can afford with its current points and picks a random one from those. Then it looks at every unoccupied tower slot on the map and awards it a score equal to how many path segments are within line of sight and within the tower's weapon range or area of effect. Path segments that units have walked on in the last 3 rounds are weighted more heavily, and tower slots near other towers of the same type are considered less favorable (Frostbite Towers will almost never be built such that they overlap, because their auras don't stack). It then builds the tower on the slot with the highest score and repeats this process until it can't afford any more towers this round. Its budget increases slightly each round (affected by what difficulty is selected) and unspent points carry over, creating a little bit of variance from round to round. The only other limitation is that the AI knows which towers deal damage and which don't (currently only the Frostbite Tower), and it needs to have towers that deal damage on the map before it will consider building non-damaging ones. Otherwise you could get a map full of slowing Frostbite Towers and nothing that can actually destroy your creeps!

In the future I may look into deepening the building AI somewhat, for instance by telling the AI which towers synergize well and allowing it to build "bundles" of towers. However, not only is this more work, but I'm not sure it's even needed. The point of AI in a video game, after all, is not to actually win as often as possible, but rather to present interesting gameplay to the player. Some genius could code an AI that's brutally smart and beats almost every human it fights, but aside from people who specifically enjoy conquering very difficult opponents that will probably turn off the majority of players from the game.

Going Forward

I want to emphasize right now that Fading Light is not my "dream game," nor is it my forever project. I have a few big updates I want to give it before I shelve it and move on to other long-term projects and I fully intend to complete the game to my satisfaction, but this won't develop into a $20 Steam release or anything. I may charge $2-3 for it on itch.io when it's done, but for now it's purely a hobby project.

That being said, here is my high-level To-Do List, itemized in no particular order:

  • Add a map generator. This will be the subject of at least one devlog by itself, I imagine. I've done some research into procedural generation and although it is easier than I feared it's still something entirely new to me and will take a lot of work to get running. But if I can pull it off I think being able to press a button and get a new, unique map to play on will really boost the longevity and depth of the game. I expect this to be the biggest item on this list.

  • Add a story. Not so much with characters and dialogue, because I don't think this genre lends itself well to that. But more environmental storytelling that really sells the idea of invading humans destroying this magical forest and its denizens carrying out a last-ditch escape. I don't expect that I'll be able to work on this much until the map generator (and/or set of handcrafted levels) is done, since I won't know what maps will look like until then.

  • Add more content generally, referring mainly to types of creeps, modifiers, abilities, towers, and pickups. The game's skeleton is basically done, I just think it could do with a bit of fleshing out. I have to be careful not to go overboard with this, however. I wouldn't want to drown the player with too much choice or complexity, nor would I want to burn out trying to wrack my brain for 50 different creep types that are all unique, interesting, and balanced.

  • Do an art pass. This means looking at all the art I've made and touching it up. Adding animations to things that lack them; making the map look less monotonous and boring; making the towers more obviously distinct from one another, and so forth. I intend to add a cool background to the main menu and post-game screens, and maybe spruce up the UI with some vines and leaves. Art really does make your game "pop," both on a website and in players' memory, and having ugly or dissonant art will make a lot of people pass on your game even if they might really enjoy the gameplay or story. I don't think Fading Light's art is terrible right now, it just needs a bit more love.

Anyway, that's it for now; I'll see you in the next one. Thanks for reading, and if you play it, thanks for playing!

No comments:

Post a Comment

Post-Mortem: Protect & Serve

 A couple weeks ago I participated in my first ever game jam! This is something I've wanted to do for over a year now, but in the beginn...