Ok, I’m currently having an issue with the script. here’s my problem:
local RunService = game:GetService('RunService')
local ContextActionService = game:GetService('ContextActionService')
local BeatsPerMinute = 120 -- Frequency of beats
local ActionTimeInSeconds = 0.25 -- Duration of time before or after precise BPM to give the user a grace period, hitting a frame perfect beat isn't easy but hitting a beat within half a second is p simple.
local TotalTimeInSeconds = 0 -- Keeping track of the time that has passed.
function HitBeat()
local BeatsPerSecond = BeatsPerMinute / 60
local BeatDistance = (TotalTimeInSeconds % 1) / BeatsPerSecond
if BeatDistance <= ActionTimeInSeconds then
local BeatRating = (BeatDistance / ActionTimeInSeconds) * 100
print('Beat hit on time! With a rating of: ' .. BeatRating)
else
print('Missed!')
end
end
RunService.RenderStepped:Connect(function(Delta)
TotalTimeInSeconds += Delta -- Incrementing our total time by Delta
local BeatsPerSecond = BeatsPerMinute / 60
local BeatDistance = (TotalTimeInSeconds % 1) / BeatsPerSecond
if BeatDistance - Delta <= 0 then -- when we reach our beat on time the beat distance should be so low that the Delta subtracted by it is less than 0.
print('Beat!')
end
end)
ContextActionService:BindAction('Hit Beat', HitBeat, true, Enum.KeyCode.H, Enum.KeyCode.ButtonY)
I’m trying to test a change in BPM for differently paced songs, but when I try this (I’ve changed BeatsPerMinute
to 120), instead of the expected result, the metronome still plays at 60 BPM and just runs print('Beat!')
twice, probably because 120/2 = 60.
Next, I returned BeatsPerMinute
to 60 and tried changing both definitions of BeatDistance to (TotalTimeInSeconds % 0.5) / BeatsPerSecond
(Dividing by 2, just like 120). THIS gave me what I was looking for, leading me to the conclusion that, to change BPM, you should use this formula for BeatDistance: (TotalTimeInSeconds % (1 / (BeatsPerMinute / 60))) / BeatsPerSecond
.
However, while this does fix the issues with the BPM itself, it’s not fixing the issue of print('Beat!')
being run twice. I’m not sure how to proceed from here. Should I add a debounce somehow?
here’s the current script:
local RunService = game:GetService('RunService')
local ContextActionService = game:GetService('ContextActionService')
local BeatsPerMinute = 120 -- Frequency of beats
local ActionTimeInSeconds = 0.25 -- Duration of time before or after precise BPM to give the user a grace period, hitting a frame perfect beat isn't easy but hitting a beat within half a second is p simple.
local TotalTimeInSeconds = 0 -- Keeping track of the time that has passed.
function HitBeat()
local BeatsPerSecond = BeatsPerMinute / 60
local BeatDistance = (TotalTimeInSeconds % (1/(BeatsPerMinute / 60))) / BeatsPerSecond
if BeatDistance <= ActionTimeInSeconds then
local BeatRating = (BeatDistance / ActionTimeInSeconds) * 100
print('Beat hit on time! With a rating of: ' .. BeatRating)
else
print('Missed!')
end
end
RunService.RenderStepped:Connect(function(Delta)
TotalTimeInSeconds += Delta -- Incrementing our total time by Delta
local BeatsPerSecond = BeatsPerMinute / 60
local BeatDistance = (TotalTimeInSeconds % (1 / (BeatsPerMinute / 60))) / BeatsPerSecond
if BeatDistance - Delta <= 0 then -- when we reach our beat on time the beat distance should be so low that the Delta subtracted by it is less than 0.
print('Beat!')
end
end)
ContextActionService:BindAction('Hit Beat', HitBeat, true, Enum.KeyCode.H, Enum.KeyCode.ButtonY)
sorry for the long long reply