ID:150196
 
Here's my problem. I have a procedure where the player enters a desired speed.

The amount a player must accelerate is equal to the desired speed minus their current speed (obviously).

However, the acceleration procedure takes into account their current speed. Worse, the acceleration occurs at 10 separate intervals.

How would I go about accurately calculating the amount of acceleration required at each of the 10 steps of acceleration to have a final result that is equal to the desired speed (assuming that the player is indeed capable of accelerating to that amount)?

Here is the acceleration formula:

//Engines = number of working engines
//Armour = amount of armour covering engines
//Velocity = current velocity in m/s
var/mass = length*width
var/result = (engines * 2.5 / mass) * 100
result -= result * (armour/engines * 0.25) //armour covering engines hinders acceleration
result -= (velocity/CalculateMaximumVelocity() * 0.75) * result //ships accelerate 75% slower as velocity approaches maximum
return round(result,1)

And here's the maximum speed formula:

//Engines = number of working engines
//Armour = Amount of armour covering engines
//Log base = 1.85
var/mass = length*width
var/result = log(log_base, (engines * 3)/(mass/2) ) * 3 * 100
result -= result * (armour/engines * 0.25) //armour covering engines hinders movement

return round(result,1)
The average acceleration is the change in velocity divided by the change in time. The simplest case would be a constant accelearation of (FinalVelocity - InitialVelocity)/10.
a = (v9 - v0)/10
The ship applies exactly the thrust needed for 10 time units, then cuts off immediately.

If I read your code properly, you want the ship to accelerate 75% as fast as the last time unit each time. That complicates things a little.

at = a0 * .75t
and
average a = sum(a0 to a9)/10 = (v9 - v0)/10
sum(a0 to a9) = v9 - v0
.750a0 + .751a0 + .752a0 + .753a0 + .754a0 + .755a0 + .756a0 + .757a0 + .758a0 + .759a0 = v9 - v0
(.750 + .751 + .752 + .753 + .754 + .755 + .756 + .757 + .758 + .759)a0 = v9 - v0

We'll say k = (.750 + .751 + .752 + .753 + .754 + .755 + .756 + .757 + .758 + .759) and leave it as an excercise for the reader to calculate. ;)

k a0 = (v9 - v0)
a0 = (v9 - v0)/k

Now that you know the initial acceleration, you're set. At the end of each acceleration phase, multiply the current acceleration by 75% to find the acceleration for the next phase.

This sort of acceleration will cause the ship to suddenly lurch into motion, slamming people into their acceleration couches with much greater force than a constant acceleration would, then it gradually tapers off. It should probably gradually increase then gradually decrease to avoid the lurching sensations, but even then it will apply greater force at the peak of the curve than a constant acceleration would.
Spuzzum wrote:
However, the acceleration procedure takes into account their current speed. Worse, the acceleration occurs at 10 separate intervals.

How would I go about accurately calculating the amount of acceleration required at each of the 10 steps of acceleration to have a final result that is equal to the desired speed (assuming that the player is indeed capable of accelerating to that amount)?

I think to do this properly you'd need a variable t indicating which step you were on. As Shadowdarke mentioned, starting acceleration off quickly and slowing it down would be murder on passengers, and isn't very realistic. (Interesting physics fact: Rate of change of acceleration, the third derivative of position, is called "jerk".) What would be more realistic would be acceleration that acts as a curve, increasing acceleration to maximum and then decreasing it. Average acceleration should be aavg=(vf-vi)/tf. In this case, tf=10.

A simple linear increase and decrease of acceleration will start out at (1/3)aavg and end at (5/3)aavg from t=1 to t=5. From t=6 to t=10, it would go backwards, with (5/3)aavg being used for both t=5 and t=6. (This curve would be altered somewhat if tf was odd.)

Thus the formula might look something like this:
proc/CalculateAcceleration(v,vf,t,tf)
var/a_frac // portion of acceleration already done
// t ranges from 1 to tf
var/peak=round((tf+1)/2)
var/denom
if(tf%2) denom=peak*peak // special case, tf is odd
else denom=tf*(peak+1)/2
if(t<=peak) a_frac=(t*(t-1))/(2*denom)
else a_frac=1-((tf-t+1)*(tf-t+2))/(2*denom)
// vf-v = a_total*(1-a_frac)
// a_total = (vf-v)/(1-a_frac)
var/a_total=(vf-v)/(1-a_frac)
return a_total*min(t,tf-t+1)/denom

If you want to only accelerate by integer amounts, round off the return value; the calculation will compensate for rounding errors because the proc doesn't need to know vi and is essentially computing a new acceleration curve each time.

Lummox JR