1. Rhythm Quest
  2. News

Rhythm Quest News

Devlog 80 - Calibration Rework

[p]Progress continues on doing the easy/hard charts for the remaining levels that I've made so far, but I took a detour for a bit to work on something more important that I've been putting off for a while -- redoing the audio latency calibration flow.[/p][h2]The Story So Far[/h2][p]Rhythm Quest is a music game that does its best to Do Things Right when it comes to audio synchronization, even doing things like prescheduling jump/hit sounds by default instead of playing them in response to player actions. Of course, some sort of audio latency calibration system is needed to measure the difference in the delay of input/video display versus the audio output that is being used by any given player.[/p][p]The calibration has gone through a number of different forms over time. Here's a really early version that was needlessly confusing and had the player set the audio offset manually for no good reason:[/p][p][/p][p]
[/p][p]I realized at some point that =that= wasn't really going to work well, so I fell back to something simpler:[/p][p][/p][p]
[/p][p]And then there's this "rotating circle path" visual that has been in the demo for a while:[/p][p][/p][p]
[/p][p]I've known for a while that this needed a rework (honestly, the earlier/simpler version was probably better). I had various issues that I needed to solve...for example, I had the "beeps" create a melody to go along with the background music, but players were getting confused at which beeps they were supposed to be following. The whole circle path thing was "cool" but visually confusing and I don't think it actually helped many people understand what they were supposed to do. When I watched some people go through the flow, they were off-beat to the point that it would have been better if they =hadn't= gone through any sort of calibration process.[/p][p]This was something that I had been mulling over for a while (user experience design is hard!) thinking about how to do it effectively. I also did some research into how this is handled in other rhythm games -- unfortunately, a lot of it ranges from bad to worse. The flows I saw were either really bad (even for experienced users), or at the very least not easy to understand for the average layperson. I was beginning to wonder whether I should just not even prompt people for calibration at all and let only advanced users do it by drilling into the settings menus? That didn't feel right, though...[/p][h2]Opt-in Calibration[/h2][p]Thinking about this, the first thing I wanted was to give people a good and intuitive litmus test for whether they =should= recalibrate their audio latency or not. Before I was using flashing squares for this, but I wanted something less abstract and easier for people to see, so I built out this screen using an animation of a drum being hit:[/p][p][/p][p]
[/p][p]Hopefully this is much more clear, as it provides a snappy visual and also illustrates what the player should be looking/listening for to see if they care to change things.[/p][h2]Drum Animation[/h2][p]Drawing the drum animation was a fun little project. I obviously wanted something that clearly looked like a drum being hit, but it was also important to make sure that the exact moment of impact was highlighted. There's a brief flash that happens with the outline and other colors to demarcate this:[/p][p][/p][p]
[/p][p]I used a big motion smear, because there can't really be anticipation frames for this animation (I'm using it for the auto calibration flow as well) -- the drum stick needs to hit immediately on the first frame. And then the squash + stretch of the drum itself not only makes the animation more "lively", but also serves to create a visual "moment" that your eyes can distinguish for the moment that the drum is getting hit.[/p][p]Next, I needed to build the automatic calibration flow for if you say that the sound seems too early/late. This one is relatively straightforward -- this time the drum reacts to your input. There's a little progress meter on the bottom to solve a problem with the old calibration flow (it wasn't clear when it was going to be finished), and I even try to give you a rough indication of how consistent you were at the end.[/p][p][/p][p]
[/p][p]One little interesting quip you might have about this screen is that every system has not only some amount of audio output delay, but also a delay inherent in receiving and processing input, and having the result of that input become visible on the display. If you watch the animation of the drum as you tap, you might actually time your taps slightly earlier, so that the drum animation matches the audio, instead of tapping exactly when you =hear= the audio.[/p][p]I think this is okay, though. If players unconsciously (or consciously?) time their taps a little early in this way, that will probably be a tendency that they carry over into the game as well. And experienced rhythm game players who want to rely primarily on the exact audio timings may already know that the most accurate way to do this sort of test to achieve that outcome is to close your eyes or not look at any visuals at all...[/p][p]After calibrating, you get this screen where you can check your work, and the option to adjust it manually:[/p][p][/p][p]
[/p][p]I like this "choose the drum animation that looks best" approach as it provides a simultaneous side by side view of what different calibration settings look like, as opposed to most other flows I've seen (including my own) where you kind of just have to adjust a number while looking at one thing.[/p][p]
[/p][p]That's it for this update! There was a little more work involved in getting this all fleshed out, and getting the drum audio (it's just a pre-mixed separate version of the music loop, I don't schedule each drum hit on the fly) to play correctly; for example there's a completely different set of audio that plays in-game when you're in the pause menu and I needed to add the drum-sounded versions of that, too. But it's all working properly and this should be going out with my next patch release! I'm excited to finally be checking this one off (for now...) because first-time user experience is always important and this was definitely something I needed to address and iterate on at some point.[/p]

