Preview v0.0-27 & v0.0-28
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.
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!
- Box select will add any entities that the box has covered to the selection regardless of whether or not the box currently contains those entities
- Multi hit enemy timing/placement can not be adjusted
- Horizontal placement (vertical in editor) can not currently be adjusted for existing entities
- Some input modes don't have custom cursors
- Click and drag movement with snapping enabled ignores small mouse movements, leading to the mouse getting out of sync with entity positions
- Snapping and guide frequency are in decimal seconds (future builds will likely have a % beat option)
- Auto scrolling when the track is playing in-editor doesn't have any buffer for when the play head is comfortably on-screen
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.
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).
- Added error output when cursor mode does something that it shouldn't
- Added temporary 'fancy' EntityType
- Externalised action type mappings out to json (not yet exposed to users)
- Added large icons above enemies as a temporary visual differentiator
- Refactored entity loading/handling to dynamically load based on EntityType named folders/scenes
- Added states to entities to track behaviour for multi-hit enemies
- Added EnemySuper to hold common processing code for enemy entities
- Made Manager::musictime persistent
- Added convenience functions for converting time to enemy movement distance to Manager
- Added initial push back behaviour for multi hit enemies
- Added editor representation for multi hit enemies (not non-first states can't be edited yet)
- Refactored doodad spawning
- Added doodad type specific positioning.
- Added doodad superclass
- Added automatic doodad folder traversal/loading
- Renamed tree doodad scene to work with automatic loading
- Added placeholder doodads for trees, shrubs, rocks, small rocks, path stones, mushrooms, fireflies, and moths
- Added TURN_LEFT, TURN_RIGHT, TURN_UP, TURN_DOWN effect types
- Added effect icons
- Moved editor beat def parsing to Globals
- Added effect handling for path turns/hills to Manager
- Added entity icons
- Added first pass on duration and intensity context menus for effects
- Added handling for placing entities on either side of the midline
- Added duration trail for effects in the editor
- Added cleanup for stray effect nodes in Manager when quitting
- Added EFFECT EntityType
- Added EffectType enum
- Added EnvironmentType enum
- Added DoodadType enum
- Refactored get_entity_string() and parse_entity_type() to no longer rely on hard coded values
- Fixed crash when entity isn't in reverse action mappings
- Refactored entity and action icon loading to use fallbacks
- Added EffectSuper class
- Updated included horsedemo2.ogg.txt to include xoffset values
- Renamed GhostType enum to EntityType
- Added EntitySuper superclass for ghosts, etc. to extend
- Moved time, xoffset, and type tracking to entity superclass
- Moved parse_ghost_type() and __ to parse_entity_type() and get_entity_string() as global static functions
- Renamed ghostlist to entityList
- Removed old type-dependent xoffset (fallback is still used when xoffset insn't present in beat defs for backwards compatibility for now - will be removed closer to release)
- Added xoffset parsing to Manager::setup_beat_sequence()
- Updated editor to use EntitySuper instances
- Updated editor to no longer use entity type derived vertical offsets
- Added credits
- Removed some prints
- Added editor zoom input mode (shortcut F3, left click to zoom in, right click to zoom out)
- Fixed editor playback button state not aligning with audio player play state when automatically playing after loading music
- Refactored waveform data saving/loading to store time for each peak sample
- Updated waveform data to be higher resolution
- Updated waveform drawing to be cached via a render texture for better performance
- Added importing input mode to be used during music processing
- Added special cursors for entity, move, and importing input modes
- Moved editor audio processing into _physics_process() for fixed time processing
- Replaced old pixel_time_multiplier magic number with zoom_multiplier now that everything is scale agnostic
- Added selected/non selected variants for action icons
- Added convenience lists for tracking reverse action type mappings, entity icon and action icon associations
- Moved gameplay controls from ui_right and ui_left to action_torch and action_sword
- Added keyboard nudging to editor (shift and alt as slow/fast modifiers)
- Added mouse dragging to editor
- Added support for selecting multiple entities in the editor
- Added support for click and drag box selection in the editor
- Added new entity icons
- Added selected icon variants for entities
- Added icons to editor entity buttons
- Added editor move button
- Added shortcut text to editor select and move buttons
- Added action icons to editor timeline
- Added checkbox for toggling action icons in editor timeline
- Hack workaround for cursor sometimes getting stuck in captured mode (possibly an engine bug??)
- Added editor playback button icons
- Moved editor images into sprites/editor
- Refactored visualiser ghost/tooltip detection to use sprite dimensions
- Refactored actionTypeMappings to hold an array for future entities
- Added auto snapping checkbox
- Updated type entry on editor entity context menu
- Added tooltips to type enties on etitor type context menu
- Added preliminary work on multi selection support
- Refactored editor time interval calculation
- Added tooltip to enemy/entitity buttons
- Added input mode tracking to editor
- Added ghost context menus to editor
- Optimised some editor node references
- Added hh:mm:ss.nn time formatting
- Added timeline slider
- Refactored editor layout
- Added editor nudging
- Added editor snapping
- Added editor popup for manual ghost time adjustment
- Added editor guide frequency and offset customisation
- Removed editor pause button and made play button a toggle
- Refactored entity editing
- Refactored current position marker handling
- Refactored timeline/waveform layout
- Fixed editor media_end() function not properly seeking to the end of the track
- Added keyboard shortcuts for playback controls (Space toggles play/pause, Home, End, Page Up and Page Down seek)
- Added keyboard shortcuts for input modes (F1 for select and 1, 2, 3, etc. for ghosties)
- Added dynamic ghost button generation based on existing enum entries
- Added auto scrolling on playback/seek
- Optmised some visualiser draw processing
- Added ghost placing and save option to editor
- Added another editor button for type
- Added visualizer tooltips
- Fixed potential memory leak
- Unified manual and WM quit handling.
- Restructured non-experiment scenes and resources into appropriate folders as described in the project outline doc
- Removed old experiments
- Renamed MainBeat to Manager
- Abstracted player-specific data/processing out to a Player node
- Added references to Player and Manager nodes to Globals
- Added track selector to main menu
- Repurposed settings track selector to be default track selection
- Fixed settings button not being visible when game is paused
- Moved attach and enemy type enums to Globals
- Fixed GGGGhost scene not using the correct ghost model
- Added load/save
- Added editor
- Added settings menu
Get Into Darkgroove Forest
Leave a comment
Log in with itch.io to leave a comment.