Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1412142 Posts in 69752 Topics- by 58684 Members - Latest Member: HellBornHacker

January 15, 2025, 02:55:27 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogsRhythm Quest - Chiptune music-based runner (Free Demo out now!)
Pages: 1 ... 3 4 [5]
Print
Author Topic: Rhythm Quest - Chiptune music-based runner (Free Demo out now!)  (Read 29212 times)
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #80 on: June 29, 2024, 03:02:20 PM »

Rhythm Quest x Mozart, Assist Features

New levels! In addition to charting out "Song of the Sea (Expert Mix)" from Melody Muncher, I've added two Mozart compositions to Rhythm Quest. Here's the video showing off some excerpts from those levels:





Mozart

The two Mozart pieces that I added are the first (Allegro) movements from Piano Sonata No. 16 in C Major, K. 545, and Eine kleine Nachtmusik (Serenade No. 13 for strings in G Major), K. 525. (whew, that was a mouthful)

Various classical pieces have been featured in other games (see: Pop'n Music, Taiko no Tatsujin, etc etc) and I wanted to see how they might work in Rhythm Quest too (given that I could find some public domain recordings or simply take a MIDI arrangement and create my own).



Overall, they're pretty energetic and make for a fun playthrough! The rhythms aren't necessarily perfect for charting in the Rhythm Quest system, but they work well enough and there are a few phrases that came out particularly nice-feeling. The trickiest part about charting them was making sure that for all of the repeated sections were charted slightly differently so that it doesn't get stale. I don't want to just have the exact same sequence repeated a bunch of times over and over again! (looking at you, Rock Band...)

Probably the best aspect of these songs is that they're pretty widely known to a general audience, so that factor of "hey, I know this song!" is nice to have. Perhaps I can look into some other public domain compositions in the future...

Song of the Sea (Expert Mix)

Like with "Beneath the Surface", this one is at a slower tempo of 90 BPM (the two are very similar actually), so I wanted to focus on more complex rhythms in the chart, including 16th note patterns!



In the above gif you can see a couple different trickier rhythms being used. The sixteenth-note flying enemy patterns are something that I haven't actually used in the main game (yet??), as I've only done that grouping in the middle of a water zone. However, it's actually quite easy to read once you're familiar with it, so that might end up showing up in World 6 at some point (?).

The trickier patterns is the one with the yellow ghost intermixed with red basic enemies. Fortunately, the tempo is slow enough here that even if you're just visually reacting to the spacing, you can kind of get it even if you don't parse it ahead of time. It's very satisfying to hit, though! This makes me think that maybe when I work on level 6-3, it should be one that's at a slow tempo like this, so that I can introduce some (maybe not all) of these more complex rhythms.

One last note is that currently these types of 16th-note based patterns are impossible to create in the level editor, which obviously isn't ideal given that they're actually quite fun to work with when used tastefully. I'll have to make a note to see if I can add a setting for snapping to 16th-note placements, which I'm sure will also involve a bunch of work on validation and bugfixing, haha...

Assist Features

Feature-wise, I've actually been doing a bunch of work on game assists -- functionality to make the game temporarily (or permanently) easier, for players who are struggling or get stuck on a certain song but want to continue to progress.

First off, I've added a dialog that shows up if you fail the same section of a track enough times (currently, after your 30th attempt). Because this is an unexpected prompt that happens in the middle of gameplay (I try to avoid those!), I made sure to fade it in and disallow input during the fade, to prevent you from accidentally selecting something without having the chance to read the prompt.



One of the options here is a "track preview" feature, inspired by the "binoculars" in Celeste, which let you view upcoming sections of the level in case you want to get them into your head and see what's coming up:



There's also "practice mode" (UI still being worked on) which will let you repeatedly practice the current section on the fly (while controlling the speed, etc.) until you're ready to attempt it for real. "Temporary cheats" just contains settings for slowing down the music speed, lengthening timing windows, and enabling autoplay, but they automatically disable themselves once you reach the next checkpoint.

Track Freezing

The new assist feature that I've just developed is something I'm calling "track freezing". When this is enabled, the level scrolling will automatically pause and wait for you to make the correct input, if you haven't already done it in time:



The music keeps playing even during this pause (trust me, it would be wayyy too complex to try and pause the music and reschedule it on the fly), so after you make the input, the scrolling tries to speed up to "catch back up" to the music.

The end result is actually pretty cool! If you aren't missing any inputs, then the track freezing doesn't kick in at all and you just play normally. But if you miss some notes or press something too late, you'll be able to just correct it on the fly and have the music keep playing instead of having to restart the section.

Life...

...happens. I'm happy that I was able to put together a progress update for y'all this month, but I honestly wasn't sure it was going to happen as I had some tough stuff that I had to handle in my personal life over the past weeks. This is kinda just the way that things go (I'm a normal human being just like the rest of you), but it's also kind of tough to account for the in the grand scheme of things.

