Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

 
Advanced search

1403812 Posts in 68294 Topics- by 61958 Members - Latest Member: Kvrochi

December 09, 2022, 10:45:02 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 2 [3]
Print
Author Topic: Rhythm Quest - Chiptune music-based runner (Free Demo out now!)  (Read 8846 times)
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #40 on: May 06, 2022, 03:18:14 PM »

Jump+Attack Enemies, Too Early/Late Detection

Steam Page Now Live

First thing's first: the Steam page for Rhythm Quest is now live!

Please go ahead and give it a wishlist if you haven't already -- really helps out for metrics and visibility!

Jump+Attack Enemies

This week I worked on two new levels for world 3! The existing level 3-2 that I had was too difficult, so I've pushed that aside for now and come up with a new one, this time featuring a new mechanic:





As you can see in the above video, I've now got teal-colored flying enemies that signify jumping and attacking simultaneously. This is technically not a new enemy type, but I thought it would be good to differentiate these from the regular flying enemies visually to help key you in to the combo button press.

I had actually already coded these enemies in a couple weeks ago, but hadn't gotten around to trying them out yet...I'm glad I finally did! The jump+attack enemies open up a lot of interesting charting possibilities when combined with other mechanics, such as flight paths:



The backdrops for this new level came out pretty nicely, despite being relatively simple. I started with the "brick" pattern on the wall (just tiled rectangles...) and then added in the archways. I wasn't quite sure what to put in the archways at first, but ended up putting a dithered waterline, along with some stars in the background.

If you look closely, I'm using the same "shimmer" effect on the top pixels of the water as in prior stages -- it's just two layers of lighter translucent pixel segments that scroll at different speeds, giving a nice effect. I also added a dithered fade on the top and bottom of the wall. The final touch was to add the torches on the walls for some added interest.

Too Early/Too Late Tips

I worked on this feature last month but forgot to write about it. The game now detects when you press a button too early or late and shows a quick message on screen:



I wanted to try adding this feature since it might be difficult at higher speeds to know exactly what went wrong, especially because of prescheduled (not dynamic) audio hit sfx.

How do you think you would go about implementing this? You could try to have an extra collider/zone in front of the player to detect "too early" presses, but that's potentially inaccurate and doesn't help for "too late" presses.

The way I ended up coding this is a little more intricate and involves keeping track of actions and button presses across multiple frames rather than trying to "predict" what could be coming ahead:

For "too early" presses, I detect these by keeping track of the last time at which the player performs a "dud" jump or attack that didn't correspond to an obstacle. When the player collider intersects with any new interaction point, I check to see if the player's most recent "dud" input matches the obstacle, and was within 0.25 seconds. If so, I show the "Too Early" message.

For "too late" presses, it's essentially the same thing in reverse. First, I needed to restructure my code to allow input processing even during respawns, since that's often when "too late" button presses happen (after you already ran into an enemy). For this, I continually keep track of the most recent interactable jump point and attack point that overlapped the player collider, as well as the time at which it last overlapped. If the player presses a button that doesn't correspond to something, or if the player is already respawning, then I check against these "most recent interactables" to see if I should show a "Too Late" press.

That's it for this week! I also worked on a new (easier) level 3-3 for introducing the multi-hit ghost enemies, which is almost done. I'm pretty happy with the rate at which I'm able to make new levels (when I'm actually focusing on them) -- I generally take one day to write the music and chart, and then another day for the backdrops and any additional tweaks. At this rate I should be able to finish world 3 next week, unless I get sidetracked by something else. That's only halfway (?) through all of the world, so I really have to get cranking through these!

One other thing I have in the back of my mind is how to approach world 4. I already have speed zones implemented, but I might consider taking another stab at the underwater section mechanic. I also have to solidify my musical style for that world, still...
Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #41 on: May 13, 2022, 12:50:20 PM »

World 3 Complete

Despite struggling a bit with other stuff in my life, I managed to do some more music/charting/backdrop work in order to finish out world 3!

New Level 3-4 Backdrops

This originally used to be level 3-2 (and the first introduction of the multi-hit ghost enemies), but got bumped over to become level 3-4 because of difficulty. The backdrops for this got shifted over to level 3-3, so I needed some new background art for this level.

You might not notice it at first, but I actually reused some of the artwork from level 1-5 (City in the Rain) here, except this time the houses are darkened for a nighttime look, with a little bit of rim lighting and a gentle glow coming out of the windows. There's also a big castle in the back -- I like how that blends into the background at first but then pops into focus at the chorus when the colors shift.



Later in the stage I do a different effect where everything gets blacked out entirely except for the rim lighting and the window glows, and I like how that turned out. This whole world ended up having very dark backdrops in general so there's a lot of playing around with this sort of thing, which I think nicely contrasts all of the bright colors in world 2.



Level 3-5

This level draws a little bit of inspiration from Metal Man's stage (Mega Man 2) and/or Tinker Knight's stage (Shovel Knight) and has a bunch of (unfortunately, non-animated) gears/cogs in the background, which scroll in parallax. I have a dithered fade effect which adds some more feeling of depth, and it also turns into a light "glow" at the first chorus, which is kind of neat:



Later in the level I black out the dark backdrop colors and brighten everything else, which results in a sort of "neon" effect which is a bit characteristic of this world in general:



And I also play around with darker colors some more in this section, where the background gears are darkened:



That's it for this week, and that rounds out world 3! Overall this world unfortunately felt a little more "phoned in" than before, I think in particular levels 3-3 and 3-5 didn't feel like I was as meticulous about the music and charting as I have been in the past. I'm a little shaky on whether the difficulty curve for this world holds up well, so I may need some additional testing or tweaks on that as well. I've been tending to make songs a bit too high on the difficulty scale in general for these worlds, and I've already had to scale down the tempo of a few songs slightly to try and compensate, but you can only go so far with that. It's a tricky balance to maintain!

I'm never one to let perfect be the enemy of good, though, so things will have to sit as is for now as I move on to work on other things like world 4, which will hopefully have an entirely different vibe.
Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #42 on: May 20, 2022, 03:49:20 PM »

Level 4-1, Water Mechanic

I spent this week working on the first level in world 4, which introduces the water zone mechanic. Here's a video of the entire stage in action:





Water Zone Rework

It's been a long time since the water mechanic has made an appearance! I initially prototyped this almost an entire year ago, where it looked like this:



The water zones slow down the scrolling rate to 50%, and also make jumps take two beats instead of one. I was also contemplating having the water sections feature triplet-based rhythms.

I liked the idea of the water zones since they seemed intuitive and provided an interesting changeup, but I wasn't sold on the triplet idea, and the beat grids being spaced closer together made things difficult to read. More importantly, I was worried about the chart design space of this mechanic -- since the jump length is increased and scroll speed decreased, the water sections tend to have less notes, not more, which ostensibly makes them easier, not harder.



The new version of the mechanic that I landed on isn't actually too different from the original one. The scroll rate now only slows to 60% (maybe subject to change) to avoid making readability too difficult, and I've done away with the triplet rhythm idea (which is fine, since triplets are already covered by my speed zone mechanic).

The visual representation is also more or less the same, but I've tweaked the blue tinting to something that looks more vivid and cleaner overall. The "waves" on the borders of the water zones are actually done via fragment shader using a sine function. Each water zone actually has its own camera as well, which is used to draw to a render texture, which is then shifted via a similar sine function to give a slight "ripple" effect.

One key change I made with the visuals was to have two separate layers of blue tinting rather than one. I was having trouble because using a more-saturated blue tint was causing the player character and obstacles to look too faded out; I realized the solution was to only tint the gameplay elements slightly (25%) and then use a stronger tint behind that that only applies to the stage backdrops.

Probably the biggest "difference" in the water zones compared to a year ago isn't really a change at all: I've simply found some more interesting chart design aspects of the water zones that seem promising. Here's a small snippet where I use one-beat water zones to accentuate two short flight paths:



On a pure mechanical level this isn't particularly difficult, but the way in which it comes together with the music seems really interesting and satisfying to me. We'll probably get to see even more interesting combinations (rolling spike enemies + water zones) in future levels across this world. Despite the water zone limitations, I managed to have a higher note density for this level than any other level besides 3-5, so it looks like I might not have to worry so much about difficulty with this mechanic.

World 4 Music Theming

Going into world 4, I knew that I wanted to try utilizing pentatonic scales as a musical style choice, but I wasn't entirely sure how I wanted to differentiate the world instrumentation-wise. My previous attempt was straight 9-bit chiptune, but I wanted something a bit more distinct (I really like how world 2 turned out with its "airy/lush" instrumentation to set it apart).