Devlog 79 - Hard Charts, Settings Tweaks, and More

[h2]Easy/Hard Difficulty Charting[/h2][p]I've been quietly plugging away making the easy/hard mode charts for all of the existing levels. Back in June I got done with recharting level 4-1, but since then I've gotten through another 7 levels and am now finished with those additional charts for level 5-3, plus some of the bonus levels![/p][p]Since everyone loves seeing videos, here's one that demonstrates some of the harder patterns in action. Some of these later levels are getting quite tough![/p][previewyoutube][/previewyoutube][p][/p][p]I especially appreciate the patterns where the ghost enemies jump forward into grouped sequences of flying enemies, like in this sequence from level 4-5:[/p][p][/p][p]
[/p][p]The quick pattern of hold - flying enemy - release has been a really common pattern in the hard difficulty charts. In level 5-2 it gets enhanced to feature green combo enemies at the start:[/p][p][/p][p]
[/p][p]In the normal difficulty, sixteenth-note rhythms aren't introduced until the yellow ghost enemies in level 6-1, and rapid sixteenths aren't used until level 6-3, but in hard mode they start showing up in level 5-3. This was both the point at which I was having trouble making things any harder without using sixteenth rhythms, and also a point in the music where it just made sense to throw them in:[/p][p][/p][p]
[/p][h2]Basic/Advanced Settings Split[/h2][p]In the last devlog I went over my big rework of the settings menus so that everything is available in one unified/paged menu:[/p][p][/p][p]
[/p][p]After a few weeks of actually using this new menu, I found that while it was great for exploring the plethora of miscellaneous options, I actually found it a little tedious for doing common tasks, like toggling auto play or changing music speed, etc. It helps a =bit= that I added page up / page down bindings to flip through the pages quickly (alternatively, you can use the mouse wheel or gamepad shoulder buttons), but I didn't necessarily want to rely on those.[/p][p]The new iteration is a hybrid approach, where I have the most common options in a basic menu format like before, but the "Advanced Settings" button drops you into the paged version where you can access all of the more complicated stuff:[/p][p][/p][p]
[/p][p]Hopefully this approach will combine the best of both worlds, though I'll have to sit with it for a while before forming a new opinion of it.[/p][p]
[/p][h2]Editor Work[/h2][p]I totally broke the level editor a while back when I was doing my big refactor where backdrops and tilesets were specified per checkpoint instead of for the entire level. I've since gotten the editor working again, and turned the backdrop/tileset dialog into a per-checkpoint tool:[/p][p][/p][p]
[/p][h2]Screenreader Fixes[/h2][p]I did another pass on screenreader fixes and support, including making the new advanced settings menu work with screenreader navigation, fixing the level 1-1 tutorial. There was also a fun bug where I was trying to disable built-in screenreader support on Steam Deck, but I was calling that API incorrectly, resulting in a completely different bug where screenreader functionality was broken on Windows if you had a screenreader running...[/p][p]There was also a screenreader issue on Windows where unicode text wasn't being encoded properly, leading to something like "你好" being sent to the voice synthesis as "ä½ å¥½", which was of course unintelligible. I somehow managed to make the appropriate fix to the C++ side of the accessibility plugin that I'm leveraging, along with pulling in code that lets you switch the voice used for the speech synthesis (only works if you have that Windows language pack installed...), and even fixed a race condition.[/p][p]The basic settings menu will also show you a quick shortcut for Accessibility options if you have screenreading enabled or have one running:[/p][p][/p][p]
[/p][h2]Performance Optimizations[/h2][p]I don't have any fancy stuff to talk about regarding performance, mostly just a lot of little things here and there that I took care of. For example, I've completely ripped Unity's animation system out of all of the obstacles in the game and am manually controlling each sprite frame using my own implementation (those animations are quite simple anyways). There were some other random things here and there -- caching some variables here, changing out a data structure there.[/p][p]One other thing that I noticed performance-wise was that the in-game settings menu was struggling to render efficiently, because there are a whole bunch of big transparent dialogs layered on top of all the actual gameplay and backdrops that have to already be rendered in the background. This was especially bad on systems like the Switch, where fillrate and overdraw (having to render a bunch of different layered transparent things on large swaths of the screen) was already an issue.[/p][p][/p][p]
[/p][p]Except...when the settings menu is being displayed, the game is paused and nothing is moving! So there's no reason we need to keep re-rendering the backdrops every frame, we can just turn off the backdrop cameras and updates (except for special cases like when you toggle certain settings) and save on all that rendering time.[/p][p]There's actually something else really big related to performance that I forgot to mention (or even think about) last year when I was doing a big refactor on how backdrops are rendered:[/p][p][/p][p]
[/p][p]The big change I made was that I composite all of the backdrop layers into a temporary texture first, and then draw that final result onto the screen. This might seem like the same amount of work as before (or actually one additional step), but there's one important optimization that past me made: the temporary texture is sized at 1x (no pixel upscaling at all). So if you're playing the game at 1920x1080 (which by default uses a 3:1 pixel ratio), the temporary backdrop texture is actually only 640 pixels wide! Rendering at 33% dimensions means we only need to render 1/9th of the pixels as we originally did, which is huge for performance. It does mean that we lose out on subpixel backdrop scrolling, but that's something that I honestly wasn't a huge fan of to begin with (subpixel scrolling is still supported elsewhere).[/p][p]With all this done, I'm happy to report that the game runs smoothly on Nintendo Switch, even in the later levels where I've got many backdrop layers overlaid on top of each other. Hooray![/p][p]I've also optimized level load times...this was a funny one as it turns out that the grass (!) in levels 1-1 and 1-4 were slowing down ALL level load times (d'oh!). The grass got added to those two levels about four years ago, and I guess at that time I somehow thought that I needed the grass to be dynamically generated by spawning many different small patches of it because otherwise it would look too patterned or something? Or perhaps that was how I solved the issue of how to place grass on slopes? (make lots of small short patches of flat grass across the entire slope)[/p][p]So I had code that spawned a ton of different grass objects at level generation time...and unfortunately, because I had refactored the level generation to use "universal" tiles that supported transitioning to =any= tileset for every level, this happened for every single level load, not just levels 1-1 and 1-4. Well, the grass is no longer dynamically spawned, it just tiles statically and I just made some sloped grass graphics that are super duper straightforward. Not sure why I didn't go with this solution initially, but...there you have it.[/p][p][/p][p]
[/p][h2]Respawn Markers[/h2][p]Because I was already doing some performance optimizations on the song density chart in the level browser, I had a little fun and the game now keeps track of where you died in your fewest-deaths run, marking those with little red "X"s in that chart.[/p][p][/p][p]
[/p][p]This is just a small little throwaway feature at this point, but maybe I could do something a little more fun with it at some point, like after every play show you a more exciting visual animation of all of the times you died. Not really something I want to sink a bunch of time into right now, though.[/p][p]
[/p][h2]And more...[/h2][p]I meant to get this devlog out earlier but kept on working on actual development instead of writing about what I had done so far. I suppose that's not really a terrible thing, probably more efficient for me to spend time actually working on the game instead of writing about it after all. There are a bunch of other random things that I also tackled since my last update 3 months ago (did you know that the values you get from scroll wheel input are completely different on Mac and Windows, and depending on whether you use a trackpad or a mouse? Or have inertial scrolling disabled? Fun...), and I also did a bunch of Steam Deck-specific fixes, but that's all that I'm going to write about this time around. Hopefully I can continue to make good progress through the remainder of the year![/p]

