It’s time to talk about code stuff again 🙂
The core component of Valkyrie, being a rhythm game, is the note generation and scrolling. Unfortunately, I have been having a good deal of trouble implementing this system. But that’s not to say there’s no progress…
Since my last dev blog post about this, I have re-implemented arrow scrolling yet again (3 total iterations so far), and this time it’s hopefully the final solution to the issue. This previous dev blog post details the previous two iterations of the arrow scrolling system, and I recommend you read it if you want to make sense of what I’m about to talk about.
So the whole “invisible line” system worked well for the most part, but that was when I was feeding it dummy data. In the real-world use case, these arrows would need to be generated in real-time, which presented some challenges. For example, things like BPM changes and speed mods (which can change during the song in this game) would affect the time at which the arrows would need to be generated. This was creating issues figuring out when exactly to generate arrows, lest you generate too many too early and they very slowly move from emitter to receptor, or you generate them too late and they suddenly pop into existence and blaze across the screen.
So what I’ve settled on is a hyrbid solution of sorts, combining the first two iterations into one. Before the song starts, all arrows are now generated ahead of time. Using the BPM and the beat offset of a note, we can determine the exact time at which a given arrow should cross its receptor, and this information is handed off to the arrow. Instead of creating a line from the emitter to the receptor, the arrow now creates a line coming out of its receptor, passing through its emitter (which is now more of a node than an emitter, really), and continuing past it. The length of the line is arbitrary and determined by the difference between the current time and the time offset the arrow was given upon generation. As time progresses, this line shrinks and eventually becomes zero-length, which is when the arrow will be completely inside its receptor.
It’s great in theory, and my implementation is somewhat working. The hold up right now is trying to determine the time offset. In its simplest form, we can divide the BPM by 60 (to turn beats-per-minute into beats-per-second), take the reciprocal (to turn beats-per-second into seconds-per-beat), and then multiply by our beat offset. However, nothing can be that simple of course. BPM changes and Stops are the two roadblocks here, particularly the BPM changes. Right now I have the concept of what to do formulated in my head, but I’ve been having quite a bit of trouble building it in code. Of course, now that I’m writing this post and am stuck at work, unable to work on the code, I’ve got some new ideas for potential fixes. Regardless, I’ll keep on throwing ideas at it until I get it working.
Hopefully I’ll see you guys tomorrow for Screenshot Saturday with a working implementation!