I decided to try and bring in some plucked east asian instruments -- here I've got a shamisen and a yangqin:

https://rhythmquestgame.com/devlog/34-plucked.mp3

These instruments provided a nice textural flavor, but I wasn't confident in their ability to cut through the mix to provide the focal lead melodies, so I fell back on some of my usual chiptune leads for that. However, I also wanted to be sure to bring in this pan flute patch which fit right in:

https://rhythmquestgame.com/devlog/34-flute.mp3

I'm attempting to lean more into grace notes and similar embellishments in the melody writing here, to fit with the overall vibe.

Next, I needed to figure out what to do with the drums. I was initially thinking of fast drum n bass-style percussion (probably doesn't work at quite this tempo), but I ended up with something like this instead:

https://rhythmquestgame.com/devlog/34-drums.mp3

The main drum pattern is made of fairly ordinary tight drum sounds, but I'm using half-time drum fills with different elements -- a bigger, more reverbed snare, triangle wave tom rolls, and a ride cymbal -- to accentuate the water zone patterns. I'm liking how this is working out, so I'm going to see if I can continue to have this emphasis on "drum pattern changeups" throughout this world.

Level Graphics

A couple of things to note about the visual design for this world/level:



First, I knew I wanted to have the sky color be bright, to contrast with all of the dark backgrounds from world 3. I've had the idea to draw pyramids for world 4 for a while, so I put those in as well.

Somewhere along the line I started feeling like world 4 should sort of have a "mystical" or "arcane" vibe to it, since it features these blue and red (water and speed) columns. I ended up drawing these simple "floating octahedron" things and have them scrolling in parallax. Very simple, but it definitely looks a lot different than anything we had from world 3. I like how everything has more "depth" because of the shading, which constrasts to all of the more "flat" graphics from the previous world. The ground tileset for world 4 also features diamonds, to go along with this theme.

Something else to note is the clouds, which are actually all the same color, but translucent and overlapping (which causes different shades to come through). Transparent layers are something I've used a little bit in previous levels, but I'm thinking that I should try and experiment with them more across this world to fit with the overall "mystical" vibe and accentuate the feeling of depth.



During the high-energy sections of the song, I switch out the sky color so it looks like a night sky, which to me gives a sort of "alien planet" look. This wasn't something I planned on initially at all -- I was simply playing around with the palettes and realized that I had an extra color slot available and could use it for the background to achieve this effect.

I like how the sky is dark, but the pyramids are still bright, which is different than in world 3 where most of the background layers were all dark. This is something I'll also be trying to keep in mind as a thematic throughline for future levels in this world, if I can.

That's it for this week! Level 4-2 will be next on the docket, and will probably be another water zone-focused level, (then level 4-3 can introduce the speed zones, which are more challenging).
Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #43 on: June 03, 2022, 11:32:35 AM »

Level 4-3

This week was a bit of an off-week for me, as Monday was a holiday and I've also been busy brushing up on ALTTPR for the GMP Mentor Tourney. I still managed to finish up another level, though (one which I had started last week, actually). Here's the video for level 4-3, currently titled "Outerworld Highway":





Water Zone Charting

In this level I started to experiment with some new charting sequences involving the water zones. In particular, I have this section, which features rolling spike enemies intermixed with short water zones:



Since water zones double your jump duration from one beat to two beats, I also discovered this triple flying enemy pattern that reads nicely:



Water/Speed Zone Bugfixes

I won't dive into the details, but part of getting this level to function properly was going through and refactoring some of the logic behind water and speed zones -- particularly as they relate to jumping and jump durations/jump arcs.

This is actually a little bit more complicated than it might seem because jump arcs in Rhythm Quest are not determined empirically (as might be the case in other platformer-type games). In other words, we don't simply keep track of the character's currently velocity and accelerate it by a given amount each frame. Instead, we track the jump's starting position and derive the character's current position each frame thereafter based on a quadratic equation (a parabola!).

Obviously this becomes a little more complicated with water zones and speed zones in the mix. Previously my code assumed that a single jump would only ever cross a single water boundary, but that's no longer true with some of these new charts, so I had to refactor the jump arc code to handle an arbitrary number of transitions per single jump.

Level Backdrops

Not too much to say about the level backdrops here. It took me a while to settle on this particular combination of elements (the first few things I tried looked really bad), but you can see that I'm using the same themes of having translucent clouds along with bright colors against a dark background, plus some geometric shapes floating in the air. I've reused those floating shapes twice now, so I'll need to make sure I change things up for the next level I make in world 4.



Moving Forward

This stage was originally going to be level 4-2, with level 4-3 introducing the speed zones mechanic. However, after playing through this level, I think it's a bit too hard and bumped it to be level 4-3 instead. I'll have to fill in the gaps with a different level 4-2...and that also throws out my original plan of introducing the speed zones in this world.

The new plan is to simply have all of world 4 focus on water zones and instead have world 5 introduce and explore speed zones. I think this works out since speed zones in particular have a lot of interesting combinations of other mechanics that will probably need separate levels to introduce. World 6, then, can be the grandaddy combination of all mechanics where levels can freely use any mechanic in the game as they see fit.

World 4 is probably going to be slightly less "measured" in its approach due to this changeup -- if I had known this was going to be the world structure I would have planned each song to introduce one or two different types of water zone charting -- but I think it'll still be fine as the water zones aren't =too= different than normal obstacles. My current thinking is that level 4-2 will introduce and focus on the triple flying enemy pattern, and then level 4-3's main new gimmick will be the rolling spike enemies in water. Level 4-4 can probably focus on flying paths that go into and out of water, and then level 4-5 can just be everything all together? Well, that's the current plan, anyways...
Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #44 on: June 11, 2022, 10:08:41 PM »

Level 3-2 Revisited

Despite my task tracker listing a lot of items having been accomplished this week, it still felt like another slow week for Rhythm Quest since I only made one new level. Here's a video of that in action.





Level Order Restructuring

You've probably noticed that this is labeled as level 3-2, which I had already showed 4 devlogs ago, originally featuring the teal jump+attack enemies. After some feedback on the difficulty of this mechanic and further thought, I ended up deciding that I should postpone the introduction of the jump+attack combo enemies until world 5, where they can be introduced in various forms throughout that world.



That of course meant that level 3-2 needed to be changed entirely, as the old version I made was built specifically to highlight these combo enemies. The new track and chart is completely different, and focuses more on the spike enemies that were introduced in 3-1. There's a small emphasis on patterns where spike enemies are intermixed with both grounded and flying enemies, including the "jump attack attack" pattern seen in this clip:



This also meant removing all of the teal combo enemies from the rest of worlds 3 and 4. Unfortunately, the old level 3-2 (despite being a good song and chart) probably can't be reused in the main set of levels, since world 5 is going to have a completely different musical style. (It also introduces the combo enemies in a bit too many different forms at once) It'll still probably get featured as a bonus level though.

The new planned breakdown for introducing mechanics throughout the worlds is as follows:
World 1 - Basic Attack/Jump, flying enemies, doublehit enemies
World 2 - Air jumps, flight paths (+ flying doublehit enemies)
World 3 - Spike enemies, ghost enemies
World 4 - Water zones
World 5 - Jump+Attack combo enemies
World 6 - Speed zones

Other Stuff

I updated the level metadata code to also parse "actions per second" for each individual checkpoint of a song rather than for the entire song. This lets me see at a glance (roughly) which sections are most difficult and what the overall difficulty looks like over the course of a son. The entire song metric was sometimes being thrown off balance by particularly light sections, so this should be a little more accurate as a numerical gauge of difficulty.

I've been enjoying the recently-released game Chiki's Chase recently (highly recommended, go support!), which features a ton of small nifty features and polish (seriously, the main menu has a hint of parallax camera scrolling when you tilt your phone around...who does that??). This is the first time I've played a mobile game that effectively integrates haptic capabilities (short vibrations when you perform actions or click through dialogue), so on a whim I decided to see if I could hook up the native iOS/Android code for triggering haptic events in Rhythm Quest for mobile. That's currently working, though I think I'll need to play with it more before I give a verdict on whether to have it enabled or disabled by default. The game feels just fine without them, so I don't want to add a feature that ends up gets annoying after a while.

In a similar vein, controller/gamepad rumble has been an interesting one to iterate on, as most of my attempts have resulted in either imprecise or way-too-aggressive rumble. Unity's has built-in APIs for triggering rumble, but they're a bit coarse-grained, so this week I also managed to hook into the native Switch rumble functionality, which lets you control the vibration values in a bit more detail. That seems to be working better, so I'll have to continue to play around with that as well.
Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #45 on: June 18, 2022, 12:08:05 PM »

Menu Tweaks, Shop Rework

I miss the weeks when I would just crank out two levels over the course of the week...that really made it feel like I was making a lot of concrete progress towards finishing the game. Instead, this week I ended up getting zero work done on levels (oops) and worked on a few other things instead.

I suppose it's just as well, since I'm still mulling over what to do with the levels in world 4. My current plan is to have world 4 wholly feature the water zones, but 5 levels seems like slightly more than enough to explore that mechanic's design space (?). I could also try to bring in speed zones (or combo enemies) to world 4, but I think having 5 levels to introduce both of those mechanics is simply too few!

Legal/Accounting Stuff

That's right, everyone's favorite thing to deal with! (laughs) For a multitude of reasons I decided to form an LLC (limited liability corporation) to sell my game, as opposed to having it just be tied to me as an individual. This is pretty standard practice and if you deal with some form of side-business on a regular business it's often recommended to keep business accounting separate from your personal money.

I'm happy to report that most of that is now finally set up, and my Steam app (along with my iOS account, etc) are now tied to "DDRKirby(ISQ) LLC", and I also have a business banking account tied to that. Hooray! I won't drill into the boring step-by-step details of how I did all of this, but I'll gloss over some tips and learnings that I got out of the journey in case anyone else finds themselves in a similar position.

First, stick to A-Z letters and don't use parentheses in your LLC name like I did, lol. (we'll ignore the fact that "DDRKirby(ISQ)" was never the best alias to begin with) This worked just fine for my state's registry but various other systems strip out / don't allow symbols, so better to just not deal with that.