Now that we're at the end of June, 2024 is officially halfway over! (gulp) Looking back over the past six months, it seems like I mainly worked on a bunch of bonus levels and custom level import/publish flows, but there were also some other great features added such as the companions, plus the eighth-note ghosts (a new core mechanic!). If we're being totally realistic, it's probably inevitable that I won't be able to do a full release by the end of the year =(...but part of me wants to keep that deadline fixed because I think it's good to have a goal to shoot for!

Honestly, though, I've always been in "marathon mode" for this project -- as long as I'm continuing to progress forward at a steady pace, that's going to be considered a success for me. Hopefully seeing more and more levels and features is also enjoyable for you guys, even though I know y'all just want to hurry up and play the game already. I guess part of the reason I wanted to call out the whole "real life" stuff is that recent events have reminded to step back a bit in terms of perspective on what is important to me. At the end of the day, as much as I wish I could say that releasing Rhythm Quest is going to be something that brings lasting happiness into my life, it kind of isn't, in the grand scheme of things.

...which is not to say that it's not important to me or that I won't keep working on it! I'm still having fun working on the project and every now and then (usually when I'm charting new levels) I'm reminded of just how fun the gameplay actually is, and of COURSE I'm going to finish it, guys, I'm very committed to that. But at the same time, it's something I'm trying not to get too worked up about, because it's only one part of my life. I hope whoever ends up reading this will also keep in mind what the "the real important stuff" is as they go through their day to day struggles and efforts.

Anyways, personal segment over, I'll see you back here next month with some more updates!
Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #81 on: July 31, 2024, 11:54:53 PM »

Level 6-3

Another month, another new level. Hopefully I can at LEAST keep this pace up, if nothing else, haha. There's some other stuff I worked on that's not ready to show off yet, but here's the preview for level 6-3, titled "Quantum Orbit":





Chart Design

I don't have any more game mechanics to introduce (we're nearing the end of the main levels, after all!), but this level still introduces some new rhythms into the mix to spice things up.

I'm hoping to introduce two "combination rhythms" involving the yellow ghost enemies, one for A.bA ..A. and another for A..A b.A., where A is the ghost hits and b is a basic enemy inserted in the middle of the pattern. Level 6-3 features the former of the two:



A little later in the level I also feature the same rhythm, but this time with a green jump+attack enemy:



I originally had these as ghost + jump combinations (without the green combo enemy), but I was worried about the visual readability for that rhythm because the ghost =looks= like it's a half-beat after the jump (even though it's only a sixteenth-beat after the jump). My hope here is that by adding the green combo enemy it's actually easier to recognize as being the same rhythm as before (with the red enemy). Things are definitely getting trickier here near the end of the game!

Level 6-3 has what I believe is the slowest tempo out of all of the main songs so far (95 BPM) due to featuring these fast sixteenth patterns. This also gives me the opportunity to introduce sixteenth-note strings of flying enemies:



We've already seen this same grouping inside of water zones, but this is the first time we're seeing them outside of them, meaning the pattern is twice as fast. I like how despite being a very fast rhythm, it should be very easy to pick up due to being so similar to something you've already gotten used to recognizing throughout the previous 2 worlds. This is where my consistency in pattern usage will hopefully pay off!

Last but not least, towards the end of the level I throw this super-interesting purple + yellow ghost combo rhythm at you:



This is another instance where I'm trying to help the player out by first introducing the same rhythm, but with basic enemies instead of the purple ghost. Since the musical rhythm repeats the same way both times, there's a higher chance that you'll be able to get it -- if not on the first try, then hopefully without too much trouble after practicing it a few times.

Visual Design

I went kind of wild with the number of transparent layers for the backdrops here (I have to be careful not to do this too much as the backdrop textures will end up eating up more memory and storage space), which is why the colors look to have such a gradual gradient when they're all blended on top of each other.



I'm staying consistent with the general visual theme of world 6 and using the spraypaint tool everywhere for the "nebula cloud-like" dithering textures. That combined with the gratuitous layer blending really makes this world's backdrops feel different than any of the other worlds. It's working out nicely that the colors involved are the most complex compared to the other worlds as well.

The main focal point of the backdrops is the big rimlit planet. Honestly at this point I'm just searching for random sci-fi/space-themed drawings and photos and using those as inspirations. It's working out okay so far! I tried to draw the stars a little differently this time -- have to do something to set apart all these generic "dark space backdrops"...

Music Design

I'm trying to use more varied bass synths through world 6. Here we have a thicker "plucked" bass sound that kicks off the song, as well as plays through the first "verse" section. Note the use of triangle wave tom fills to accentuate the triplet speed zone pattern (that's becoming pretty consistent musical signage for me):

https://rhythmquestgame.com/devlog/69-verse.mp3

I'm trying to keep my lead sounds diversified as well. I still use my trusty square wave "bell" tones, but I also use more complex synths like this synth patch. Here I'm using an added square wave "pluck" layer to accentuate the onset of each note, and also adding extra "cool spacey" vibes by slapping on a reverse effect on the delay/echo trail:

https://rhythmquestgame.com/devlog/69-reversedlead.mp3

For the main chorus section, I'm using a bog-standard VI-VII-i chord progression (probably the most common progression in the entire soundtrack) with some added sevenths/suspensions to spice things up a bit. Dropping into this specific progression at the main climax of a track is definitely a go-to techinque of mine, both inside and outside of Rhythm Quest, so I'm well, well acquainted with it. The pad synth is sidechained against the kick drum to give it that "ducking/pumping" sound, which you can hear here:

https://rhythmquestgame.com/devlog/69-sidechainedpads.mp3

I'm trying to let loose a little more with reverb through world 6 as well, which means some heavy use of my favorite huge-reverb plugin, ValhallaSupermassive, which can turn any sort of basic/dry sound into an entire soundscape of washed out echoes. I use it mainly on this "call-and-response" arp synth:

