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!

(0, 0)
(t, 0)
(t/2, h)

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:

(0, s)
(t/2, k)
(t, e)

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.

Sunday, August 2, 2015

Jam Week 2015: TetherBrawl

Last week I participated in Jam Week at work.  Jam Week is a week in which the entire studio gets to work on anything they desire -- within reason.  I, like I tend to do, worked on a solo project that I entitled TetherBrawl.  The following three videos are of the game's progress over time:

http://mattrified.tumblr.com/post/125212118058/schell-games-is-doing-a-jam-week-this-is-what-i

http://mattrified.tumblr.com/post/125305271785/more-progress-of-tetherbrawl-the-jam-week-game

http://mattrified.tumblr.com/post/125526782007/this-is-the-result-of-my-solo-jam-week-project

In TetherBrawl, the two players hit the ball, trying to get it through their hoop while moving in the correct direction.  Once the ball enters the hoop, a set of gems is generated that the player must collect; the amount of gems generated is proportional to the ball's speed upon entering the goal.  If the player is hit by either the ball or the opponent's attacks, they lose 10 gems that their opponent can then pick up.  After a minute, the winner is determined by whomever has the most gems.
I only did one character, a billiards player with an eyepatch, but my thinking for the theme was to create a cast of characters all based of sports that people don't deem as very athletic:  billards, golf, chess, bowling, esports, etc.  I do think the character proportions for the size of the screen work against it.  That character is probably around 7 heads tall; for a game like this, characters should probably be more cartoonish, around 5 heads tall, maybe even 4.
I thought it was a simple game, but a lot of people didn't quite know what was going on, at least on their first play through.  I think part of this is because I didn't get a chance to tutorialize it enough -- then again, when you have 4 days, maybe 4.5, tutorialization isn't your top priority.  Another is that I sort burned myself out.  I've been stressed lately trying to finish up Battle High 2 A+; finding motivation to work on it has been rather daunting.  So working on something in such a short amount of time burned me out.  Also, I realized about halfway through that most of my Jam Week ideas are extremely similar.  Two times I worked on GumTrix -- which is now available for iOS and Android -- and every other time, I've done some sort of 2-player, competitive game:  Two years were different fighting robot games and now this year was a competitive game.  I guess I sorta felt like a one trick pony.
Also, lately, doing solo work has been a little problematic.  I like working by myself.  There's a lot of good aspects to it, but I've lately found there are some negative aspects as well.  The most positive aspect is that there is a lot of ownership and control over the ideas.  No meetings to brainstorm or discuss or hurt feels when things are rejected or undesired compromises.  On the other hand, I find I have a hard time staying confident in an idea without working with another person, and sometimes, bouncing ideas can be beneficial.  Also, trying to do everything yourself is extremely daunting.
That was one area that working solo affected this jam week.  I tried to do everything myself when I should have cut some things.  For example, I made a character using Fuse and then animated it in 3DS Max.  This took a little longer than expected, the Max to Unity process being a bit clunkier and slower than I imagined.  Also, I thought I knew a lot more about Mecanim than I did.  I was able to get my animations and transitions working, but there were times were triggers always happened or when the game would wait for a transition before going to the next state.
 I think if I had went with a simpler, more minimalist approach to the art, I could have focused on the game's design more, maybe even getting a chance to make a strong tutorial.  Overall, I learned a lot, but I should have narrowed my focus during this year's Jam Week; given the amount of pressure I'm imposing on myself to finish the Xbox One port of Battle High 2 this year, trying to do a whole game in 4 days was a bit imposing, and after 3 days, I sorta stopped caring about the idea, as I just wasn't feeling it.  Next Jam Week, I'd like to avoid the two-player, side view game theme as well, but we'll see.