GMLMove character on Rhythm with BPM

Spongyoshi

Member
Okay so, my new project is planned to have a rhythm-game, here's how I want it to work:
My character's sprite goes forward automatically and has an hitbox of 1 pixel of width.
Every 25 pixels, there's another sprite placed and when the two sprites collide, it does an cowbell sound.
I want my character to move so that the cowbell's tempo is set to 175 bpm.
Problem is, it's always thrown off-tempo after half a minute and I've did so much trial and error that I've put this part of the game on hold at the moment.
So, to anyone who already did an rhythm-based game, anybody would have an idea of how to make this work (Like an idea of how to calculate the speed needed for my character) or if you have a better alternative?

The-any-Key

Member
I used audacity and time labels. Then checked the played length.

Spongyoshi

Member
Uh, I don't see how that could help. Could you be a bit more specific please?

The-any-Key

Member
With audacity you can place time labels. These labels can be exported as text. You can then use the time data and compare it to the current length played.

Relic

Member
175 bpm = 2.917 beats per second = 0.0486 beats per game step (assuming 60 FPS)

It will take 1/0.0486 = 20.58 game steps to complete one beat. So move 25 pixels per 20.58 steps, which is 25/20.58= 1.215 pixels per step.

Speed should be 1.215

MirthCastle

Member
Good mathing @Relic

@Spongyoshi - taking @Relic advice, you may be even better off finding a nice beat that rounds off nicely according to his math. I can imagine errors will appear after time using all those floats.

like 180 bpm = 3 bps = 0.05 beats per step
1/0.05 = 20 steps for one beat - 25 pixels in 20 steps = 1.25 pixels per step

I love all those 5s and 0s at the end of those numbers

The-any-Key

Member
Note that if the player move the game window or if the game get a lag spike for just a second the sound will be out of sync. Better use sound length so the sound is always in sync with the beat.

Spongyoshi

Member
Woah great job on that one! And seems like a good idea! Thanks a lot you guys and I'll try to put it at 180 bpm if it doesn't work properly.
And to @The-any-Key I know there's this possibility but... How do "sound length" works? I didn't even knew about time labels in the first place

The-any-Key

Member
Ex of a label in audacity that is set on a beat.
00:01:43
you can export this text and load it. You need to handle this however.
Now when you play a sound you can get the current played length with: audio_sound_get_track_position
You can then check if it has passed 00:01:43 and make a beat. Or if the window has been holded to long (ex 5 seconds has passed) and skip that beat and check for the next beat.

Spongyoshi

Member
I'd have to put a lot of labels then And you can check labels on Game Maker then?
But, "audio_sound_get_track_position" would mean it's searching for a label and not a position in the sound itself?

The-any-Key

Member
I'd have to put a lot of labels then
I didn't say it would be easy. I think there are some label plugins however so you can add labels with specific intervals.

But, "audio_sound_get_track_position" would mean it's searching for a label and not a position in the sound itself?
The script give you the current position of the played sound. And you have labels with time stamps.

When you start a sound you know its from position 0.
You load your label list and say the first beat is in 00:01:04
Each step you check the sounds position.
If the position is 00:00:34
You now that 00:01:04 has not passed yet. So you wait some more until audio_sound_get_track_position return 00:01:04 or something later than that.
Then you do the beat animation or whatever it could be.
Then you take the next label. Say it's 00:01:40.
The sound is still playing.
You still check the sounds position each step and now wait until 00:01:40 come in the sound...

Spongyoshi

Member
I see. Seems an optimal way to do it but also a very complex one. It works fine as it is for now but if it doesn't anymore, I'll go with your route!