Hello, I’m attempting to utilize a parabolic curve to simulate a feature in my game. The player is a battery and spawns in at 100% charged. As the round begins, the player’s battery charge should gradually begin to decline towards 0% at a relatively slow pace, then pick up the pace once it hits about 60%, then slow back down to the original pace around 20 or 30%.
I decided to attempt to use a parabolic curve to simulate the rate of change of how fast the battery’s charge declines, but no matter what I do, the battery charge always goes all the way to 0 in basically less than a second. Below is a desmos illustration of the graph I’m attempting to follow:
The formula I’m using is:
y = -a(h-0.5)^2 + c
a = 4.0
c = 1.05
The graph is centered at x = 0.5 so that if I’m understanding correctly, the battery will be draining at it’s fastest around 50% power. The code I’m using is below:
Module Script: GameLoop
local function drainRate(charge)
local a = 4.0 -- Steepness of curve
local c = 1.05
local rate = -a * (charge - 0.5)^2 + c -- "a" is negative so the curve faces down and not up
return math.max(rate * (1 / 600), 0) -- 1 / 600 multiplier supposed to slow decay rate down
end
function GameLoop.DecreaseCharge(dt)
for i, v in pairs(Players:GetPlayers()) do
if v:GetAttribute("Playing") and v.Character:GetAttribute("Charging") == false then
local character = v.Character
local currentCharge = character:GetAttribute("Charge") or 100
local normalizedCharge = math.clamp(currentCharge / 100, 0, 1) -- Set the charge to a number between 0 and 1 so it's easier to work with
if normalizedCharge <= 0 then
character.Humanoid:TakeDamage(100) -- Player is out of charge so they should die
v:SetAttribute("Playing", false)
end
local rate = drainRate(normalizedCharge) -- Drain rate function utilization
normalizedCharge = math.clamp(normalizedCharge - rate * dt, 0, 1) -- Something might be wrong here
character:SetAttribute("Charge", math.floor(normalizedCharge * 100)) -- Set the new charge value to a percentage number between 0 and 100 percent so client can receive it
end
end
end
Main Server Script:
if workspace:GetAttribute("TestingMode") == false then
local connection
connection = RunService.Heartbeat:Connect(function(dt)
GameLoopModule.DecreaseCharge(dt)
end)
end
My suspicion heavily lies in how the Heartbeat function is handling the DecreaseCharge execution. I tested it at 240 fps and the battery ran out faster than when I tested it at 60 fps, but in both cases the rate at which the battery depleted was unbelievably fast (a second or less when it should be more like 30 seconds).
The weird thing is that before I tried the parabolic curve approach to this, I had been using an exponential decay function which worked completely fine, so I’m not sure why the Heartbeat would now be affecting things.
I added some comments to hopefully help people digest the code better, but I understand this is a lengthy and probably complex problem, so anyone who is willing to help is very much appreciated and I will do my best to provide any extra information. I’m not a super math wizard but I’m trying.