Using friction limited acceleration to set a max velocity precisely
The previous answer is correct that friction can set a limit to the velocity but the answer missed some details in regard to setting the limit.
First your velocity variable
vel = 0; //in pixels per frame. Start at 0 (or wherever you want)
And you want a particular max velocity in pixels per frame
maxVelocity = 100; // set the maximum speed
And you have a particular maximum acceleration in pixels per frame2
maxAccel = 1; // The max acceleration will occur when accelerating from 0
You now need to get the friction needed to stop the acceleration when the velocity reaches 100. We will call the unknown friction
friction = null; // what we need to find out
You will be using the equation
vel = vel + maxAccel; // accelerate
vel = vel * friction; // add friction
You know that friction
should reduce the velocity after acceleration so it does not go over maxVelocity
. So we need a value for friction
that when applied to the maxVelocity + maxAccel
is equal to maxVelocity
maxVelocity = (maxVelocity + maxAccel) * friction;
Now just rearrange the equation to solve for the unknown friction
to get
friction = maxVelocity / (maxVelocity + maxAccel);
Now you have a value for friction
that will ensure your velocity will not exceed maxVelocity
.
To extend it a little, you may want to add a boost that will give you short term extra velocity but you do not want that boost velocity to go over a limit. You could just recalculate friction
to a new maxVelocity
but that may not give you the kick you want as the top end of the velocity curve has low acceleration.
Another way is to provide additional acceleration while still keeping the same friction is to calculate additional acceleration required. We need to new vars.
maxBoostVelocity = 120; // max boost velocity
boostAccel = null; // this will have to be calculated using the friction we have
Using the same logic as above but rearranging the friction solution in terms of the new max velocity and with the known friction we get
boostAccel = ((maxBoostVelocity / friction )- maxBoostVelocity);
I like to use only the additional acceleration for boost so I don't have to touch the existing acceleration values. So I just subtract the original acceleration from the calculated boost to get what I want.
boostAccel = boostAccel - maxAccel;
So in some code
// the known limits
vel = 0; //in pixels per frame. Start at 0 (or wherever you want)
maxVelocity = 100; // set the maximum speed
maxAccel = 1; // The max acceleration will occur when accelerating from 0
maxBoostVelocity = 120; // max boost velocity
accelerate = false; // flag to indicate that we want to accelerate
boost = false; // flag to indicate we want to boost
// the unknown friction and boost accel
boostAccel = null; // this will have to be calculated using the friction we
friction = null; // what we need to find out
function applyAcceleration()
if(boost){ // is boosr flag true then add boost
vel += boostAccel ; // boost
}
if(accelerate || boost){ // is accelerate or boost flag true
vel += maxAccel; // accelerate
}
// always apply the friction after the accelerations
vel *= friction; // apply friction
}
// in the init function calculate the friction and boost acceleration
function init(){
friction = maxVelocity / (maxVelocity + maxAccel);
boostAccel = ((maxBoostVelocity / friction )- maxBoostVelocity) - maxAccel;
}