https://rhythmquestgame.com/devlog/69-reverbarp.mp3

Here's the entire main drop into the chorus of the song. The echoey arp that I mentioned above is definitely a background element here since it needs to make room for the actual gameplay-based melodies, but it's my favorite element of the track by far.

https://rhythmquestgame.com/devlog/69-chorus.mp3

That's going to do it for this update! I only have TWO MORE LEVELS to make before I can celebrate at having all 30 songs in the main 6 worlds done! (and then go back to the million other things that I have to do, ha ha ha...)
Logged
BestFriendStudio
Level 0
**


One man studio with ton of pixels


View Profile
« Reply #82 on: August 01, 2024, 03:31:21 PM »

Your devlog is pure gold and the game looks quite fun. There's so many interesting and useful information provided in very pleasant form.

Thank you for all your efforts.  Hand Clap Smiley

One of my students wants to create a rhythm game, and she had a problem finding useful information and instructions, so I've shared your devlog as a good starting point.
Logged

DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #83 on: August 29, 2024, 09:20:42 PM »

Midnight Moon, Rondo Alla Turca

Working on new levels has consistently been my favorite part of Rhythm Quest development! As I continue to flesh out my roster of bonus stages (I've got 15-20 at this point!), I've been thinking about other musical styles that I haven't yet represented. One of those is DnB (Drum and Bass), so I made a track called "Midnight Moon" inspired by "Liquid DnB" soundscapes:





This one is at a very brisk tempo of 170 BPM, but doesn't feature any of the mechanics from worlds 4-6 (water/speed zones, green enemies, yellow ghosts), so it's a good exercise in simply testing your ability to read basic patterns. I'm making more liberal use of syncopated rhythms in the bonus songs throughout, though, so they are going to be a little trickier to sightread than the main stages.



As I've probably mentioned in the past, even when I do use offbeat rhythms, I'm trying to keep them relatively readable, often favoring airjump patterns over basic enemies as they tend to be easier to read at a glance based on height differences.

For the music side of things, the basic structure of the DnB soundscape is actually not very complicated. The foundation consists, of course, of a nice drum loop, and then a prominent low bass synth with a little bit of "wetness" (growl/detune/warble) to it:

https://rhythmquestgame.com/devlog/70-drumsbass.mp3

The cool thing about the liquid DnB-inspired soundscape for me is that the tight drums contrast with the other melodic layers going on, which are either drenched in lush reverb, or have softer textures. Here I'm using a droning bell-type pad loop sample, some electric piano-ish plucks, and then a chiptune arpeggio that's put through a ton of reverb:

https://rhythmquestgame.com/devlog/70-texturelayers.mp3

Here's all of that coming together in the main drop of the song, which also adds in a few other new elements (an additional drum loop layer, a high blippy synth):

https://rhythmquestgame.com/devlog/70-drop.mp3

Rondo Alla Turca

I'll eventually try to get someone else like Bach in the mix, but for now we've got some more Mozart! This time the very well-known "Alla turca" movement of Piano Sonata No. 11 in A Major, also known as the "Turkish March":





This chart is simpler (doesn't even use ghost enemies) and should be a fun, light-hearted playthrough for anybody who has gotten to world 3-ish. Being familiar with the melodies of the song should also make sightreading a bit easier, which is nice. There's not much else to say about this one so let's just move onto talking about other stuff!

Pausing while Respawning

Finally!!! This seems like such a trivial thing but has literally been on my TODO list for years...you can pause in the middle of a respawn now:



It's...actually still not perfect, as instead of immediately resuming the respawn where it left off, it restarts the respawn transition so it might take a few extra beats. But that's certainly good enough for me!

You might be asking why this took so gosh-darned long for me to implement and the answer is that the respawn logic is actually really complicated with a bunch of different moving parts. Briefly speaking, during a respawn the following things happen:

- Switch over seamlessly to the respawn music loop (which was already playing, just at 0 volume)
- Find a seamless point in the future to reschedule the main music
- The pause music loop and respawn music loop also need to be scheduled (at 0 volume!)
- Take care of the actual camera and player animation, which needs to be smoothly interpolated
- At the end of the respawn, the entire audio timeline needs to be shifted

Because of how audio needs to be scheduled in advance (otherwise you run into audio buffer/latency issues), pausing that entire process isn't as simple as "just pause here and resume later" -- the scheduled music transition needs to be cancelled entirely. Of course, pausing the game also involves some special logic (keeping track of when in the music the player paused, so that we can later schedule the unpause seamlessly and drop you in on the right beat).

This was really daunting, so I kept putting it off, but recently I was working on handling an edge case where switching the audio device (e.g. plugging in a pair of headphones) would cause all currently-playing audio sources to stop (sigh...) and need to be rescheduled, so I went in and tried to just solve for all of this at the same time.

Weblate Setup

For a while now the community translation/localization efforts for Rhythm Quest have been managed via its page on Crowdin. This has mostly sufficed (actually was a headache at first as their Unity integration wasn't robust and I had to patch it up a lot...fortunately they have patched all of that up since then), but despite my impressions of the game not having a lot of text, I eventually started adding enough options and level editor UI flows that I quickly started running into the limits of their free plan (word count X number of languages can be 60,000 at most).

The next tier up would cost $150 USD a month (yeouch) and only increase that limit to 100k, so I chose to look for alternative solutions for hosting and managing community trnaslations (hopefully something better than just reverting to using a scrappy shared google sheet). I ended up looking into Weblate, an open-source solution for this. Weblate's cloud-hosted option costs ~$40 USD a month, but you can also host it yourself if you have enough know-how to administrate a web server and set up all the infrastructure for it.

After some failed (but educational) attempts at bringing that online earlier this year, I managed to actually get that mostly up and running on my web/cloud infrastructure stack:



This is not really production-ready yet (I've disabled new user registration and everything), and there are still some aspects of it that I need to follow up on, but it's good to know that this has a good shot of panning out for my localization needs moving forward. It's still not free, of course, as I need to pay for the server resources and all that, but the cost is an order of magnitude less than I would be paying otherwise, so it's a win there nonetheless.

Translation is actually quite an important thing for my game if you look at the Steam wishlist breakdown by region, as the majority of my wishlists are actually from non-English speaking countries...



I had some plans initially for transitioning to using a professional agency and/or service for localization, but got a little discouraged after thinking about the costs involved. I guess it's a hard thing to commit money toward something that hasn't really yet cost you anything nor made you anything either...
Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #84 on: September 26, 2024, 11:44:16 PM »

Level 6–4, Even More Bonus Levels

Level 6-4 is sickkk.





New Patterns

This is the second-to-last level of the 30 main ones, so I can't hold anything back now! Even this late in the game, I'm actually still managing to introduce a new curveball or two...starting off with combining speed zones with ghost enemies:



Since this isn't immediately obvious how it would work, I've provided the tutorial icons below to show where the ghost ends up. It's actually simpler than it looks, as the timing is just equivalent to regular eighth notes (like a normal double-hit enemy). But now I can use this triplet->eighth note rhythm as a satisfying way to cap off a phrase.

In a similar vein, I also combine speed zones with spike enemies:



This is another instance where I'm secretly making the rhythm easier to parse by adding extra elements -- the green combo enemies allow you to have a more obvious indicator of when you need to jump.

Besides that, I'm making full use of the 16th-note rhythms that I introduced in the previous level:



I feel okay using this tricky purple + yellow ghost combination as a "fixed pattern" since I already introduced it in level 6-3 at a slower tempo. As you can see, I'm also leaning more into variations on 16th-note flying enemy patterns as well.

Honestly, the new rhythms are a blast to play. It's crazy to think that over a year ago I thought that speed zones would be the last mechanic added to the game, until I was inspired to make the yellow ghost enemies (partly due to some custom level work I was doing!) which started to open up the opportunities for more variations.

Backdrop Design

I'm quite pleased with the backdrops for this level, not just because they look great but because I managed to do something different than just a 4th version of "outer space with a bunch of stars, plus something extra". I started things off with these spraybrush layers, actually very similar to some of the cloud layers in previous worlds, just with a lot of dithering going on (that's the main stylistic thing going on in world 6):



I liked the way that looked, but wanted to add something more to it. My first attempt was just to do some mountains (clouds + mountains...just how many of my previous level backdrops are variations on this?):



It wasn't the worst (the dithering on the shading of the mountains was a nice touch), but I felt like it wasn't quite hitting right, plus it didn't really feel like it vibe with the whole space theme. I decided to try using translucent triangles instead, kind of like how I did in world 5, and that looked much better:



I'm scared at how this might perform on the switch (this is the kind of backdrop set that requires toggling off some layers when in low-quality graphics mode), but it looks beautiful when you see all of the translucent layers scrolling at different rates and blending together.

Audio Design

The element that kicks of the track and plays through its entirety (and the one I wrote first) is this gated pad sound. I layered some different sustained synths and then applied a rhythmic volume automation to it:

https://rhythmquestgame.com/devlog/71-gatedpad.mp3

There's two different basslines going on in the first section of the song -- one main "plucked" bass synth, and then a simple pulse wave bass that's a bit higher in frequency:

https://rhythmquestgame.com/devlog/71-bass.mp3

The drums aren't anything too fancy, just a drum loop that I've chopped up and rearranged, plus some extra hi-hat layers:

https://rhythmquestgame.com/devlog/71-drums1.mp3

Here's all of that coming together in the first chorus along with the lead melody:

https://rhythmquestgame.com/devlog/71-chorus1.mp3

In the second second of the song where the big drop happens, I switch to a different main bass sound. This one is really thick, made by layering a handful of different synths -- some providing a really "meaty" low-end, and others providing a more middle-range detuned sound.

https://rhythmquestgame.com/devlog/71-bigbass.mp3

The drums get a little changeup too! Most notably, I switch to a halftime beat, but I also use a beefier kick drum, and there's an extra drum loop layer, which mostly adds extra strength to the snare hit.

https://rhythmquestgame.com/devlog/71-drums2.mp3

There's this heavily-reverbed chirp sound too. I featured this same sort of thing in the previous level too, but I guess I just can't get enough of it; it provides this sort of nice melodic "shimmer" in the top-end without getting in the way of the lead melody.

https://rhythmquestgame.com/devlog/71-echoarp.mp3

In the buildup I also turn on a "notch filter" (removes a narrow range of frequencies) and sweep it from high to low, for an almost phaser-like effect. Here's all of that coming together:

https://rhythmquestgame.com/devlog/71-chorus2.mp3

Other Bonus Songs

I've also been working on adding some more classical music pieces to the game as bonus songs -- this time by composers other than Mozart!





Starting off with a classic, "Flight of the Bumblebee". While this one isn't quite as well suited to Rhythm Quest as it is to some sort of 7+ key rhythm game where you can just chart out all of the 16th notes, it was still a fun one to do.



Past the very start of the song, you spend the entire time in the air through combinations of air jumps and flight patterns, as a nod to the theme of the song. The scrolling speed also increases bit by bit with every checkpoint, adding to the frenetic nature of the song. (PS: I spy mountains + clouds in the backdrops...)

Then we've got a song that I heard about a billion times at music recitals for young piano players, "Für Elise":



This one is more laidback -- kind of a repetitive song, to be honest, but I made sure to chart each repetition a little differently so that you don't end up falling asleep (like I did during those music recitals...). It's also notable for being the first song I've charted that makes use of a non-4/4 time signature. (Hm? Yes, that functionality totally worked the first time that I tried it, there were no bugs to speak of, nope, not at all. ...why are you looking at me like that?)

That's it for this month's update. Comparing level 6-4 to level 1-1 is wild; I can't believe how far I've come in these past 8 years and how deep I've gotten into Rhythm Quest charting and level design. I'm honestly almost glad that the journey to get here has taken this long, as it means I get to put the knowledge and skills that I've accumulated over the years into use. Well, it also means I probably need to revisit some of the older levels to touch them up, but I'm going to not think about that just yet...

Level 6-5 feels like it might be a little intimidating to work on, so I might try and work on a few other things next month to start with. Knowing how I work, though, I feel like it's going to be the sort of thing that I just decide to just sit down and knock out most of it in like a day or two. Just has to be the right time, I guess.
Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #85 on: October 31, 2024, 11:13:28 PM »

General Improvements and Optimizations

No fancy new level to show you all this time, but I've been doing good work regardless this month. I have a silly little -- ok, maybe it's really not little anymore, actually quite the opposite -- Trello board where I track tasks and work items that I accomplish for the game, divided into weeks, so you sorta track the number of things that I end up tackling per week. This past month had some columns that are longer than can fit in my screen...



Weblate Site

I mentioned in a previous devlog that I had been working on migrating off of Crowdin for managing community translation efforts due to exceeding their free plan limits. I'm happy to report that my self-hosted Weblate site has been up and running and seems to be fully functional with no issues!



Currently (subject to change) this runs on an Amazon t3a.small EC2 instance, which costs me $0.0188 an hour on-demand (was easiest to go with AWS since I already have other stuff running there), which is pennies compared to the non-selfhosted options out there. More importantly, it all seems to work, and it's even synchronizing everything to a github repository in XLIFF format, so I can breathe much easier knowing that rollbacks or tracking down issues are going to be that much easier.

No More Unity Branding

I finally bit the bullet and did a major engine upgrade to Unity 6 (aka Unity 2023). This involved fixing a couple of bugs that cropped up (the upgrade exposed some issues that were mostly my fault that had never surfaced before). Upgrading isn't really painless right now because I have all of these custom changes to Unity packages (hacks to make things actually work like they should...), but I managed to handle it well enough. Probably the biggest relevant change (hah) in Unity 6 is the removal of the Unity splash screen requirement for free Unity licenses (huzzah!). I also took a few minutes to update the WebGL template for the web version of the game, so now we get a nice loading graphic and we're totally devoid of any Unity branding!



I can probably stand to make this even nicer later on, but this is already a welcome change, and nobody has to wait those extra 5 seconds sitting through the Unity logo before the game starts, woo~

Loading Icons

Speaking of loading graphics...I also took another few minutes to implement a simple change that's been on my list for a while: the loading indicator in the corner of the game now changes to reflect which character you have selected!



(More) Backdrop Optimizations

I was tired of seeing framerate drops when testing on lower-end devices (like the Switch...), so I went in and did another pass at performance optimizations. Besides random trivial "cache this lookup" or "use a binary search here" improvements, the main change that happened was with regards to how the backdrops are rendered (again).



A long time ago I did some nifty optimizations around backdrops that had large opaque areas (obscuring big chunks of what was behind them). Essentially, if we know that the entire screen below a certain point is covered up, we don't need to bother rendering any of the backdrops below that point.



...eeexcept if the backdrop in question is transparent, in which case we =do= have to go ahead and still render everything. Now of course, I have a lot of backdrops that are opaque, so this is still a good improvement.



...eeexcept when I'm crossfading between two sets of backdrops in the menu. This special case has caused me a lot of headaches in the past and it was never performant on the Switch despite my best efforts. There's multiple problems at play here:

- We're simply drawing twice as much stuff (twice as many texture lookups, twice as many "pixel paint" operations).
- If you want something that's a halfway fade between set A and set B, you can't just render set A at 50% opacity and then render set B at 50% opacity on top of that. That's not how blending works. So instead you need to reorder everything -- you can render set A at 100% opacity, and then set B at 50% opacity on top of all that. That requires a lot of bookkeeping logic around the sort order of all of the different backdrop layers.
- Rendering backdrop layers at less than 100% opacity throws all the nice optimization described above out the window.

Really what I wanted to do was just treat backdrop set A and backdrop set B as pre-rendered (moving) images and then fade between those two, instead of having to deal with the complexity of each one being made up of 20-30 different layers. So, I did just that!



In the new setup, each set of backdrop layers is rendered at full opacity to two separate temporary render textures -- one for foreground layers, and one for background layers (for those of you who are familiar with how rendering works, we need to use premultiplied alpha here to handle transparency correctly). We can then easily crossfade between our temporary textures without having to worry about weird transparency blending artifacts. This took a bunch of work to set up, but actually massively simplified the menu backdrop handling code as I don't have to worry about doing weird juggling of the sort order of a bajillion different individual layers.

There's still more rendering optimizations I can potentially look at in the future (some of the world 6 backdrop sets are particularly heavyweight and could benefit from some additional techniques around intermediary textures), but this is already great progress and we successfully eliminated the framerate drops on Switch that were caused by menu transitions.

Editor Improvements

I also made some optimizations for the level editor! Previously I described how each time you make a change to a level, the editor currently needs to regenerate the level in its entirety. To make this faster, I have object pools for all of the level objects, so that I can reuse the instances instead of destroying all of them and recreating them from scratch (which would be much slower).

...except, somewhere along the way I ended up breaking that entirely, lol. When I started supporting different level tilesets, I had to swap out the "level generator" object that contained all of the tileset data, and the easiest way to do that was to just replace it every time you recreated a new level. Except, that object also contained the object pool...which therefore was getting destroyed every time...[facepalm]

Anyhow, that's all fixed now. I actually found this bug because I was testing out the new fine-grained editor grid, which lets you place obstacles using a 16th-note grid. This is mostly so that you can create interesting syncopated rhythms, but yes, if you wanted to, you could just go wild and make "random note-spam" type charts:



Virtual Cursor

I also added a virtual mouse cursor implementation for the level editor that you can control using either the keyboard or a gamepad. Technically this isn't really required for any platform (even for something like Nintendo Switch you can still use the touchscreen, unless of course you have it docked), but navigating the editor UI via keyboard doesn't really make any sense anyways so I figured I'd try this out.



As usual, Unity gets you kinda halfway there but then you have to pick up the pieces, leaving you wondering whether you should have just implemented the entire feature yourself in the first place. Unity provides a virtual mouse cursor implementation that (fortunately) will hook into their UI input system, except:

- It doesn't properly handle UI canvases that are scaled (like mine)
- Disabling and re-enabling the cursor causes a HUGE lag spike as it re-registers a new virtual input device and does god-knows-what-else
- For whatever reason it seems to not interact with UI (yet still move around fine) if you're using specific parts of the new input system (device-based control schemes)

But after some cursing and debugging, and some added hacks, it seems to all be working fine! The system is smart enough to enable the cursor when you use keyboard or gamepad input, and turn it back off if you start using a mouse, plus you can even scroll the camera by putting the virtual camera at the screen edges (or via right analog stick).

Gamepad Fixes

As is common, gamepad support is yet another piece of functionality that has landed firmly in the bucket of "I should have just reimplemented this myself manually from the beginning instead of using the Unity-provided solution". So far I've been using Unity's newer "Input System" solution, which actually has a number of advantages over older implementations -- including automatically switching between control schemes based on player input, as well as supporting input rebinding. After (sigh) some hacks here and there, including one to deal with the fact that Steam forcibly takes controller input and translates it to keystrokes (thanks, no thanks...), I actually had that all mostly working.

...eeexcept for the fact that on some systems (??), certain controllers would simply not register input under Unity's new input system whatsoever. Not just a "my implementation" problem either, as I downloaded some sample projects and the issue shows up there, too. But...clearly the device has connectivity, and Unity even throws up a helpful message reporting when the controller connects.



Gamepad input is understandably something really hard to deal with (given the number of hoops you have to go through sometimes to get a given console controller working with your system), but I'm going to blame Unity for this one given that their old input manager implementation still picks up the gamepad's input in this case.

I hope I'm not going to be regretting this later on, but for now I'm leaving the old (new?) input system implementation in place (with my hacks, it does end up switching more-or-less gracefully between input schemes, which I like), but I implemented a legacy gamepad fallback implementation for when the new input system claims to not have gamepads attached but the old one does.

Of course, with the legacy input system, there's no standardization for how the buttons and sticks on various controllers present themselves, which is probably part of why Unity had that old input configuration dialog that used to pop up every time you started up a poorly-made game jam game:



Ah yes, the telltale sign that you were about to play somebody's first Unity game. Anyways, fortunately for me, Incontrol's old open-source package contains device profiles for many known controllers. Granted, this hasn't been updated in the past 3 years (since Incontrol became a commercial closed-source asset), but I found that it was good enough for my purposes, at least for now. I integrated Incontrol's input handling and mapping, updated it to work with Unity 6, turned on XInput support, and "just like that", I have gamepad input testing and working for my XBox360 controller on Windows and on my PS3 controller across Windows and Mac.

I mean, forget the fact that I needed two separate programs to even get the PS3 controller to hookup to those systems successfully, and the fact that the XBox360 controller support is just plain borked on Mac...

Font Rendering Fixes

Updating to Unity 6 meant some small shifts in how Unity packages its text-rendering system, which exposed a few issues with pixel snapping and sorting order that I ended up ironing out. While I was at it, I noticed that the unicode pixel font that I use (unifont) rendered OK when the game was at small resolutions, but at higher resolutions it got all blurry and the sampling didn't seem right.



This one is kind of on me. Unifont is designed to render minimally at size 16 (or 12, depending on what you're plugging it into), but because my game pixels are often already upscaled, I was having it sample at that size and then setting it to display at 50%. The UI canvas would for example be scaled up by 2x, so it ends up balancing out to present at 1x scale and render crisp pixels (which are 50% the size of the rest of the game's "pixels").

Unfortunately that just doesn't extend to other canvas scaling situations. In the end I just decided to get rid of that 50% factor, so now unifont displays one to one with the rest of the pixels in the game UI:



Of course, now the font is just bigger, so I run into issues where the glyphs can't really fit properly into the areas they're supposed to. But if you're using a language where the unicode font is used, you reallllyyy ought to not use the pixel-based font anyways (and the game is smart enough to default you to smooth font rendering in this case). Unless of course, you're playing at like 500x300 resolution for who-knows-what reason. In that case, this is actually an excellent change because the unicode pixel font now reads really well at that size, and you probably don't mind that the lettering is bigger!

What's Next?

Phew. There's still an endless list of things to take care of, and we're already two months out from the end of the year, but I'm happy with the amount of time I've been putting into things, at least. Moving forward, there are some remaining big-ticket items that'll make me feel much better if I can knock them out, including but not limited to:

- Unifying the selection menu for both bonus songs and custom levels (and main campaign levels, why not) into one big "song select/free play" menu
- Doing some thinking about whether I want to support multiple game difficulties (and more importantly, how I'd like them to work)
- It's awkward that the game settings are half split between "settings" and "game mods", I'd like to reorganize things if possible
- I still need a proper export flow for the level editor...

With any luck I will be able to at least get a few of these done by the end of the year. Thanks for reading, as always!
Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #86 on: November 30, 2024, 11:27:11 PM »

Multiple Difficulties, Song Select Menu

We're into the start of the holiday season now! I could either take this opportunity to dive head-first into Rhythm Quest work, or I could instead take it as a chance to rest and recover before the start of the new year...knowing myself, I suspect it's going to be neither of those and I'm just going to continue onward at a slow and steady pace!

Multiple Difficulties

Unfortunately I don't have any sort of "Rhythm Quest is feature complete!" or even "I finished working on all of the main levels!" announcement for the end of the year. However! As a consolation prize, I do have a little upcoming holiday present for all of you, and that is the unveiling of the new difficulty selection feature:



This isn't live in the demo (yet!), but you can now select from Easy, Normal, and Hard difficulties when starting the game, right before the world select menu. While I have reservations about adding yet another screen that you need to get through before you're actually in-game, in this case I ultimately decided that the benefits seem to justify the cost in this case. I unfortunately didn't have enough screen real estate to show any fancy previews or graphics here, but I also didn't want to have a menu that was =just= text, so I added the little enemy icons some some cute little visual iconography (with beat-synced animations!).

The hope is that adding multiple difficulty options will let experienced rhythm game players feel less bored through the earlier part of the campaign, as well as offer a more lightweight version for people who want to experience all of the levels but without them getting too hard near the end. It also adds some amount of replay value for people who want to go back and replay the levels with some harder charts.

Picking a difficulty level isn't a commitment and doesn't "lock you in" -- you're free to change your mind at any time and each level will track your scores (and coin counts!) separately, so if you decide that the levels are getting a little too hard for you, you can always turn the difficulty down moving forward. This does mean that there are essentially triple the amount of available coins in the game, so you'll probably just end up with a bunch of extra ones after unlocking everything (or maybe I'll just make some expensive "stretch" purchases for show).

There have been some UI changes in various screens to accomodate the new feature. Here's the level select screen, for example, which has a new button for changing your selected difficulty without having to go back to the initial menu. Again, I dislike how this screen feels more cluttered than before, but it was the best solution I could come up with given the constraints, and committing to it also allowed me to fit an extra "Bonus Levels" button on the upper-left to make things all nice and symmetrical.



I've been thinking about this feature for a while and initially had some trepidation because one of the main strengths of Rhythm Quest is the tight and intentional mirroring between the charting and the music cues -- I was worried that recharting the same tracks would lead to a loss in that coherence. With a previous game, "Melody Muncher", I solved this by simply adding new melodies into the existing songs and exporting multiple mixes of them, but I wanted to avoid doing that this time around as that would triple the amount of audio content that needs to be authored and served with the game, which is undesirable (particularly on mobile devices).

After thinking about the tracks, however, I think I can manage to make it work, even reusing the same audio. Normal mode will still be presented as "Rhythm Quest as it was originally intended", so it will most likely have the best matching between charting and music, but I think there are plenty of good opportunities where I can take liberties in charting the same piece differently.

This does add quite a lot of additional charting work for me, as I've now got to re-chart all of the existing 29 songs for both Easy and Hard mode (some of the later Normal mode charts might even get toned down a bit), not to mention the bonus songs as well. But charting is not particularly "hard" work to do, as it's a very known quantity. It's just going to take time.

I do, however, intend to release the re-charted versions of the demo levels before the end of the year, so you can look forward to playing those soon! Consider them to be my holiday present to all of you who are patiently waiting for more progress to be made on the game...

Charting Differences

Because the beginning of the game needs to ramp players up from essentially zero, the first few levels (the only ones I've worked on so far) won't have very significant charting differences between the three difficulties, but there will still be some.

The mechanics are still going to be introduced in the same levels throughout all difficulties, because I want players to be able to switch between difficulties at any time during their playthrough. However, the level of "rhythmic pattern" difficulty will increase at different rates. Here's an example of a snippet of level 1-2 to illustrate some of the minor differences:



Separating the easy and normal charts is actually fairly difficult early on and as a result they end up looking mostly the same (which is alright, for now, until we get to the later levels). I could just remove even more obstacles from the easy chart, but at a certain point that ceases to meaningfully make the chart easier, and can even make things =harder= as it's potentially more difficult to keep a steady beat in your head when the notes are too sparse. I briefly thought about increasing the number of checkpoints in the easy charts, but I decided against it as that would throw off a number of things (color palettes, too many screen flashes, etc).

The hard charting is a little more interesting to look at. Early on I need to strike a balance where I don't want to ramp up the difficulty too quickly, but I want to also make sure that players who "get" rhythm games are still always being engaged. I decided to allow for eighth-note basic enemy patterns in hard mode from the get-go, which really helps set apart the hard chart, but I'm still mostly holding off on more advanced rhythms involving off-beats and syncopation, except where it really flows in tune with the music in an obvious way.

Level Loading

Small (boring) technical note here on a change that's being made to the way levels are stored and loaded. Previously I had a "level baking" process where I ran the level generator code for each level ahead of time and then wrote the results out to disk as part of the build. The idea here was to (in theory) speed up the process of loading levels by precomputing all of that logic and just reading the fully-baked level from disk instead of instantiating all of the objects on the fly dynamically.

This is now more or less gone as part of the difficulty refactor. I didn't want to bake 3 different versions of every single level, and it's not actually even clear that this reduced loading times at all, as reading a million serialized objects from disk can potentially be slower than just instantiating them dynamically (this is the sort of thing that's hard to test outside of an actual build, and probably varies device to device). I still have a "level analysis" pass that needs to be run offline where the logic runs through every level to collect stats on it (notably, how many coins are in the level), but now I only save those numbers and not any of the actual level geometry.

I've mentioned before that I have an "object pooling" solution that's used in the level editor in order to reuse object instances every time the level is re-generated. I'm leaving this as a task for future me to talk about, but if I wanted to speed up level load times, I could actually persist the object pooling across different level loads -- that way, when you load a new level, it can just reuse the enemy/obstacle objects from the previous one you played instead of creating new ones from scratch (which is slower). So there's more optimizations that can be done if I put in the work to make it possible.

Song Select Menu

Besides supporting multiple difficulties, another work item on my by-end-of-year wishlist was building out a holistic "song select" menu that features all of the levels available in the game -- including the main campaign, the bonus levels, and custom levels, all in one big browser. I spent a good portion of this month working on that, and it's coming along pretty alright:



This looks pretty similar to the custom level browser that I implemented a while back, and a lot of the implementation is copied over, but in general things are more encapsulated / architected out a bit more robustly because I need to handle different types of content (i.e. many different button formats, instead of just one).

One new thing I coded up was a way to scroll the list via touch swipes, with scroll momentum and all that. This is only allowed on mobile devices, as on desktop / web / switch builds you have other better methods of navigating the list. It's a bit weird that this is the only UI in the game that uses this UI navigation paradigm, but I couldn't think of an elegant alternative for touchscreens that I was happy with and this is the only place in the game where the buttons need to be laid out in a really long dynamic list like this.



I had two options for implementing this -- use Unity's built-in scrollview logic, or just code and manage the scrolling inertia and clamping/snapping logic myself. Fortunately, I'm wiser than I once was, so I chose to just roll my own custom solution instead of even attempting to deal with Unity's this time. =P

Overall, it works pretty well! I had to iterate a little on exactly how much momentum to accumulate based on the movement of your intial touch/swipe, but fortunately it seems like my instincts were mostly on point and it feels natural for the most part.

New Water Shader

Someone reported a bug where the water effect in level 1-3 wasn't stretching across the entire screen for certain resolution/zoom levels, so I took the opportunity to just revamp the entire effect altogether. Here's what it used to look like, just a flat rectangle with a render texture that's used to capture the "reflected" graphics and then apply some sine wave modulation to them:



And here's the new version:



Looking a lot nicer, I think! This is going to be one of (hopefully) many many improvements to help bring the visual quality of the earlier levels more in line with the later ones.

The different "wave" layers are actually all drawn in a single pass by the fragment shader here. There's no complicated water simulation going on (the movement doesn't need to react to anything dynamic anyways), it's just a bunch of sine waves blended together to make an undulating pattern. Combined with the parallax scrolling and layering (and the fact that it's now partially translucent), it all comes together to make a nice effect.

One interesting aspect of the implementation here was to clamp/filter the pixel rendering correctly. Without that, you get waves that are rendered smoothly at whatever your device's native resolution is, which doesn't match the pixel aesthetic of the rest of the level:



With the clamping, the water waves are "stepped" with the same pixel sizing as the rest of the level graphics.




That's it for this update! There's still a lot more work to be done on the song select menu (bringing back the left-hand panel, letting you change your selected difficulty, etc) as well as recharting all of the demo levels (which will be my priority for the remainder of the year!) as well as trying to think about what I want to do with the backdrop visuals for worlds 1-3. Hopefully you all have a nice end of year and here's hoping (once again) that the coming year is "the year" for Rhythm Quest!
Logged
Pages: 1 ... 3 4 [5]
Print
Jump to:  

Theme orange-lt created by panic