#Rhythm Game precise timings?

1 messages · Page 1 of 1 (latest)

slender sparrow
#

Basically I am creating a "game" where you hear a sequence of sounds and then you have to play those yourself in the same rhythm. I tried to implement a basic "metronome", but it is deviating noticeably over time. Also, I wasn't sure how to implement the playback feature as I'd like to support more than just on-beat sounds. Any ideas?
Godot 4.2, C#

true gale
#

Hi there 😊,

Without any code it's hard to help, context is important.

Did you put your sound giver in a Timer.on_timeout callback?

Is it in a _process_physics(delta) of a node?

Do you use a plugin for sound playback?

final slate
#

Hmm... Here is my idea, works for anything that involves me using rhythm to a song. I will try to explain the process as best as I can.

Make a script or plugin (if you prefer reuse) and in that script, make it so that when an input of your choice is pressed, it creates a index that contains the time since project start up or until song has been played.

Then on project exit or any other form of finish, print those dictionary values into the console.

Next, if you haven't already, create a script that responds to those indexes (dictionary values recorded) and give a score depending on the time close to the time recorded. Also, make sure that if you miss it completely, count for zero as a score and continue to the next index.

Bam! The rhythm is now more dynamic!

slender sparrow
# true gale Hi there 😊, Without any code it's hard to help, context is important. Did you...

This is my code

public override void _PhysicsProcess(double delta)
{
    if (TimeUntilNextBeat >= (60.0f / Data.Bpm) * (Data.BeatUnit / 4.0f) * 1000)
        {
            GetNode<AudioStreamPlayer>("MetronomeBeat").Play();

            TimeUntilNextBeat = 0d;

            BeatCounter++;
            BeatIndex++;

            if (BeatIndex > Data.BeatsPerMeasure)
            { BeatIndex = 1; }
        }
        else
        { TimeUntilNextBeat += delta * 1000; }
}

TimeUntilNextBeat is a double going from 0 to whatever was calculated. Might of course just be my calculation being weird but it should at least be constant, even if its wrong. BeatUnit is basically just the lower part of a time signature, for testing I'm using 4/4 so (Data.BeatUnit / 4.0f) evaulates to 1.

#

I've used multiple online metronomes to check and with everyone, it's a noticeable change. Even if I start off-beat, it should stay the same amount of off-beat. But it's getting in and out of sync in usually less than 15 beats

#

I've also set the physics fps to 480 and had a look in the profiler. Was very stable as there aren't any additional physics calculations happening.

slender sparrow
true gale
#

So, first off:

This will be always off by one tick (one frame) of the physics engine. Because you recalculate the next beat point in one call of the physics_process() function but check for the result one tick/call later, but (as far as I can see) don't account for this offset.

Did you try just using a Timer for this?

I would keep a reference to the audio player in the class, as the lookup via get_node() is "slow" (at least in regards to precision timing you might need) and reference lookups are fast.

#

The proposed options might be a way to go, but I'm not convinced this is yet a problem not solvable with "standard Godot tools", so to speak.

slender sparrow
#

It still has some limitations, high bpms are probably going to introduce a bit of inconsitency, but for my project it's enough

true gale
#

It will deviate because it's continuously off by one tick. Summing up over time the ticks.

#

But if you have a valid solution which works for you, no need to drill down here. 😊

#

It's about getting help and solving problems, which in this case you did with the help of some other source by yourself. So kudos to you and happy godoting gdparty