Best way to create rhythm for my rhythm game?

What I thinking right now is making rhythm manually. But it’ll be a waste of time so ofc there are other better ways to make rhythm so what do you think is the best way to create rhythm?

(Rhythm as keyframes or notes of music rhythm, not making music)

4 Likes

Hey there! :wave:

I’ve linked some other posts that are related to this topic below, they may assist you so check them out! :grinning_face_with_smiling_eyes:

Link 1; click here.
Link 2; click here.
Link 3; click here.

Best of luck with figuring this out! :heart:

2 Likes

They don’t assist me at all, sorry for that but thanks for trying to help.

Link 1: I’m already good at the basics of lua so that post doesn’t help me, and i’m here to find the best way of creating rhythm.
Link 2: I don’t understand the code in the robeats mapping place and I’ll rather make my own.
Link 3: Same thing as link 2.

2 Likes

That place actually could help you. There are instructions to convert .osu beatmap files into lua code, which is possibly what you are looking for. Rather than dismissing this person, you should have maybe dug a little bit deeper to see what they were actually referring to. Good luck with your project.

  • Galactiq
6 Likes

I’ll do that if I don’t have any other choice if I don’t have any other best ways.

1 Like

Your biggest friend will definitely be

Sound.PlaybackLoudness

As this is the only property relating to audio volume levels, you will have to use a hacky solution.

Duplicate your audio file, slap an EqualizerSoundEffect on it with HighGain and MidGain turned to 0. This will leave the audio channel with only sub bass frequencies, the frequencies that tend to drive a track’s rhythm and give you that kick.

You will have to do some trial and error scripting to come up with something that compares the PlaybackLoudness of this EQ’d track over time. Make it just sensitive enough that only primary beats of the track trigger it.

Then incorporate the same method with the original sound. Slap an EqualizerSoundEffect on it, but this time with only LowGain turned to 0. Make it less sensitive since the changes in high end sounds tend to be more sporadic.

Make sure that you are calculating the magnitude of the beats relative to the rest of the song, not to an objective volume standard because every song is a different volume. I would try something like this (pseudocode):

function RunEveryFrame(delta) – delta is important here
local Volume = 0
local Time = 0
local SensitivityThreshold = 0.95
local Magnitude = 0
if Sound.Playing then
Time += delta
Volume += Sound.PlaybackLoudness
Magnitude = (Volume / Time) * SensitivityThreshold
local TempTime = delta
local TempVolume = Sound.PlaybackLoudness
if (TempVolume / TempTime) > Magnitude then
CreateBeatOrSomething()
else
Volume = 0
Time = 0
end
end

This will get you the average volume of the track, not including the peaks based on your sensitivity threshold amount. Create the song beats when a single runthrough of this code’s volume is greater than the magnitude. Use something like this code for each track. This will create beats on main bass rhythms and also melody rhythms.

3 Likes

Hm maybe that will work, i’ll try that. Thanks.

1 Like

Something like that is really the only way I’d see it possible to generate beats from audio files. Alternatively you could make an automation system where you can manually mark every beat and make a system that randomly disperses beat things in patterns.

3 Likes

I can help! So this is what I did for my rhythm game engine:

  1. I have two audios in game.SoundService: Song and Beats.
  2. Based on the difficulty the player chooses, start playing Beats and then start playing the song a few seconds later.
  3. This is so that the song syncs with the notes on screen. Note that Beats volume is 0.
  4. Use Sound.PlaybackLoudness along with a bit of randomness to generate the notes for each track.
1 Like

How will sound.playbackloudness work and where will it apply to?

I’d recommend first mapping the beats, and that’ll be your start (like Osu).
And then have a localscript fire a remote to the server, in which the server will be recieving

and that’ll keep track of effects, etc.

1 Like

Alright, so this is how I did it in the most basic ways possible:

local SS = game.SoundService
local difficulty = 2 -- time it takes for notes to go from start - finish.
local noteCooldown = .25 -- so we dont have an overflow of notes.
local canMakeNote = true

SS.Beats:Play()
wait(difficulty)
SS.Song:Play()

game:GetService("RunService").RenderStepped:Connect(function()
   if canMakeNote then
      canMakeNote = false
      generateNote()
      wait(noteCooldown)
      canMakeNote = true
   end
end)

In my rhythm game, I had four colors lined up: Red, Yellow, Green and Blue.
I calculated what track the notes go on based on PlaybackLoudness

local pbl = Beats.PlaybackLoudness

local ranges = {
		Red = NumberRange.new(140,184),
		Yellow = NumberRange.new(185, 249),
		Green = NumberRange.new(250,304),
		Blue = NumberRange.new(305,340),
		random = NumberRange.new(341, 9999999)
	}
	
	local noteType = nil
	
	for color, property in pairs(ranges) do
		if pbl >= property.Min and pbl <= property.Max then -- found value in range
			noteType = tostring(color)
		end
	end

This is part of the generateNote() function.

3 Likes

Also, yes, this does use random notes. If the song was loud enough I just decided to throw the notes on random tracks. It was lazy now that I think about it but this should still be a good enough example to show how its done and what tracks to put the notes on. After testing this with about 3-4 songs I can say it generates pretty decent patterns. This method also gives the freedom of doing ANY song you want. Players can just put in an audio ID and BOOM, they can play it on any difficulty.

Not to be rude, but doesn’t that ruin the purpose of a rhythm game?
Usually in most games, the notes come to you based on when the next song bass/note/etc.
In your code, you’re basically wanting it to make a lot of notes just spawn out of nowhere, which is not even timed with the song, which takes us away from the point,

I meant it positions them on random tracks. It is still in perfect sync with the beat. Sorry if that wasn’t clear. If it was loud enough, they would all be on the blue track so I put them on a random one so they all aren’t blue.

noteCooldown handles that so that the notes dont suddenly increase or decrease. They are all timed with the song based on the difficulty.

1 Like

Can I ask what exactly “Song” and “Beats” is?? Like Id wise?? Are they matching, with different properties, is Beats a set audio, while Song changes based on whatever song you want?

And whats the purpose of Beats, if its volume is 0?

They are the same audio. Beats is what the script reads to generate the notes. Song is what the players hear. Playback loudness is the same, regardless of volume. You start beats a bit earlier to kinda “predict” what the notes are going to be. Basically just to have the beats sync up with what you hear. My way is generated with a script, which is why you put a delay between them.

Using your code as a base, managed to make this :smiley:

Few notes aren’t perfectly synced with the song, but ye, not really sure I can do much about it :man_shrugging: gonna see if I can figure out held notes and dual notes (2+ notes at the same time!)

1 Like

If you do, please share it here! I would love to know, I can’t figure it out either!

Just saw you even have the perfect and good note pop-ups, my testing place has the same thing! :smile:

2 Likes

Also, about the notes being off, I used a script to wait until both audios are fully loaded and ready to go. Basically something like this:

repeat wait(1) until Beats.IsLoaded and Music.IsLoaded

print("Both audios are ready.")

Beats:Play()

wait(2) -- offset so the notes are timed with the song.

Song:Play()