💾 Archived View for gemini.spam.works › mirrors › textfiles › programming › gravity.txt captured on 2022-04-29 at 00:30:53.
⬅️ Previous capture (2020-10-31)
-=-=-=-=-=-=-
Gravity Faq The information contained in document will allow you to realistically simulate jumping and interstellar maneuvers. The purpose of this document is to understand the physics of the world we live in, and apply realistic physics to your game. It will not give you optimized routines for your program, that is your job! But if you understand how things work, it will be a heck of a lot easier. ===================================================================== = Basics ===================================================================== There are some key terms I will define to make sure we are talking about the same things: Distance : Total path of travel. Displacement: Difference between original position, and final position Speed : Change in displacement divided by the change in time Velocity : Direction of travel, and speed of travel. Acceleration: Change in velocity divided by the change in time. Force : Note: That displacement, velocity, and acceleration are actually vector quantities. (That is, they have a direction and magnitude). Abbreviations: a : acceleration M : mass s : displacement s0 : initial displacement t : time v : velocity v0 : initial velocity units m : meter (unit of length) m/s : meter per second (unit of speed) m/s^2 : meter per second squared (unit of acceleration) N : Newtons (unit of force) s : second (unit of time) ===================================================================== = The concepts ===================================================================== Imagine a spaceship flying through space at 1000 m/s. It is deep in interstellar space with nothing around it. What forces are acting on it? The answer: none! It will continue to fly through space at 1000 m/s forever if no force acts on it. : The ONLY reason why objects will change velocity (direction and/or : speed) is if a force is applied to it. What is a force you ask? A force is an external push or pull. A force is also a vector. It has a magnitude and a direction associated with it. Right now gravity is exerting a force on you: it is pulling you toward the center of the earth. Also, the only reason an object will change displacement is if it has some velocity. Suppose now that the hand of god reaches down and starts pushing the spaceship forward. There is now a force applied to the ship. With any force applied, an acceleration is induced. With our new acceleration, the velocity starts to increase. If god doesn't stop pushing the ship, then soon the ship will go very fast! ===================================================================== = Look, I just want to make my guy jump. ===================================================================== Ok, I'm getting to this. We have our jumping dude Joe. Joe's initial position is on the floor or platform that is not moving. The user presses a key and Joe should leap into the air. You need to keep track of three things about Joe: His position, velocity, and acceleration. Initially, his position will be at the floor. Once the key is hit, we simply give Joe a very fast velocity in the upward direction. Then every frame/sec/update/whatever decrease his upward velocity by a constant amount. That's it! The constant decrease is actually an acceleration in the downward direction. The horizontal motion of Joe is unaffected. So while Joe is flying through the air, you can change his forward/backward movement as normal. Side note: In real life, it is impossible to move forward/backward when jumping straight up. But I find games that allow forward/ backward movement while jumping more playable and fun than just jumping straight up. And who said games are realistic anyway? What should be the acceleration that we are applying? On earth, the acceleration of Joe will be 9.81 m/s^2 in the downward direction. Unfortunately, meters per second squared means nothing to the computer. The acceleration must be determined based on your game's update rate. Usually guessing and tweaking is the best way to achieve this. So our pseudo-code is as such: Joe.pos.y = 0; (Or wherever floor is) Joe.vel.y = 0; Joe.accel = 10; Joe.jumping = NO; Loop If (jump key is pressed) { Joe.vel.y = 100; Joe.jumping = YES; } if (Joe.jumping == YES) /* Move Joe if we are jumping */ { Joe.vel.y = Joe.vel.y - Joe.accel Joe.pos.y = Joe.pos.y + Joe.vel.y } if (Joe.pos.y <= 0) /* Check to see if Joe has hit floor */ { Joe.vel.y = 0; Joe.jumping = NO; } End Loop For the first time the jump key is pressed, the position of Joe will suddenly jump off the floor. As he goes higher, Joe begins to slow down because the velocity is constantly decremented. Joe will eventually stop moving up, and begin to move down. He will move faster and faster until he reaches the floor again. Joe's velocity and position in the y direction at the end of each loop will appear as such: Loop0 : Joe.vel.y = 0 Joe.pos.y = 0 Loop1 : Joe.vel.y = 100 Joe.pos.y = 100 Loop2 : Joe.vel.y = 90 Joe.pos.y = 190 Loop3 : Joe.vel.y = 80 Joe.pos.y = 270 Loop4 : Joe.vel.y = 70 Joe.pos.y = 340 Loop5 : Joe.vel.y = 60 Joe.pos.y = 400 Loop6 : Joe.vel.y = 50 Joe.pos.y = 450 Loop7 : Joe.vel.y = 40 Joe.pos.y = 490 Loop8 : Joe.vel.y = 30 Joe.pos.y = 520 Loop9 : Joe.vel.y = 20 Joe.pos.y = 540 Loop10: Joe.vel.y = 10 Joe.pos.y = 550 Loop11: Joe.vel.y = 0 Joe.pos.y = 550 Loop12: Joe.vel.y = -10 Joe.pos.y = 540 Loop13: Joe.vel.y = -20 Joe.pos.y = 520 Loop14: Joe.vel.y = -30 Joe.pos.y = 490 Loop15: Joe.vel.y = -40 Joe.pos.y = 450 Loop16: Joe.vel.y = -50 Joe.pos.y = 400 Loop17: Joe.vel.y = -60 Joe.pos.y = 340 Loop18: Joe.vel.y = -70 Joe.pos.y = 270 Loop19: Joe.vel.y = -80 Joe.pos.y = 190 Loop20: Joe.vel.y = -90 Joe.pos.y = 100 Loop21: Joe.vel.y =-100 Joe.pos.y = 0 Notice that Joe is going very fast when he hits the floor. If Joe does not hit the floor, or the floor disappears (i.e. he jumps off a platform) then eventually Joe will be going very fast. We need to give him a limiting velocity. This is the fastest velocity Joe can go by falling. In real life this is caused by air resistance. This is easy enough to do. The modified pseudo-code is such: Joe.pos.y = 0; (Or wherever floor is) Joe.vel.y = 0; Joe.accel = 10; Joe.jumping = NO; Loop if (jump key is pressed) { Joe.vel.y = 100; Joe.jumping = YES; } if (Joe.jumping == YES) /* Move Joe if we are jumping */ { if (Joe.vel.y > -100) /* Limit Joe's velocity to -100 */ { Joe.vel.y = Joe.vel.y - Joe.accel Joe.pos.y = Joe.pos.y + Joe.vel.y } } if (Joe.pos.y <= 0) /* Check to see if Joe has hit floor */ { Joe.vel.y = 0; Joe.jumping = NO; } End Loop The added loop will not decrease Joe's velocity if he is already moving downward at a speed of -100. Thus we have added his limiting velocity. ===================================================================== = Other dimensions ===================================================================== Ok, the above example is all well and good, but some game sprites do not just go up and down. Some go side to side while they are jumping. Easy! It just so happens that the x and y values of velocity and acceleration are independent! So while you resolve the y position and velocity of Joe, you can move Joe in the x direction normally. It will appear that Joe follows a parabolic path, which is what he would follow in the real world. The same goes for 3 dimensions. x,y,z velocities and accelerations are all independent of one another. ===================================================================== = Spaceman Spiff ===================================================================== Another example where kinematics applies is an asteroids type game. You fly around in a zero-g environment, but can thrust forward in any direction. In this case gravity is not a factor. What do we use instead? We use the thrust of the spaceship as our acceleration. We simply break up our acceleration vector into x and y directions, and apply the same techniques as above. To implement this we get the pseudo-code: pos.x = 0; pos.y = 0; vel.x = 0; vel.y = 0; acc.x = 0; acc.y = 0; Loop if (thrust key pressed) { resolve_direction_vector; acc.x = scale_x * 10; acc.y = scale_y * 10; } vel.x = vel.x + acc.x; vel.y = vel.y + acc.y; pos.x = pos.x + vel.x; pos.y = pos.y + vel.y; End Loop Now we have a step we have not seen before: resolve_direction_vector. We need this because the ship can move in any direction. What this step does is get the appropriate directions vector and break it down into an x vector and y vector. Once broken down, the resolve_direction_vector step will set scale_x and scale_y. /^ Original / | acceleration / | vector / | / | / | Y vector / | Start / * | position -> X------->| X vector