Posted August 31, 2020 by Cheeseness
OoooooooOOOOOOOoooooh! A spooky update arrives!
Test build v0.0-27 includes a bunch of visual changes (most placeholder) and an in-game editor for creating alternative beat defs for existing music or beat defs for custom music.
If you're keen on keeping track of Darkgroove progress in more bite-sized fomat, I try to tweet and toot my work more frequently than I post builds!
The first half of the past month was primarily been focused around migrating tests/experiments to unified code as part of the main codebase. We've been trying to keep experimental things separate so as to not clutter up the core project - everything's in the same repo and the same Godot project, but having separate scenes that we can run directly that aren't included in what the player sees when they run the game gives us a bit more flexibility to try quick/hacky things out without introducing hacky code or potentially breaking existing things that we might want to keep.
The second half has been divided between getting the in-game beat definition editor up and running, adding further placeholder assets/visual representations, and refactoring/improving existing code.
The editor is mostly usable, and while the beat defs for the included track were originally written by hand by me as I eyeballed timings in Audacity and typed out beat defs, they've been updated and edited in the in-game editor, so in that sense it's ready for use.
There are a few caveats/known issues. If you're planning to use the editor, please keep them in mind!
Although it's never a good metric for assessing progress, and in this case, the codebase size has more or less halved over the past month, hinting indirectly at the level of refactoring that's been done. I've migrated a lot of previously duplicated code into base/super classes that individual variations can inherit from (the EntitySuper class stores things like time, type, and xOffset, while the EnemySuper class builds on that, holding common logic for movement, and lastly, individual enemy classes pretty much only define their type as part of their upstream constructor call (eventually they'll be where enemy-specific behaviours end up being kept for any enemies that require that). Similarly, EffectSuper defines some extra bits and pieces that are relevant to effects, such as duration and intensity. The nice part here is that there's always a super class that exposes all of the data that the editor needs to expose, so none of the end derived classes need to be instantiated for the editor, keeping things a little lighter.
I've also put effort into automating loading, with things like enemies and doodads no longer being hard coded, and instead being loaded at runtime based on the folder structure that's present. This is nice in that it means if I want to add a new doodad type, I just make a new folder in the appropriate doodad category path, save a scene with the same name as that folder, and it'll be in there next time the game runs without any further changes.
Depending on how things go, I'd like to look toward allowing entire scenes/scripts to be loaded from custom folders (similar to how custom music is currently handled). I wanted to do this for Hive Time to allow for use-made hats, but the workflow for creating a scene and attaching logic to it is awkward and convoluted for the style of modding I'd like to allow (ideally, I'd like to not require the use of the Godot editor, and just allow people to dump models and scripts in appropriately named folders and have the game assemble everything at runtime automatically). Modding is pretty low on my priority list for this project, but the benefits of being able to just drop stuff in from a production standpoint are pretty big, so if there's a way that I can easily leverage that into making the game more friendly toward modification/user created content, then I will.
On top of that work, I've also been working to simplify/tidy/modularise/make code more maintainable as I work on things. At this stage of a project, I tend to do a lot of iteration, adding, trying, changing, removing things as I rough out how things should work. I like to think of most of the code I write at this point as being like scaffolding or an armature that I can use to support other code I write, but which generally will be removed/changed as other, more refined work takes its place. For example, yesterday, I effectively wrote three implementations for multi hit enemies. Each successive one built on the knowledge and perspectives I'd gained from the previous iterations, and each one allowed me to focus on getting other parts of the game to work with the broad strokes concepts of multi hit enemies, meaning that although the majority of the multi hit enemy code I wrote ended up being removed/replaced, all of it still provided me with practical benefit.
Similarly, I popped large icons above enemies to indicate which action they're vulnerable to - this gives strong differentiation between enemy types, which is necessary now that horizontal position doesn't convey that any more. The icons are temporary, and in some respects, they might look like wasted work, but what they actually do is allow me to work on other things without getting bogged down in modelling new placeholder enemies, which ultimately saves me work. It also means that I'll have spent more time exploring how enemies mechanically function in the game before it comes time to do proper character design, and that's valuable too.
Last, but not least, I spent some time quickly slapping together a bunch of new environmental doodads that helped explore/refine what exactly it is we want from doodads, and give a little more breadth to the atmosphere that the placeholder environment suggests. Everything is meant to be dark/not so easy to see, which makes getting a screenshot hard, but I think the general sense of space is being conveyed a lot more strongly now.
Since we're now rendering a lot more stuff and optimisation isn't something we've been giving much attention to yet, I'm expecting that this build will show a performance decrease over the previous build, but that's how development goes sometimes.
I haven't been working on my own of course. preceding and alongside my work, Nemoder has done the first pass on the editor tools, getting something capable of generating a waveform visualisation, rendering the timeline, placing enemies on click events, and saving it all out to file before I came in to do a UI pass and add further functionality like click and drag, box selection, customisable guides, etc.. Nemoder also did the implementation on our current turn effects, tackling the parts that my tiny maths brain would be a lot slower with. So far, this has worked out well, as I was primarily occupied with Hive Time work early in the month, giving Nemoder time to lay the groundwork for work I'd be doing later in the month.
All of this work also means that the beat def format has changed a little. I've tried to maintain backwards compatibility for now, but I expect it to change plenty more before release.
18.17,basic,0.75 18.424999,effect,1,1.5,turn_right
Enemy beat defs now have a third field, which is their horizontal position (0.75 for what was previously the automatic position for "basic" enemies and 0.75 for what was previously the automatic position for "advanced" enemies.
Effect beat defs are time in decimal seconds, the word "effect," intensity in decimal arbitrary units, duration in decimal seconds, and then the effect name (currently only turn_left, turn_right, turn_up, and turn_down are defined).
Enjoy!
Full changelog: