1
\$\begingroup\$

I am developing an athletics game, and working on the mechanics of the 100 meter dash. The player controls an athlete, that during the race has acceleration and a max speed. To win the race, the player has to collect boost tokens, which will increase the max speed.

So when the dash starts, the athlete will accelerate to his max speed, then when the athlete picks up a token, the max speed will increase, and he will accelerate again to the new max speed.

The problem is, I want to set the fastest time possible. In a config file, I want to set the fastest possible 100m dash time to 9.4 seconds.

How do I determine my starting max speed, so that when all tokens are collected, the final time will be 9.4 seconds?

This code is not actual code, but to illustrate the problem, and provide an example with numbers.

const acceleration = 6; // meters / seconds^2
const numTokens = 10;
const tokenDistribution = 100 / (numTokens + 1); // one token per 9.1 meters (and not on the finish line)
const tokenIncreaseSpeed = 1; // meters / seconds
const bestTime = 9.4; // seconds

const maxSpeed = ?? // meters / seconds - value so with all tokens the final time is 9.4 seconds...
const speed = 0;
// Pseudo loop code
update(delta) {
    speed += acceleration / delta;
    if (speed > maxSpeed) speed = maxSpeed;
    if (player.collides(token)) {
        maxSpeed += tokenIncreaseSpeed;
    }
    player.y += speed / delta;
    if (player.y > finishLineY) endRace(); 
    render() etc...
}
\$\endgroup\$
1
\$\begingroup\$

TL;DR

Starting maxSpeed should be about 6.28171069

Approach

The naive approach isn't terribly difficult, but it's a bit tedious. I'm using "naive" here to mean "ignoring that the actual time spent prior to getting a boost token will vary based on frame rate", and "we assume runner reaches max speed after each boost, prior to the next boost". If you need better than that, you'll need to go beyond what I do here and add per-frame bookkeeping.

Suppose you think of your track as numTokens+1 sections. Each section has a time to traverse based on the player's acceleration and max speed in that section.

Working from formulas for distance-acceleration explanation (I grabbed them from http://www.dummies.com/education/science/physics/how-to-calculate-time-and-distance-from-acceleration-and-velocity/ ) you can work out how long each section has to take to hit the target time of 9.4, and from that, work out the starting maxSpeed you'd need.

Two formula of interest pulled from the above link:

t = ( v_f - v_i ) / a (time to reach a given speed from a start speed with a given acceleration)

and

s = v_i*t + 0.5*a*t^2 (how much distance was traveled during that acceleration)

and I suppose we can include the equation Stephan mentioned:

speed = distance/time

More Variables, Maestro!

Let's define a few variables of interest, using _j to denote values related to the jth section of track:

  • startSpeed_j is the speed we had coming into section j
  • maxSpeed_j is the maxSpeed we can reach in section j, a function of our initial maxSpeed + numTokens * tokenIncreaseSpeed
  • accelTime_j is how long it takes to accelerate to maxSpeed for section j
  • accelDist_j is the distance traveled during acceleration
  • cruiseDist_j is how much distance remains in a section after accelDist_j
  • cruiseTime_j is how long we spend at maxSpeed before we reach the next boost
  • totalTime_j is how long the runner spends in the section
  • overallTime_j is how long it took the runner to get from the race start to the end of section j

Computing values

So using the above formulas and variables in a per-section way, we get:

accelTime_j = (maxSpeed_j - startSpeed_j) / acceleration
accelDist_j = startSpeed_j * accelTime_j + (1/2) * acceleration * accelTime_j * accelTime_j

Then with these, we can figure out how much distance remains after acceleration:

cruiseDist_j = tokenDistribution - accelDist_j
cruiseTime_j = cruiseDist_j / maxSpeed_j

And from these we can calculate how long the section takes to run (though we need a special case for the first section):

totalTime_j = accelTime_j + cruiseTime_j
overallTime_j = overallTime_(j-1) + totalTime_j

You could flip all this around to solve for the starting maxSpeed value, but unless you need that to be adjustable real-time in your game, I'd probably just solve it by trial and error.

I made a google doc spreadsheet that I used to solve this, which you can find and make a copy of here: https://docs.google.com/spreadsheets/d/1RJQWbbc831Rw_pWBoU3UHh4OKW13dt0yHDSRQ8eO_9U/edit?usp=sharing

The sheet supports tweaking of the initial parameters (up to 50 numTokens, above that will you'll have to do some copy-pasting), and has the starting maxSpeed value I found: 6.28171069

Hope this helps!

\$\endgroup\$
  • \$\begingroup\$ This helped me in figuring out just the complexity of calculating backwards. (solving this equation for x is quite hard: T = x/a + d/x − x^3/2*a + ∑d−(v(n−1)x+f)/a+g)) I might have to settle with just trying out different maxspeeds for each distance. Thank you. \$\endgroup\$ – LongInt Nov 29 '17 at 12:13
0
\$\begingroup\$

Speed = Distance/Time

You don't need to care about the acceleration here. Even with instant acceleration, your max speed if you complete 100m in 9.4 seconds is

Speed=100m/9.4s

Speed=10.6382978723 m/s

Divide this by however many tokens you intend to let the player collect to get your token boost value.

\$\endgroup\$
  • \$\begingroup\$ Thanks, but I want the player to be able to reach 9.4. With acceleration, every attempt will be lower than 9.4 \$\endgroup\$ – LongInt Nov 29 '17 at 12:10
  • \$\begingroup\$ You fixed your acceleration at 6m/s/s. At that point your only variable is your current max speed at any given point in time. To keep from violating your 9.4 limit, you absolute max speed cannon exceed 10.6 and a start speed should be 10.6/(coins+1). if you i tended for your acceleration to be the variable, you need to edit your question to indicate. As it's written, your accepted answer is not correct. \$\endgroup\$ – Stephan Nov 29 '17 at 13:05
  • \$\begingroup\$ If the absolute max speed of 10.6 is not reached until the last token, will it not only be the segment after the last token, that the absolute max speed is applied to? And a speed of 10.6/(tokens+1) = 0.96 m/s, which means it will take 10m/ 0.96 m/s = 10.4 seconds to run the first 10 meters? I will wait to select an answer, until I understand you fully. \$\endgroup\$ – LongInt Nov 29 '17 at 13:57
  • \$\begingroup\$ Ah, I didn't read your answer right, I now notice. You want me to get the token boost value, and not the speed. Sorry, now I think I understand. \$\endgroup\$ – LongInt Nov 29 '17 at 13:58
  • \$\begingroup\$ Well your starting speed can be whatever you want so long as it's less than 10.6. Each boost coin value should be (10.6-startMax)/coincount. By biggest point is that the way you coded it, you aren't changing acceleration, you're changing the max speed with each coin. \$\endgroup\$ – Stephan Nov 29 '17 at 14:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.