Wednesday, August 12, 2015
Calculating Jump Arc
"So how do I jump?" It's a common question I hear when I see people play a game with any level of platforming in it -- and often a desire in a game that doesn't.
But lately, while working on Battle High 2 updates, I have been asking myself a particular question related to jumping: "How do I jump so that I reach this height and return to the ground within so many seconds?" It's honestly a mathematical question that would make ninth grade me laugh, but then I'd slap him and tell him that he couldn't comprehend any aspect of 3D modeling, but I digress.
Anyway, I just wanted to write a small post about this situation as it's something that has perplexed me during Battle High 2, and something I hope won't perplex me in future games.
Firstly, I hate using builtin Physics engines, at least for character movement. People don't often move realistically in games, so why should I use an engine that is trying to simulate realistic physics? In conclusion, when working in Unity, I don't want to let the physics engine move my character, but instead use my own velocity, speed, etc.
The most common setup that I've learned since college is simply as follows:
speed += gravity * timeDelta;
position += speed * timeDelta;
Essentially, the player's speed -- assuming we are only focusing on the vertical -- is increased by the gravity and then position is moved by the new speed. This works fine. There's probably a bunch of other ways to calculate these values, but I use this one.
The problem I was having though was, if I'm using this, how do I predict positioning? Whether it would be for networking or basic planning, being able to predict a jump arc is pretty useful.
So, after banging my head against the wall for awhile, I found this was the equation I wanted to use to do said prediction:
position = 0.5 * gravity * time^2 + speed * time
Honestly, it's a basic physics equation that can be found doing some searching or going here: https://en.wikipedia.org/wiki/Equations_for_a_falling_body . Here's some more information involving calculus concepts such as integrals and derivatives: http://hyperphysics.phy-astr.gsu.edu/hbase/acons.html . This being said, this still didn't help me if I wanted to know the best speed and gravity to reach a certain height in a given amount of time.
Anyway, the previous equation is a basic quadratic equation where
a = 0.5 * gravity
b = speed
c = 0
c is 0 because I know that I want to start my jump on the ground -- at 0 -- and end it on the ground -- also at 0. Anyway, going to a quadratic equation in standard form:
y = ax^2 + bx + c
I know three of the five variables: x, y, and c. So my issue was, knowing what these values are, how can I solve for a and b, my gravity and speed.
I also knew that I can graph any parabola as long as I know three points, and I did!
Assuming t is time and h is the desired height or apex, I have these three variables. At the beginning of my graph, I'm at (0, 0). I haven't left the ground yet. Then, when time has elapsed all the way, I'm back to the ground. Finally, at half the time, I'd reach the desired height. Knowing this, I knew I could factor the equation as follows:
y = (x - 0)(x - t) or x(x-t)
In factored form, however, there is a coefficient, which I'll designate a. If I solve for a, I should be able to find my gravity! So what I did, is I substituted t/2 into the equation and solved for a.
h = a * (t/2)*(t/2-t)
a = h / (t/2)*(t/2-t)
a = -h/(t/2)^2
Finally, I knew a. Problem was, a is not equal to gravity. a = 0.5 * gravity. So gravity = a * 2.
Now, knowing my gravity, I can solve for speed, which is equal to -0.5 * gravity * time:
0 = 0.5 * gravity * time^2 + speed * time
-speed * time = 0.5f * gravity * time^2
speed = -0.5 * gravity * time
So, I finally figured out the issue, an issue that someone in a basic physics class learns within the first semester, but I was still happy, and yes, there are probably better, easier ways to figure this out, but that doesn't change the difference that I'm proud of my work!
But, I soon thought, what if I'm not on level ground? Then what?! I was a bit stumped, but I thought about all the variables I know and how they relate.
g = gravity (or acceleration)
v = initial velocity (or speed)
s = starting position
e = ending position
t = time
k = height (I'll explain why I'm using k later)
So at first, I thought the following three sets would work:
I know (0,s) and (t,e) are true, but the problem is (t/2,k) isn't necessarily true. By having different starting and ending heights, my jump is essentially ending at a different point, interrupting the full arc jump. So now, I have to find t/2, which I will designate as h so I can use the vertex formula:
y = a(x - h)^2 + k
In the above, a is the same as it was for standard form, so 0.5 * gravity. h and k stand for the vertex of my jump arc. We know k, the height designated earlier, but we have to solve for h now, which was originally t/2.
So now, I have to solve for h. I do, however know two values, which can help for solving h.
s = a(0 - h)^2 + k
e = a(t - h)^2 + k
We are solving for h, but if we solve for a first, we can set the two equations equal to each other.
a = (s - k) / h^2
a = (e - k) / (t-h)^2
Because of this, I know now the following is true:
(s-k) / h^2 = (e-k) / (t-h)^2
Now, I can solve for h! I'll save you the trouble and give you the following. It's the quadratic formula:
In this formula:
x = h
a = sk - ek
b = -2 * sk * t
c = sk * t^2
The only change is that s-k and e-k have been replaced by sk and ek. So first, we should note that if the starting position and ending position are the same, we can't use this method. We'll be dividing by 0 which won't work, BUT this doesn't matter. If the starting height and ending height are the same, we can just use the original method where we know that t/2 is our halfway point. Anyway, now that we know h, we can use this method to solve for a by using the following:
s = a(0-h)^2 + k
s-k = a(-h)^2
a = (s-k)/h^2
g = a * 2
We know now everything we need to know for our equation!
a = (s-k)/h^2
g = a * 2
s = -g * h or -0.5 * g * h * 2
This is really just scratching the surface, so I'm going to end this early. Regardless, using the following equations, we can solve a combination of problems concerning jumps.
p = 0.5gt^2 + st
p = a(t-0)(t-(-2s/g))
p = a(t-h)^2 + k
I can write more later, maybe illustrate some of points. This is a lot more complex than I was expecting when I started writing. Regardless, being able to determine what speed and gravity I need to utilize so that a jump of a certain height can be accomplished within a certain amount of time is very useful.