Rhythm Quest Demo v0.38.0 Released

[p]The Rhythm Quest Demo has been updated to version 0.38.0.  This update includes a rework to the settings menu organization, as well as many other fixes and improvements.[/p][p]Full changelog:[/p]
Version 0.38.0
- Split settings into basic settings and advanced settings menus
- Fixed some coin sfx playing even when disabled
- Fixed doubled input bug when using steam deck or certain other gamepads
- Fixed broken jump inputs when using steam deck touchscreen
- Fixed crash/lockup on level browser screen
- More robust handling of device suspend/pause events
- Better load time / more efficient grass for level 1-1 and level 1-4
- Fixed y-axis scaling in level browser density charts
- Performance enhancements
- Level load time improvements
- Density chart now uses magenta color for 300-360 notes per second
- Added failsafe to automatically trigger respawn if y position is too far off
- Fixed inconsistent beat pulsing for some in-game menus
- Respawns (for best runs) are now tracked in save data and displayed on density charts
- Shortened "Perfect" text in level select list
- Compacted ui elements in level select list for low width aspect ratios
- Give more space to right half of level select list
- Allow variable line width for level select descriptions to prevent overflow
- Fixed behavior when changing music speed while unpausing
- Fixed accessibility audio cues using wrong volume/audio bus
- Fixed accessibility audio cues always being panned to one side
- Fixed broken accessibility audio cue for jump release
- Add audio cue setting for jump hold + attack
- Fixed screenreader navigation for advanced settings menu