Second, a common question is when to form the LLC? The downside of forming an LLC too early is that you need to pay annual fees on it, so that's just wasted money if you're not actually earning revenue (your game isn't done yet) or tracking expenses. The downside of forming the LLC too late is that it's a bit of a hassle to change tax/legal information after the fact. For example, with Steam you need to make an entirely new Steamworks partner account, then set up a transfer for the app from the old account to the new one. Importantly, you need to pay the $100 Steam Direct fee AGAIN for the new account. This is probably less than the annual LLC fee (depends on state), though. So I think this is roughly the right timing for me.

Often people will recommend third-party services to help with filling out forms for establishing the LLC, as well as providing an on-file business contact (in lieu of yourself personally). The forms for registering the LLC were quite easy to self-fill, though, so I don't think this is necessary, though I think it can be useful to have access to some form of legal / accounting advice (whether that be from a CPA, a friend, or whoever).

UI Layout Scaling

Okay, back to stuff that I can post images about Smiley

Last time we left off, the main menu looked like this:



The overall structure has stayed the same, but everything is bigger now:



You might be wondering why I chose to do this, given that the old version looks more or less fine. The new version might look a little too cramped, actually, since everything is so big! The answer is to deal with multiple resolutions! Because I (by default) maintain integer pixel scaling to avoid scaling artifacts, the portion of screen space that the UI covers actually depends on the screen size. Here's the old version of the menu, but this time at the resolution of an iPhone in landscape view:



See how the UI feels like it has too much empty space around it now? The UI can't scale up any more without extending beyond the edges of the screen. The new, bigger UI layout fixes this issue, and looks perfect at the same scale factor:



When you maintain fixed integer scaling, your UI is never going to look perfect for all screen resolutions. I was previously designing mainly for 1000x600 resolutions, but that resulted in other resolutions having too much empty border space. Now, I've redone the menus to use up as much of the 480x300 base canvas size as reasonable, so that it looks fine even with some extra padding. Most common resolutions (720p, 1080p resolutions) will involve some amount of padding, so this works out. As an added bonus, everything feels easier to tap on for mobile as well.

Note that there are other ways to handle this issue -- for example, instead of having a fixed base canvas size with integer scale, you could build your UI proportionally (use percentage-based anchors) and then use 9-slice assets so that your buttons and menus resize dynamically. (Of course, the easiest solution is just to not use pixel-art and avoid the problem altogether.....)

Aspect Ratio Handling

I also tweaked how the game handles screens of different aspect ratios. Previously, the camera and UI only looked at the height of the screen (not the width) when deciding scale. This means that in order to support 4:3 and 5:4 aspect ratios (I know it's hard to believe, but some of us still use these...), I had to ensure that the UI fit safely into the lowest aspect ratio (5:4). This typically meant that most screens had a lot of empty padding on the left and right:



I've since modified the scaling code so it uses a 16:10 "safe area" to determine scaling. This means I can safely lay out my UI for a wide aspect ratio...



And if you're playing on a 4:3 or 5:4 display, it'll compensate by adding more vertical space, instead of chopping off the left and right sides:



Shop Rework

Astute readers will notice that in the screenshots of the new main menu above, the "Shop" button is curiously missing! In my experience with playtests, the shop menu was too out of the way for people to notice while playing. You have to drill all the way back out to the main menu in order to shop, so most people just continued to play levels without ever spending any coins (unless I explicitly pointed it out).

My current experimental redesign for addressing this by placing shops in each world as part of the level select flow:



The idea here is to funnel people to the shop after they've completed some levels (and thus should have collected a good number of coins to spend). I like that this keeps the shop out of the way at the beginning of the game -- I want the player experience from boot-up to starting level 1-1 to be as free of "clutter" as possible. It also ties into the "quest" theming of the game. Initially I placed one shop in each world between levels 2 and 3, but I've since moved them to the end of each world after level 5. I guess the idea right now is that you get a nice place to spend all of your money at the end of each world before going to the next one? This is still something I need to think about some more.

One other nice thing about this is that having per-world shops gives me a nice logical way to expand the shop inventory over the course of the game (especially important for bonus levels, which will vary in difficulty and featured mechanics). I'm not sure yet whether all shops will share the same inventory or whether you'll have to visit particular shops in order to purchase various items...

Of course, this new system isn't without its downsides compared to just having a global shop button. For one thing, it's more awkward to just jump to the shop from boot-up. It's also a bit clumsy having to scroll to the end of the world each time you want to purchase something new. In the end I might just end up nixing the entire idea and just have a shop button on the level select screen...(but that would be awkward to fit in the UI and also be accessible via keyboard...). It's something I still need to feel out and test some more.
« Last Edit: June 24, 2022, 02:23:56 PM by DDRKirby(ISQ) » Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #46 on: June 24, 2022, 02:30:21 PM »

Level 4-2

Not too much to report this week, just another level in world 4 done. I do have an update on the shop rework as well, though.

Shop Rework Update

Last week I wrote about an experiment where I moved the in-game shop to fill one of the spots on the level select screen:



There were a number of issues with this, so in the end after seeing it through I unfortunately decided to scrap it. The shop button is now simply on the upper-right corner of the level select screen:



This isn't perfect...one annoying issue is that (sigh) some phones round off the corners of the screen, so I need to make sure the button doesn't get weirdly cut off by that. I'm not a huge fan of the added clutter for this screen, but I tried to at least make the background of the coin display area translucent in an attempt to try and show the level backdrops a little better.

This ended up being the least intrusive solution (for now) for solving the issue of players not going to the shop in between levels, and I feel like the button is in a fairly intuitive place. Right now (placeholder logic) the coin text pulsates when you have 100+ coins, and in the future if I decide to add more fancy shop logic (unlocking more inventory with each world) I can point/highlight that on this screen.

One thing that might still be nice to do is have some sort of animation/ticker for the coin count when you complete a stage and get a new record -- right now the coin count updates instantly as soon as you jump into this screen, but there's an opportunity for some sort of animation to happen there.

Level 4-2

Other than that, I spent the rest of the week finishing level 4-2 (along with grinding more ALTTPR for the tournament I'm in...). As is becoming customary, here's a full video of that in action:





This level is meant to introduce the "jump slash slash slash" pattern where you have a jump followed by three flying enemies during a water zone. I tried to fit in a bunch of instances of that here and there, along with more general play with the water zones, including air jump sequences that jump in and out of water. There's also this checkpoint with a really long water section, which works nicely alongside the break in the music:



Music Design

For the music, I'm again going with the theme of more "mystical" sounding instruments, while keeping to a pentatonic scale. I used a distinctive bottle blow instrument to kick things off, and then there's also some soft sweeping pads that come in after the
intro:

https://rhythmquestgame.com/devlog/38-pads.mp3

I'm starting to really get the hang of using drum fills -- both in the samples drums as well as in the triangle-wave toms -- to accentuate the water zones. Funnily enough, I've noticed that this is causing me to do a lot more detail work in my drum programming than usual, so this is one of those cases where the level design and music really feed off of each other. Here's how those fills sound:

https://rhythmquestgame.com/devlog/38-drumfills.mp3

When the chorus comes in there's a supersaw chord synth that opens up. I'm applying sidechain compression here to give it that classic "ducking" effect whenever the kick drum plays:

https://rhythmquestgame.com/devlog/38-supersaw.mp3

That might not sound super "full" but that's because I'm intentionally trimming off a lot of the sound to make room for the rest of the instruments (mainly the lead synth). The lead is just the same square wave that I use all the time, but as always there's a lot of little articulations that give it a more rich character. Here's the entire soundscape at once:

https://rhythmquestgame.com/devlog/38-full.mp3

Backdrops

For the backdrops I went with a bunch of fluffy trees (cherry blossoms?). This is a bit of a departure from levels 4-1 and 4-3, which were both more "spacey" in vibe, with darker backgrounds, but for some reason I just had these style of trees on the mind.



I think the real key here is all of the different cloud layers, which are transparent and really give a sense of depth to the scene. These faded cloud layers are really standing out as a consistent visual theme across all of the levels in this world so far.

That's going to do it for this week! Next week I'll either take a stab at level 4-4, clean up some visual effects here and there, or maybe start to try and really polish up a public demo build...
Logged
qMopey
Level 6
*


View Profile WWW
« Reply #47 on: June 24, 2022, 02:58:00 PM »

Posting for follow!
Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #48 on: July 01, 2022, 06:14:54 PM »

Demo Build Work

What a week...well, let me try and go through some stuff here.

Release Date

Probably not too surprising to anyone (least of all me), but the estimated release date for Rhythm Quest has been pushed back from "Late 2022 (?)" to "Early 2023 (?)". Note the question mark ;P

Some life stuff came up and I have to end up moving in the next few months so this is mostly me pre-emptively throwing myself a bone so I won't worry about it as I inevitably spend a bunch of time and energy on that. I may also be taking on some part-time work in the near future, which may provide me with some extra leeway for my timeline (i.e. not feeling like I'm spending as long draining my bank account away while working fulltime on this) while still keeping a good balance. But obviously, if I'm not working on Rhythm Quest 5 days a week my progress will naturally be at a slightly slower pace. I'm not too worried given that a large portion of Rhythm Quest was built during my previous employment, but these are factor that I'm going to be keeping in mind moving forward.

Webserver Testing

This is a silly small thing, but I finally set up an =actual= webserver (nginx) on my computer to test my websites and WebGL builds locally. Previously I was just using python's simple http server functionality, which works perfectly fine...except it can't handle the gzip compression and associated headers for Unity WebGL builds. So now I just have my localhost webserver start on boot and I can navigate to any of the websites I work on locally (rhythmquestgame.com, ddrkirby.com, cocoamoss.com, katmengjia.com) and test them out without having to kick off a python process. Probably something I ought to have done earlier, to be honest, but eh.

WebGL Demo Work

It had been a long time since I had played around with the WebGL demo build, so I decided to plug away at that this week. At some point, I ran it and it looked like this:



...uh, yeah, that's not right. I think this actually just ended up being a false alarm (browser caching issue), but anyways, now it's working just fine and running in my browser locally on the demo page:



As you might be able to see (sorry, it's small), I've also done a bunch of other work to flesh out this page, including adding links to downloadable builds (which don't exist yet...) and the Steam wishlist/Discord invite callouts.

Updated Notices

I've also updated some of the text notice screens in the game, for example this one that comes up if you're playing a WebGL build:



Note that save data =should= persist across version updates normally, however this doesn't work on itch.io builds since itch uses a unique URL per uploaded build, and Unity by default persists browser-based save data based on the page URL. I briefly looked into ways to potentially work around this and then decided to just table it for now, it seemed like I should spend my time elsewhere instead...

Although I don't have (or want) DRM on my downloadable builds, I use some rudimentary copy-protection logic to avoid having web builds stolen by other websites and hosted without my permission (and profiting via ad revenue...). As I've learned from experience, this is sadly an extremely common practice when it comes to web games since they're so easy to just download and then reupload.

Of course, my simple javascript checks aren't foolproof -- in particular they can trigger false positives if you've blocked certain web browser functionality that I use to try and determine where the game is being hosted. So I wrote up some instructions on what to try in case that happens to you:



I've also updated the screen that pops up if you click on one of the worlds or features that's not available in the demo (it cycles through various screenshots here). I've added the Steam and Discord links here as well:



I also hooked up a trigger for a separate version of this that shows up after beating the last level in the demo (currently this is level 3-2). I haven't actually built out the overlay itself yet, but it'll probably have a few pages -- something to the effect of "thanks for playing the demo [...] wishlist the full version on Steam (etc)". That's something I'll be finishing up soon, hopefully.

WebGL Audio Scheduling

I wrote in a previous devlog about some of the issues I had to work around in order to get a functional WebGL build up and running, including the fact that audio scheduling seemed to be broken (specifically, AudioSource.PlayScheduled seemed to always just play audio immediately on WebGL). I checked at the beginning of the week and Unity has since fixed this issue!.........sort of. AudioSource.PlayScheduled seems to work now, but unfortunately if you want to start the play head midway through an audio clip, you're outta luck as that still doesn't work. Bleh.

On the plus side, I've gone ahead and revamped my hacky workaround for audio scheduling in a few different ways. The basic idea here is that I keep a sorted list of scheduled audio clips (along with the time at which they should be played), and then I continuously poll the list and trigger the sounds at the appropriate times, removing them from the list as I do so.

This isn't new, but one important thing to take into consideration here is audio buffering. When you trigger playback of an audio clip, there's some amount of delay before the audio data is actually played back due to buffers. It's not perfect, but you can estimate this by using the AudioSettings.GetConfiguration API and looking at the dspBufferSize field and account for this by adjusting your trigger times slightly earlier to compensate.

One improvement I ended up making this week was increasing the polling frequency at which I checked the scheduled sound list. Before I was checking this once per frame by using Unity's Update method. That works, but it turns out (for whatever reason...) that if you use the OnGUI method, you can actually have your polling code run multiple times per frame, leading to more accurate timing.

Of course, originally I was looking at AudioSettings.dspTime as my time reference, which doesn't help here because that value doesn't actually update between frames. Instead you want to have something based on a timer which continually updates -- something like Time.realtimeSinceStartup which will return different values even during the same frame. Luckily I already have a system set up for mapping audio dsp times to realtimeSinceStartup and vice versa via linear regression (the previous devlog on this), so I can just plug that in here.

It's still not perfect...in particular WebGL has a lot of issues where the beginning chunk of an audio clip won't playback properly, and seamless audio looping is often broken (maybe something to do with audio compression), but it's passable at least.

Demo Save Data/Achievements

I started setting up the demo version of the app on Steamworks (yay!), and while I was going through that, a couple of other things occurred to me to clean up:

First, I made sure that Steam achievements are disabled on demo builds (this is a recommended practice by Steam). The suggestion is to have those achivements automatically unlock when you transfer your save data over to the full version.

...speaking of which, I decided to save demo progress in a different folder than the real game (preferences are still shared for now). Previously the demo simply saved to the same location, which worked fine for a seamless carryover to the full game, but this feels a bit safer -- for example if you try to open a full game save in the demo it might cause some bad things to happen. The full game will check to see if a full game save already exists, and if not, it'll look for a demo save file as a fallback -- at which point I can do any logic I need to in order to convert from demo save to full game save as needed (hopefully not much, if anything).

I'll leave you all with this bonus screenshot of my Windows Jenkins build dashboard, which has exploded since adding all of the separate demo builds (and this doesn't even show the iOS / OSX builds...):



That's it for now...next week I'm going to continue working on and polishing up the demo build to get it ready for release!
Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #49 on: July 09, 2022, 12:14:17 PM »

Particles and Menu Tweaks

I'm continuing to polish up things here and there in preparation for the demo build!

Steam Next Fest

I also recently received an email invitation to Steam Next Fest, where upcoming Steam games can show off their demos and host livestreams. This will be happening October 3-10, which works out pretty nicely for me in terms of timing, so hopefully it'll be a chance to get a bunch more eyes on Rhythm Quest Smiley

Particle Effects

For quite a long time now I've had a bunch of placeholder "white square" particles in the game:



These show up everywhere, including on the ground when you jump/cross a beat, when you attack an enemy, when you use an airjump, etc. I've always planned to replace these at some point but never got around to it before since it doesn't really affect gameplay or anything. I've finally gone ahead and drawn some new particle sprites this week to replace them:



I've also redrawn the "slash" effect, which was fine before but was being scaled up by 1.5x (yuck) because the original sprite I had wasn't big enough. I've also added a Kirby Super Star-style "blue circle flash" to give it a little more color and impact:



The coin collection effect has also been tweaked, now looking more crisp and with some black outlines to help it show even against lighter backgrounds:



Here's all of those working in action:



There's still a couple of effects which need redrawn sprites -- such as the speed zone and water zone entry/exit effects -- but this should do it for everything that's featured in the demo.

Shop Tweaks

The shop coin count and icon in the upper-right now animate whenever you clear a level or beat your previous high score:



This is a pretty small thing but I'm hoping that having some motion here will help make sure the shop button doesn't go totally unnoticed (plus it's fun to see!).

The shop menus now have their own background as well. I was initially wondering if I should go with some sort of indoor aesthetic with this, but I was...admittedly feeling lazy, and also didn't think that would work out with the parallax scrolling effect that I currently have going on (which I like since it offers some movement in the background). I ended up just doing a very plan starfield background, which is not particularly exciting but actually sort of strangely makes sense since you scroll upwards to get to the shop menu:



I've also locked some characters for the demo (decided to still let you unlock the ever-popular Ducky and Furball though...). The price of unlocking each character has gone up, from 100 coins to 250 coins. There's something like 800-1000 coins in the demo (and much more in the full game), so I want to make sure you at least work a little bit for these unlocks!

These prices may end up changing later (which would be a little bit of a headache...), particularly if I end up implementing unlockable alternate costumes, but that's something I haven't quite figured out (I may also have other bonus unlockable content like lore / artwork). Hard to balance out the economy when you don't quite know how much stuff is going to be for sale!

Menu Tweaks

I've restructured a lot of the settings menus -- I decided to use more of a hierarchy and put a lot of settings into submenus that you can drill down into. This makes it a little more unwieldy in terms of having more screens that you need to go through (in particular I'm sad that lag calibration is no longer a primary menu item) but cleans up the initial menu a bit and I think is more logical, without creating a ton of additional work for me.



There's also a new menu item for resetting data and settings (which you can now do separately from each other). Previously this was under the "Cheats" menu, but I think it makes more sense under "Settings":



For scale/zoom settings, I've always wanted to have some sort of visual preview of what the scaling looks like, but wasn't sure how to structure the UI in a simple way to handle that (without creating a ton of work for myself). I ended up just breaking apart the UI overlay and making it partially transparent so you can see the player in the background:



Screen Filters

This probably wasn't necessary for me to implement right here and now, but since I was already working on a bunch of setting stuff, I went ahead and knocked out a todo item that I had for implementing backdrop filters for increasing readability if you find the backgrounds too colorful / distracting:



This is completely shader-based, so all I had to do was add an additional parameter or two to my existing two palette shaders and then implement the different filter effects based on that.

The Fade filter works by moving all colors closer to the primary background color, so for a level with a light sky background, everything will be lightened, and for a level with a dark night backdrop, everything will be darkened. Of course, in order for this to work, the shader needs to know what the "primary background color" is, and I currently don't have a "rule" for what palette index this occupies. I could specify (per-level) which palette index to look up, but I happen to have an unused palette slot, so I just made it so that palette index 9 is the background color lookup, and then copied the appropriate colors into the per-level palette data.

Darken is as simple as you can get -- it just multiplies each color component by 50% so that you get only half of the brightness. Nice if you want something that's a little easier on the eyes in terms of overall screen luminance.

Desaturate uses a quick calculation to try and push the colors a little closer to their grayscale equivalents (without going all the way to gray). I'm not sure whether anybody will like this one but I decided to include it for completeness anyways, since often when backgrounds are too visually busy it's because they're oversaturated with color.

This was a short week for me (had one or two days where I didn't really work) but I'm glad I still managed to have some stuff to show off anyways!
Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #50 on: July 22, 2022, 05:15:43 PM »

More Demo Polish

I took a week off last week to -- among other things -- enter GMTK Game Jam 2022, with our dice-rolling cooking game "Dice it Up", made in 48 hours:



So uh, go check that out if you'd like! :D

As for Rhythm Quest...I'm very close to having a demo build that I'm ready to show off to the public! I've already done some internal testing and have just been working to tidy up little things here and there.

Calibration UI Tweaks

One thing that came up during testing is multiple people not quite understanding the intended usage of the calibration UI and tapping every 4th beat instead of on every beat:



I've added some circular pulsing indicators here in an attempt to hopefully make that more intuitive. I also replaced the "line" markers with circles, just felt like it looked like a better animation to lay down a circle. It's a little busy for my tastes now (maybe I'm overcompensating...) but I can always iterate more on this later:



As an extra fallback, I end up accepting the calibration now even if you only use one of the 4 reference points, as long as you do it enough times.

More Settings Menus

I've been continuing to clean up some of the settings menus even more...for example, I've added a new submenu for configuring haptic feedback (vibration/rumble), which shows only for mobile and switch (I haven't found gamepad rumble to feel very good):



Gamepad Tutorial

Gamepad has been supported as an input method for a long time, but I've only recently gotten around to making the separate tutorial dialogs for it:



I haven't tested it yet, but this should also in theory detect if you're using a Dualshock controller or Switch Pro controller and show the appropriate icons instead. Unfortunately the last dialog here is currently a lie as I don't allow gamepad rebinding yet...(more trouble than it's currently worth to implement...)

Audio Cue Rework

A long time ago I added an audio cue system that allows visually-impaired persons to play Rhythm Quest. This has been pretty half-baked for a while, and I felt bad having only a janky single on/off toggle in the "Accessibility" menu, so I went and gave it some more attention:



I'm sure this system could still be refined more -- for instance, it might be better to have volume / panning configurable on a per-cue basis rather than globally -- but for now you can at least change the global cue volume balance and select from a wide selection (19!) different cue sounds ranging from short arpeggios and pitch slides to percussive hits. I haven't played around with these much yet so I have no idea how well they work, but it's certainly more versatile than before.

Backdrops and Screenshots

I've added some more variety in the menu backdrops as well, rather than just using the level 1-1 set for everything:



Aaand I've taken some new screenshots for the "end of demo" popup, showcasing the new mechanics that I've developed for the full game (which weren't implemented at the time that I previously took screenshots):



Other Stuff...

I've done a bunch of other miscellaneous work as well:

  • Setup the build deployment pipeline for demos (Steam, itch.io)
  • Audio volume now starts at 70% by default instead of 100%, to give you room to adjust both ways
  • Fixed links not opening properly on mouse clicks for WebGL builds
  • Had to downgrade Unity because newer versions inexplicably drop mouse input near the upper-right corner of the window =/
  • Made a new public changelog listing separate from my internal changelogs
  • etc...

Overall things are looking very good and I wouldn't be surprised if I'm able to get this out in the next week or two!
Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #51 on: August 20, 2022, 12:24:19 AM »

Demo Release

I missed the last 3 updates due to a whirlwind of a month:

    Released the Rhythm Quest Demo
    Won the Zelda: A Link to the Past Randomizer tournament I was competing in!
    Started a new part-time job
    Had to grieve for a personal loss which left me bereaved

Let me see if I can recap some of the stuff that's been going on...

Demo Release



I published the free playable demo for Rhythm Quest, and it's received some really nice reception! I'm really glad that people enjoyed playing through the demo levels, and it's also been good to take a short break after accomplishing my demo release.

Something that was nice to see was having the demo release single-handedly kick my Steam wishlist count from 1,000 to 2,000:



Something I was a little surprised to see was how many people were trying to play the game using the (unfinished) screenreader support that I've been integrating with the aid of the UI Accessibility Plugin package. This was actually a bit concerning since so much of the game still needed more work before being ready for prime-time with screenreader support (especially for users who are blind), but the people who did manage to fumble their way past the various issues really appreciated it. I decided to spend a week or two cleaning this up since there was clearly more demand for it than I had expected.

Screenreader Improvements

First off, I've added a new scene that pops up before anything else if screenreader software is detected. The screenreader voiceover functionality will always be enabled for this scene:



The accessibility menu has some new options, including a menu that will let you manually toggle screenreader mode, as well as enable a new mode that retains normal keyboard navigation but still reads aloud the selected item.



In the previous devlog I showed off the new audio cue configuration screen:



Unfortunately (and somewhat ironically), it turns out that the screenreader-based navigation for this particular screen was comically bad, with options being selected out of order, and several elements not being read correctly. Having to raise the volume balance (defaulting at 0%) for any of the other options to have an effect was also unintuitive, so I've gone back to having a global toggle for the audio cue system in addition to the volume balance. Hopefully it should be a little more useable now...

I've also fixed up a lot of other areas where the screenreader functionality was lacking, such as the world and level select screens, as well as the "how to play" tutorial (which previously didn't have any voiceover integration at all). There's still much more work to be done here overall, but I'm going to table this for now and turn my attention to other things instead.
Build Automation Cleanup

I've finally gotten a new macbook to replace my aging one from 2012, which I've been using up to this point for all of my OSX and iOS builds. Besides being a little slow, the old machine only had a 256GB hard drive split across two partitions (OSX vs Windows), so there was barely any space for any builds.

Since I was setting up a new machine (as well as all of the associated stuff like Jenkins, Unity, git, fastlane, etc.), this was a good opportunity for me to also clean up my automated build system so that it's a little more maintainable.

I've been using fastlane to drive a bunch of the build steps (particularly for iOS/Android builds), and Jenkins to manage build jobs and workspaces. However, I now have something like two dozen different Jenkins jobs to manage all of the different Rhythm Quest builds (demo builds, steam builds, mobile builds, etc.) and each one of them had a different Jenkins config involving various shell commands to tell Unity (often a hard-coded Unity path) to generate the build and then get it copied/moved to the appropriate folders.

Updating a bunch of disparate Jenkins jobs was quickly becoming unwieldy, so I've switched to having most of my logic in my centralized `fastlane` config file (which is version-controlled). I've also cleaned that up and started breaking down the logic into different subfunctions so that everything is more manageable, so I might have common functions/lanes like:

Code:
# Invoke Unity with a given build_target and build_script function
private_lane :unity_win do |options|
  system "#{unity_path_win} -projectPath .. -batchmode -nographics -quit -buildTarget #{options[:build_target]} -executeMethod BuildScripts.#{options[:build_script]} -logfile -"
end

# Move a build from ../Builds/platform_name to network-share/Builds/platform_name/build_number
private_lane :movebuild_win do |options|
  src = "\"../Builds/#{lane_context[SharedValues::LANE_NAME]}\""
  dst = "\"#{builds_path_win}/#{lane_context[SharedValues::LANE_NAME]}/#{options[:build_number]}\""
  latest = "\"#{builds_path_win}/#{lane_context[SharedValues::LANE_NAME]}/latest\""
  system "mkdir", latest
  system "mkdir", dst
  system "robocopy #{src} #{latest} /MIR /XD \"*BackUpThisFolder_ButDontShipItWithYourGame\""
  system "robocopy #{src} #{dst} /MIR /MOV /XD \"*BackUpThisFolder_ButDontShipItWithYourGame\""
end

The individual lanes for each build are then extremely simply to write:

Code:
lane :win64 do |options|
  unity_win(build_target:"Win64", build_script:"Win64")
  movebuild_win(build_number:options[:build_number])
end
lane :win64demo do |options|
  unity_win(build_target:"Win64", build_script:"Win64Demo")
  movebuild_win(build_number:options[:build_number])
end
lane :win64steam do |options|
  unity_win(build_target:"Win64", build_script:"Win64Steam")
  movebuild_win(build_number:options[:build_number])
end
lane :win64steamdemo do |options|
  unity_win(build_target:"Win64", build_script:"Win64SteamDemo")
  movebuild_win(build_number:options[:build_number])
end

Moving Forward

I honestly had a hard time remembering exactly what I was working on before the demo release came up. There are a lot of little things here and there (lots of feedback came in from people playing the demo as well), but I think my first priority here is going to be to get back to working on more levels. I think the next one is supposed to be level 4-4, where I'm supposed to experiment more with flight paths / jump sequences that go in and out of water zones.

I'm going to continue taking it a bit easy for now though -- I've got some more travel coming up, and will be moving residences after that (Ludum Dare is also coming up in a little over a month), so I'll have plenty of real-life stuff to take care of.

I'm actually fairly concerned about my ability to maintain a good pace of progress on Rhythm Quest due to my new job (currently 3 days a week) which on paper cuts my time by over 50% (!). This isn't something that I take lightly, and is going to have to be something I evaluate moving forward to see if it's really working for me or whether some changes need to be made. We'll see if for example I'm still able to get one level per week done. I'll also probably have to rethink my devlog writing time, as before I always used Fridays as devlog-writing days -- that doesn't make as much sense when I've only got 2 full days per week for Rhythm Quest...

On a more personal note, though, my recent experience with grief and bereavement have also put some thing into larger perspective for me and have reminded me that in the end my goal in making this game is primarily for my own enjoyment and satisfaction (and everything else is secondary to that). Of course, it's still very important to me that I'm able to consistently make concrete forward progress here, but past that maybe I don't really need to worry so much. Well, wish me the best of luck going forward, I guess?
Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #52 on: September 09, 2022, 10:19:01 PM »

Unpause Animation, Bugfixes

I debated taking the time to write another devlog since I don't have that much to report on, besides the fact that I'm spending a bunch of time on packing and moving and such. I worry about making devlogs that read more like blogs than anything else, but I =did= manage to squeeze in some Rhythm Quest work here and there, so let's cover it quickly. I get antsy when I go for too long without returning to one of my regular activities, and devlogs are a part of that, I think.

Unpause Countdown

There was a pretty sensible feature request for some sort of countdown when unpausing the game. Normally this would be pretty easy, just add a 3-second delay and some text that counts down "3, 2, 1" along with some tick/beep sounds before unpausing the game.

But this is Rhythm Quest we're talking about; the pause music maintains the same beat as the original song, and unpausing also relies on that sync, and waits until the pause music loop gets to an appropriate beat in order to drop you in seamlessly back into the level track, regardless of when you paused (on a beat, off of a beat, etc.). Because of this, the duration of the unpause delay varies depending on when you pause and unpause, which is probably part of the reason that a countdown timer is desirable.

The ideal solution here would probably be to count you in based on the beat of the song, making sure that unpausing takes at least 3 or 4 beats. That...seemed like a lot of work to me, so I was a little more lazy...I kept the already-existing unpause timing logic and simply added a bar that fills up:



Not the prettiest, but it'll do, at least for the time being, though I admit that in the process of writing this devlog I'm wondering if the countdown really would be that much more effort...maybe something to look at later. Anyways, the screen tint also fades away as you jump back into the action, which I think works nicely.

Input Buffering

I probably haven't mentioned this before, but you can actually buffer input during a respawn. If you press jump or attack before you're technically actionable, the Player class will store a flag and process the input on the first possible frame after respawning instead. With the added unpause progress bar, it seemed like it made sense to add that functionality to unpausing too. That wasn't too difficult, just added a different (new) condition to the input buffering logic.

One thing I did realize was that I also needed to add input buffering for jump releases for unpausing. Previously I didn't need to worry about this because, well, there's no reason to buffer a jump release after a respawn, as you'd never be on a flight path. With unpausing you =can= be in the middle of a flight path, however, so I went ahead and implemented that.

This is deceptively a little more complicated than the other cases because the jump release behavior depends on whether the jump input is held down or not. Because of how the input system works, I don't actually detect jump releases based on polling the input state every frame; instead I receive discrete key release events. This means that if you released the jump button while you were in the pause menu, I would ignore that event entirely and you'd still be flying after you unpause. That's fixed now -- I toggle a flag for jump release buffering each time you press or unpress jump during pause/unpause so I can just "do the right thing" when you regain control.

Of course, if you're using different jump inputs across multiple devices (keyboard / mouse / gamepad) that's another story, but at that point there's really only so much I can do to help you, haha...

Bugfixing

I've also had some time to look at a few bugs, such as a lot of interaction sounds being completely missing if you disable sfx prescheduling (which I don't recommend, and therefore don't often test).

One of these was a report that the screenreader text to speech (TTS) functionality was broken on Mac/OSX, which I confirmed. This was odd to me since the UAP accessibility plugin that I'm using claims to support Mac just fine. It was also working just fine in the Unity editor on Mac, so clearly it was implemented fine...something was just going wrong somewhere along the way.

Digging into it a little more, I encountered this cryptic error:

Code:
[Accessibility] TTS Error: System.ComponentModel.Win32Exception (0x80004005): ApplicationName='say', CommandLine='-r 175 "Start Game"', CurrentDirectory='', Native error= Success
  at System.Diagnostics.Process.StartWithCreateProcess (System.Diagnostics.ProcessStartInfo startInfo)
Not super promising since the error code 0x80004005 didn't seem to be specific and the "Native error= Success" field wasn't particularly elucidating. Looking at this (and the UAP plugin code), it looks like UAP is trying to use the built-in "say" command to invoke the Mac VoiceOver functionality:

Code:
m_VoiceProcess = new System.Diagnostics.Process();
m_VoiceProcess.StartInfo.FileName = "say";
m_VoiceProcess.StartInfo.Arguments = parameters;
m_VoiceProcess.StartInfo.CreateNoWindow = true;
m_VoiceProcess.StartInfo.RedirectStandardOutput = true;
m_VoiceProcess.StartInfo.RedirectStandardError = true;
m_VoiceProcess.StartInfo.UseShellExecute = false;
m_VoiceProcess.StartInfo.StandardOutputEncoding = System.Text.Encoding.UTF8;

System.Threading.Thread worker = new System.Threading.Thread(() => WaitForVoiceToFinish(m_VoiceProcess)) { Name = "UAP_TTS_Proc" };
worker.Start();

I figured this was some sort of permissions/sandboxing issue where the app was failing to spawn an arbitrary process due to OS restrictions or something like that, but this actually worked fine on a blank project, so I had to keep digging to see what the difference was (and hope it wasn't something too hairy).

Well, the good news is that it was just a single setting in the project settings file. The less good news is that the setting was the scripting framework being used. Turns out that System.Diagnostics.Process (and spawning a new process in general) is unimplemented in Unity's IL2CPP scripting backend and fails silently, whereas this works fine under Mono.

This is annoying. In a vacuum I'd rather use the IL2CPP backend -- it uses ahead-of-time compilation and is generally more performant, whereas Mono uses just-in-time compilation, which can lead to some niche issues (serialization/deserialization issues due to how reflection is handled). But poking around didn't seem to reveal any promising solutions for other TTS implementations on Mac that I could plug in here. I decided to switch the scripting backend to Mono to get the TTS support working and hope that everything else didn't suffer too much (so far it's looking okay...). The silver lining here is that Mono builds tend to be smaller on disk, so at least we get that.

Still hanging in there

Yeah, this update probably wasn't super interesting, and I haven't had much in terms of Rhythm Quest content lately at all. This is probably going to be the case for the next few weeks as I finish my move, so you'll just have to sit tight for now (sorry!). I have been seeing the demo pop up as something that people have been playing on twitch sometimes, so shoutout to anyone who's streamed some footage of it! I do have a new idea for another character to add in, so maybe I'll end up working on that next!
Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #53 on: October 02, 2022, 03:25:16 PM »

Just a quick announcement:

As part of the Steam Next Fest​ event, I'll be doing a developer livestream of Rhythm Quest on Tuesday Oct 4, at 6PM PDT/9PM EDT.

I'll be going through all of the currently-finished levels, including 10 new stages that aren't included in the public demo!

You can catch the stream on Steam, or on Twitch at https://www.twitch.tv/ddrkirbyisq​

Hope to see you there! :D
« Last Edit: October 02, 2022, 03:32:30 PM by DDRKirby(ISQ) » Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #54 on: October 11, 2022, 07:35:58 AM »

Steam Next Fest

I finally finished moving, have been continuing to work my new 3-days-a-week job, and have more recently been taking some much-needed vacation!

Somewhere in the middle of all that, an event called "Steam Next Fest" happened. This was a weeklong event on Steam for upcoming games to provide free playable demos and do livestreams to garner attention (and wishlists). Rhythm Quest already had a ready-to-go public playable demo, so it seemed like a no-brainer to opt into the event.

Dev Livestream

The livestream event itself went off mostly without a hitch (I say "mostly" because I initially botched the date when scheduling the Steam event, oops), and it seemed like everyone was excited to see all of the content that I had to show off, which included everything I've made thus far (so, much more than than what's featured in the public demo). You can view the video for that below:





Increased Visibility

While the livestream was great to do, it seems like the real consequence of Steam Next Fest has been increased public visibility for my game -- it seems like a lot more people are getting their hands on the demo (and consequently giving the game a wishlist). This was great to see, and I garnered more wishlists through this period than any other in the project's history, managing to recently surpass 4,000 wishlists:



It's been great seeing new people discover the demo and having good things to say about it; there's even some people posting in the Steam forums for the game now, which is a bit surreal to see. I've also been seeing a ton of Japanese posts about the game on Twitter, which is a pleasant surprise as well (JP players, rest assured that a Japanese translation will be included in the full game!). It's nice that the game seems playable even for non-English speakers -- means that my visual mechanic tutorials are working out so far.

This kind of stuff is great to see since I know garnering attention by myself isn't my strong suit, so if anything is going to get Rhythm Quest to spread a little more it's just going to be people enjoying the game then recommending it via word of mouth.

Mouse Cursor Hiding

Based on some comments that I've been seeing floating around, it seems like more people are playing the game with their mouse than I initially expected. I imagine this is partly because people are more inclined to click on buttons than interact with them via keyboard nowadays -- doubly so for the WebGL demo -- so they get funneled into the mouse version of the UI flow (though the UI will change wording based on whichever input device you're using). I saw some requests for the ability to hide the mouse cursor, so I'm adding a new option for that in the settings menu:



That was mostly a pretty quick thing to implement, though I still need to test it on WebGL builds to see if it makes sense to have there (it probably doesn't play very nice with browser restrictions and gives you some annoying popup).
Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #55 on: October 27, 2022, 08:29:18 PM »

Alpaca, Localizations

It's been a challenge to juggle Rhythm Quest alongside my job, but I still have some progress to report on!

Alpaca

I've got a new set of character animations in the game! I actually went to see some alpacas at a farm not too long ago, and decided it would make for a cute new character:



I decided to go with a tan-ish color...alpacas come in several colors but I figured this one would be nice since it's different than the rest of the characters that I have so far.



The running animation is mostly just basic leg movement, but there's some secondary motion with its tail and neck that help to give it a sense of weight. The slight bit of elasticity / delay between the chest movement and the head bounce I think is the main thing to focus on.



This was a fun one, haha. The anticipation frame and smear are pretty important here; the motion is a lot smaller without those. The overall form of the animation is similar to Ducky, with the horizontal stretch happening at the point of "impact". For the water, it starts as a solid wavefront and then splits off into distinct streams, which fade into droplets. It's actually somewhat challenging to get the spacing to look right for thi sone, since the enemies are really more positioned for a bite than a spit attack. Still, I think in practice it's fine.



Experimenting with having the alpaca's legs flail around while jumping was really weird, so instead I kept everything stationary and instead just focused on subtle fur movement so it doesn't look static. There's a brief crouch frame used here; that one doesn't really need to be very clean since it's more of a quick flash of motion than an actual animation frame.



Flying is the same as jumping, just with the wings added.



And same thing with the flying attack, I just added the wings onto the normal attack animation. It's really nice that I can just copy-paste the wing frames and have them look fine with only a couple of tweaks...

Community Localizations

Over on the Rhythm Quest Discord we had some interest in translations of the game, so I decided to put together a quick and dirty google sheet for people to openly contribute translations as they like. This is more of a temporary solution than anything else -- in the future I'll need to either appoint specific people to manage each language's translations, or simply use a professional service -- but the demo text has already been fully translated into 7 other languages, which is awesome to see. Those have been pulled into Unity and should be available in my next demo update, which I'm sure will be a welcome addition since I know I've got quite a few international players interested in the game.

Of course, different languages add a whole host of new challenges for me to handle...

Diacritics

First off, the pixel font that I'm using throughout the game is Softsquare / "Soft square cakes" from Chevy Ray's pixel font pack. It's a fine font, but unfortunately it's missing versions of letters with all of the diacritics, so it can't render characters like á, è, ö, ñ, and all that, not to mention stuff like ¡, ¿, and even ß. I have a fallback font for unicode characters (including East Asian glyphs), but it would be nice to have these written in the same style as the other English letters.

And so, I opened Fontforge and added them to the font myself...



So yeah, add "font design" to the endless list of skills that I've used throughout this project.

Anyhow, that is all looking mostly fine now:



They don't render as well at a 1x scale (if you're playing at 500x300, for example), but that's acceptable for me. That topic does bring me to my next point, though...

Unicode Pixel Font Sizing

While diacritics render "not well, but alright" at 1x scale using a pixel font, unicode characters like East Asian glyphs are just plain unreadable at this scale with my current unicode pixel font:



Yeah, that's a problem. Of course, I could just double the font size here and be fine, but that would lead to characters taking up much more space than I'd like:



My solution here was to implement custom code in my font-switching script that detects whether you're using a 1x UI scale, and if so, forces all labels using these unicode glyphs to use a smooth font instead of the pixel font:



So now even if you play in Chinese using a 500x300 resolution, things will be somewhat readable. Of course, probably nobody is going to play my game in 500x300 to begin with, but hey, if you do, it's going to work properly now!

That unfortunately wasn't the last of my issues, as my CJK (Chinese, Japanese, Korean) font was inexplicably missing characters that I thought it ought to have covered, so I had to spend a bunch of time debugging that and finding a different download...but I think that should be fixed now as well. Phew......

That's going to do it for this update. There's still more work to be done for localization (mostly, fixing up the sizing of labels to make sure everything fits regardless of language), but it's a lot closer to being done than before. Now I just have to get back to working on the rest of the game...
Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #56 on: November 13, 2022, 11:43:13 PM »

Performance Optimizations

Time for a devlog on performance optimizations!

Rhythm Quest has -- fortunately -- actually been running pretty smoothly on most platforms so far. Other than the occassional "I need to make sure this gets loaded early so it doesn't cause a hitch during gameplay" issue, the only other major performance work I've done has been trying to optimize the fragment shaders used to draw the level backdrops, since I noticed it was causing some slowdowns on some Android devices.

There is one place, however, where I've known there to be FPS drops for a while, mainly on Nintendo Switch...

Fillrate/Overdraw Issues

Somewhat counter-intuitively, the main gameplay runs perfectly fine on Switch and it's only the menu scene that causes it to perform less optimally. Specifically, the transitions between different backdrop sets:



Each level backdrop group alone renders fine; it's just the transition between two of them that caused things to chug a bit. As you might guess, the problem is worse when it comes to backdrops that use lots of layered graphics, like the ones in world 4, and even worse when you transition multiple times in quick succession...

The problem here mostly boils down to fillrate or overdraw. The GPU has to render each one of these different (fullscreen) backdrop layers to the screen, and because most of the textures use transparency, it has to render them back-to-front, and ends up "redrawing" many pixels where layers overlap:



On most other platforms this ends up being fine (it helps that the draw calls are batched here, and use a single texture atlas), but for whatever reason the Switch seems to struggle in this department. Anecdotally, I've noticed in Pokemon Unite that UI transitions also frequently cause frame drops on Switch and not on mobile, so I'm not entirely surprised to see this being an issue.

Solutions and Problems

So we're slow because we draw a lot of background layers to the entire screen. What can we do to fix that?

One option is to look at making the pixel/fragment shader faster. During the main game, I use a custom palette shader to transition smoothly between different color palettes at each checkpoint. I use a similar shader for the menu, and transition between different color palettes for each level/screen (along with fading in and out the background layers). This isn't strictly necessary though -- instead I could just export extra versions of all of the backdrops with the appropriate colors included, and then do a plain fade transition between them (i.e. drop the palette logic from the menu scene entirely). I haven't looked into this because it would be a pain to create all of those extra copies of the backdrops (not to mention it would increase the app size). So I haven't really done that much here.

Something else that could be done is to try to avoid drawing everything to the entire screen. If you take this background layer from level 4-2 as an example...



...you'll notice that most of the image is actually completely transparent. Despite that, the texture is authored at full-size (it's actually 500x1200...), so the shader is still running through (and doing texture lookups and everything) for all of those transparent pixels (without rendering any actual output). It would probably help a lot if I took all of these backdrop textures and exported them as smartly-cropped versions, so that each layer only has to render to a portion of the screen rather than all of it.

There are two reasons I didn't go with this approach. The first one is that I'm using automatic sprite tiling to tile the backdrops horizontally, so cropping these trees out for example would mean I would have to rework how that happens. Vertical crops are maybe not as bad, but the other issue is that doing this sort of cropping seems like it would be really tedious. My workflow for authoring these assets is set up such that I export them all at fullsize from the same project file and it just doesn't seem worth it to try and manually adjust a ton of these layers unless I really have to. It would be nice if Unity could trim the transparency out of the sprites as necessary and then embed some metadata such that sprite rendering would still act as if it was the original size, but that doesn't quite work out from what I can tell (again, tiling is an issue).

Render Texture Hack

Since the slowdown only happens during transitions between two different backdrop sets, I wondered if I could cheat a bit in order to reduce the number of background layers that are drawn in that time.

My idea here was to capture a snapshot of the first level's backdrops using a render texture, and then just use that static snapshot during the transition instead of continuing to draw all of the individual backdrop layers.



Since I already knew each set of backdrops renders fine individually, this would pretty much guarantee that the transitions should be smooth since we're now only adding one additional fullscreen draw during transitions (the static snapshot). As a nice bonus, if you trigger a second transition before the first one is done, I can just re-snapshot the current intermediary state and have that fade out, so it all still works fine.

The one downside here is that the static snapshot doesn't scroll sideways with the rest of the camera movment like it's supposed to be. This is something that can't be avoided...each parallax layer is supposed to scroll at a different rate, so it would look weird to scroll the static snapshot at all. For me this is an acceptable tradeoff, and isn't super noticable since you still get the horizontal motion from the new level that's fading in. That said, I do prefer to do the full transition (without the snapshot cheat), so for now I'm only enabling this optimization for Switch specifically.

UI Slowdowns

With that issue solved, most of the transitions were running pretty smoothly on Switch! However, I noticed that transitions to and from screens with lots of UI elements were still a bit choppy. Transitions like this one:



There's a couple of different things going on here. One is the same fillrate/overdraw problem, this time with all of the UI elements (each button features multiple sprites, plus all of the text needs to be rendered as well, and the icons...). Another problem is the scrolling of the UI...normally all of the draw calls for a UI canvas are batched up and cached between frames, but once you start moving or scaling UI elements around, that all goes out the window, so Unity has to redo a bunch of stuff every frame.

I spent some time trying a similar approach that I did for the backdrops, where I would snapshot the UI menus to a static render texture, and then just display that during the scroll, and then swap back to the actual UI elements once the transition was done. But this turned out to be too heavyweight -- it made the scrolling itself smooth, but there was a big hiccup at the beginning of the transition because of the extra draws to the render texture.

Luckily the fix here ended up not actually being too hard -- I just dug into the profiler and cached some things, optimized some functions here and there, and turned off some things that were running in the background needlessly (the shop coin display was updating all of the time, even outside of the shop...). I also disabled some logic (such as the animated pulsing effects) specifically during transitions, since they aren't too noticeable during that time anyways. All of that ended up helping out enough to the point where I'm not worried about Switch performance anymore. Hooray!

That's going to do it for now! The next devlog is probably going to be on level 4-4, which I've actually already completed the chart for (just needs backdrops and some polish now!).
Logged
DDRKirby(ISQ)
Level 0
***



View Profile WWW
« Reply #57 on: November 22, 2022, 03:53:10 PM »

Level 4-4

Before we start, I've got a quick announcement: I'm now accepting applications for translation heads! If you'd like to volunteer to be in charge of the localizations for a particular language, please go to this form to learn more details and apply!

It's been too long (5 months, somehow...) since I last completed a level, but I'm finally back at it, this time with the second-to-last level in world 4. Here's a video of level 4-4 in its entirety:





Level 4-4 takes a slightly slower tempo (110 BPM, vs 128 BPM for level 4-3) and cranks it up a notch with the interplay between water zones and air jumps/flight paths. It also specifically leans into a few syncopated rhythms, such as this flight path riff:



One of the "rules" I'm forming for myself as I chart these levels is that syncopation is that off-beat rhythms are mostly off-limits when it comes to attacks or ground jumps because of readability concerns, but they're much easier to interpret when it comes to air jumps and flight paths because the height differentials give you an indication of the relative beat positioning of the notes.

Of course, water zones change up the visual representation of those beat positionings, which is what this level is all about:



Visually, I wanted to do a skyline theme, as I hadn't done that before. World 4 has a little bit of a visual identity crisis at the moment, flipping back and forth between "alien space world" and "cherry blossoms", so I don't know if this truly fits in, but as with a lot of things, I'm just going to roll with it now and question it later.

I was inspired to do this pink/purple color scheme, which feels vaguely scifi-esque to me. There are a bunch of examples I found by other artists of this sort of look (please let me know if you find the original artist for either of these works so I can credit appropriately):




My process was essentially to draw a bunch of layers of semi-random tall rectangles, then afterwards go back and add some sporadic details along the tops of several of them. There isn't actually a ton of detail here -- I decided to just stop after adding a few as it seemed to work well enough. The only other real thing going on is the sun in the very back, and then a bunch of layers of semi-transparent clouds (which are all over the place throughout world 4 -- that part at least is visually distinctive).



The color palette here is pretty straightforward by now: notice how the hue goes from purple to reddish-pink as we fade into the background layers. The colors get brighter and less saturated for the back layers.

Overall I'm happy with how this one turned out (I feel like I say that every time...), but I'm mostly just happy that I still managed to complete another full level. There's only one level left to do for world 4, so I think that'll probably be next on my list...
Logged
Pages: 1 2 [3]
Print
Jump to:  

Theme orange-lt created by panic