Rhythm Quest Demo v0.37.2 Released

[p]The Rhythm Quest Demo has been updated to version 0.37.2.  This update includes some major fixes to accessibility/screenreader functionality, as well as UI tweaks and other fixes.[/p][p]Full changelog:[/p]
Version 0.37.2
- Adjusted default pixel clamping behavior to allow for "subpixel" scrolling
- Added pixel clamp option to restore previous behavior
- Finally (?) fix sprite clamping artifacts causing horizontal/vertical lines/gaps
- Fixed level generation bug causing shifted/overlapped spikes
- Fixed character disappearing on world transitions in level select
- Fixed odd menu transition between first calibration and level select
- Fixed settings menu navigation bugs
- Tweak darkening effect for settings menu
- Fixed minor issues with level select UI
- Performance improvements for some UI screens
- Fixed tablet mode blocking mouse/keyboard inputs
- Add ability to page through settings screens using pgup/pgdown/scroll wheel
- Fixed and improved screenreader functionality for settings screen
- Fixed and improved screenreader functionality for level select screen
- Fixed and improved screenreader functionality for difficulty select screen
- Fixed and improved screenreader functionality for level browser

Rhythm Quest Demo v0.37.0 Released

[p]The Rhythm Quest Demo has been updated to version 0.37.0.  This large update includes a ton of bugfixes and some new functionality, including a brand new settings menu.[/p][p]Full changelog:[/p]
Version 0.37.0
- Replaced "Settings" and "Mods" with new unified settings menu
- Faster "Restart Level" without reloading entire scene
- "Start Game" now skips difficulty selection
- Full difficulty select menu now accessible from the level select screen
- Fixed incorrect ramp placement for level 1-1
- Fixed missing level 1-3 water effects
- Added level 1-3 water effects to level select menu
- Fixed level 2-2 flight zone speedup
- Adjusted camera tracking - added camera height smoothing
- Fixed broken diamond indicators for ghost enemies
- Fixed input timeline hold indicators on subsequent level loads
- Correctly despawn input timeline markers when warping in practice mode
- Fixed music sync issue when pausing before first beat of a song
- Added ability to skip/quicken main menu transitions with an additional press
- Added setting to enable auto play but disable saving progress (Jukebox mode)
- Fixed track preview not following track vertical position
- Removed initial calibration prompt and automatically start calibration unless skipped
- Fixed navigation keys/buttons triggering calibration inputs
- Fixed auto play text being hidden behind tutorial prompts
- Fixed auto play text not being shown in practice mode
- Added experimental support for tablet PC input (Settings -> Controls -> Tablet Mode)
- Remove audio fading behavior when quick scrolling through song select menu (delay start instead)
- Allow clicking directly on non-active items in song select menu
- Added clickable/draggable scrollbar to song select menu
- Fixed incorrect pageup/pagedown behavior for song select menu
- Decrease outline thickness on smooth font
- Fixed mouse clicks on bottom of screen not registering even when practice mode is disabled
- Tweaked pixel snapping behavior for many sprites
- Fixed some text wrapping issues with unicode font
- Made autoplay less prone to missing inputs during FPS drops/skips
- Coin UI decrements more quickly when losing a large number of coins
- Fixed obstacles not respawning correctly after end of level in practice mode
- Adjusted vertical positioning of input timeline
- Fixed practice mode speed override display behavior
- Fixed bug when changing music speed and pausing simultaneously
- Retain menu selection when disabling full screenreader control
- Fixed Fade screen filter