|  | 
 
 Olivia Newton John - Physical 
 OK. First, I'll explain about this document. I've noticed quite a few people asking questions about physics in games. I've also seen a few (not many) documents and tutorials about this subject. However, I found that many of the existing explanations are very heavy on the maths and the mechanics behind everything. I thought I'd try my hand at writing a small tutorial which I hope will answer the questions you have and give you some insight into how to approach this subject. My aim in writing this to provide a reference that is easy to understand and read, and that will (hopefully) enable you to add realistic physics into your games. I'm not going to go into all the background behind everything, instead I will give you the equations that are important and an explanation of how to use them. If you have any questions about anything in this, please contact me. The code snippets included in the text are written using Blitz Basic. As I'm not a very strong Blitz programmer, if anyone notices any speed-ups or mistakes, please let me know so I can correct them for future revisions. The full code can be downloaded from the link at the bottom of the document (wait for it…! *g*) 
 If you know all about 2- and 3-dimensional co-ordinate representation of points and objects in space, along with simple vectors and vector math, then please feel free to skip this section. If not, or if you want a refresher, read on. Take a piece of paper, a pencil and a ruler (or imagine all these things). Now, mark a point somewhere on the paper and label it 'O' (for Origin). This is our arbitrary point that we decide to call the origin in our 2-dimensional space. This point can be represented by (0,0). As long as all measurements are taken from this one point, then things will be just fine. Now, make another mark on the paper. It can be anywhere you like. Mark this point 'A'. This point can be represented by (x,y) where x is the number of 'units' away from the origin along the x-axis (to the right) and y is the number of 'units' away from the origin along the y-axis (upwards). For example, my piece of paper looks like this. 
 A is 4 units to the right and 3 units up. A can be represented as (4,3). If A was below, or to the left of O, then it would be measured in exactly the same way, but the values would be negative. The actual units are not really important. As long as the are always the same for all points and measurements made in your world. So, it is now possible to describe the positions of points. It is also possible to describe the relation between two points. If we join the two points O and A together with another line (OA), then this we will call a vector. This vector has two important properties. Firstly, it has a direction. The vector OA is NOT the same as AO. They are pointing in opposite directions. Secondly, the vector has a length or magnitude. This is how long the line is. If you remember your Pythagoras theorem, you'll be able to calculate the magnitude of OA. Go on…. You know you want to. If you can't remember Pythagoras, don't worry. It's quite simple. "The square of the hypotenuse is equal to the sum of the squares of the other two side". Or, in other words, take the size of the two measurements you know and square them. Then add them together and find the square root of that number. In this case, it is: |OA| = sqrt( 32 + 42) = sqrt(9 + 16) = sqrt(25) = 5 So, we can now say that the magnitude of OA is 5. 
 OK, now let's add another point to our world. Point B is directly above point A. 
 A vector doesn't necessarily have to originate from the origin. In this example, there are three vectors - OA, AB and (not show) OB. Of course, as there are no directions shown, it can be said that there are actually six vectors (AO, BA and BO also). Firstly, let's discuss point B. What is the location of point B in co-ordinate form? Did you say (4, 7)? Correct! OK, now, what is the magnitude of the vector AB? That's right, 4. Finally, what is the magnitude of the vector OB? If you said 8.06, then you would be right. So now you know how to describe points in 2D-space, and how to calculate the magnitude of vectors. If you want to do the same thing in 3D-space, you simply add another co-ordinate (Z) and measure that away from you. To calculate the magnitude of the vector, you simply add in the square of this measurement to the other two in the equation shown before. Feel free to experiment with this. Time to get on with the physical stuff....... A body is a thing. Something that you can touch or see - a plane, a car, a person, etc… 
 We also need a type to represent the positions of various things later on. We could be dealing with 2- or 3-dimensions. The choice is yours. 
 Note that in all the following discussion, I will be speaking about performing the calculations and illustrating with code using the Vector3 type and in 3-dimensions. If you wish to try this out in a 2-dimensional world, please feel free. As a pointer, you will need to replace the Vector3 types with the Vector2 types and usually a simple case of dropping the z-coordinate in the remaining calculations (but not always). If you need any more pointers or help, please feel free to contact me. All bodies (things) in space have certain properties. Firstly, they have a mass. This is how much "stuff" they are made out of. They also have a center of mass (or center of gravity as it is sometimes called). This is a point that has an equal amount of mass surrounding it in each direction. For example, the center of mass of the Earth is right in the middle of its core. The center of mass of a square (in 2d) is a point that is halfway along each side inside the square. More complex objects may have a center of mass that is not in the middle of it. For example, a monitor is front-heavy. This means that there is a larger percentage of the total mass of the monitor at the front. This center of mass can be used as the single point of the object to identify "where" a body is in space. When you come to display the object on the screen, the center of mass is the local origin of the object. So, in the case of an object representing a monitor, the local origin of the monitor should be nearer the front of the screen than the back of the monitor. This will allow us to make rotations look more realistic later. The center of mass represents where in the universe your object's center of mass is located. So, we now know about the bodies mass. Let's add it in. 
 A body also has a current "speed". This is how fast it is moving. The term speed is a bit misleading as speed is a directionless unit of measurement. We say that the body has a velocity. The velocity determines the direction of motion as well as the amount of distance moved in a certain amount of time. The velocity is described as a vector with the values indicating how far along each axis the body will move in a given unit of time. The units of distance and time are completely up to you. Decide what they need to be depending on the situation. Metres per second could be used for a land-based game. Miles per second could be used for space with hyper-quantum-thrust engines installed on the ship. According to Newton's laws of physics, a body will continue to travel at a certain velocity unless another force acts on it. So, if the velocity of our body was (0,0,2), and the units were metres per second, and we are in space well away from any kind of gravity force, then we could say that the body will move 2 metres further away from us every second. Forever. The actual velocity of the body can be determined by finding the magnitude of the velocity. Talking of forces, anything that acts on a body can be described as a force. For example, pushing your mug across the table exerts a force. The table also exerts a force on the mug and the mug exerts a force on the table (friction). All of these forces can be added up, so we need some way of storing the amount of forces on the body. These forces can be considered to be applied to the center of mass. Hence we are calling them ExternalForcesCOM. Although the forces are not actually applied to the center of mass, they can be taken as acting on that point. For example, gravity is a force. This force acts on every point of the object at the same time and with the same force. So, this all averages out, and we can assume that the force is applied to the center of mass. In the next tutorial, we will explore what happens when forces that are not located at the center of mass are applied to the body. But for now, assume that all forces are acting on that one point. Now we have: 
 That's about all we need ! There's not a lot else to it. Now it's down to the maths part. Hang on! Don't run off yet. It's easy really. Honest...... I'm going to simplify the maths part of it. If you want the full explanation, then we need to use calculus with differential equations and the like. If you just take my word for it, then it will be a lot easier..... Firstly, in our main loop, we have to prepare all the bodies for the next set of calculations. All that we need to do is to reset the forces that were applied last time. 
 Now, we can add all the forces that are applied to the bodies. How this is actually performed is entirely up to you. It could be at the response to a player pressing a key (activate thrusters), or it could be in response to a collision (see later articles about this). You decide what is the source of the force, and you decide how powerful the force is. To add the force to a particular body, we can use a helper function: Function addForceToBody(theBody.body, x#, y#, z#) theBody\ExternalForcesCOM\x# = theBody\ExternalForcesCOM\x# + x# theBody\ExternalForcesCOM\y# = theBody\ExternalForcesCOM\y# + y# theBody\ExternalForcesCOM\z# = theBody\ExternalForcesCOM\z# + z# End Function This will add the force with the values specified to the given body. Note that this is accumulative, so if you have a forward firing thruster, AND a rear fire thruster, this helper function will be called twice, you get the result of both of them. Nearly ready to run the actual calculations now. But first, we need to work out is how long it was since we last called the physics update part of the code. To do this, we just need the difference in the time since last time and now. Hopefully it will be a very small amount of time. The smaller the amount of time, the better for our calculations and the accuracy of it all. Let's assume that the time difference was 0.01 seconds. That's nice. We'll store this in a variable called "DeltaTime" and we'll use that soon. 
 Note that this is just a fudged value here. In your real code, you would work it out using timers or something. Now the physics code can start. I'm sure most of you will recognise the equations F=ma. Force=Mass x Acceleration. This is fundamental. Everything follows this law and that makes life very easy for us. We know the Mass of the object, and we also know the amount of Force being applied to the object. So, we can re-arrange this formula to get the Acceleration of our object... Acceleration = Force / Mass That's it. Simple huh! But how does this help us I hear you shout. Well, we now know that if everything stays how it is with all the forces being applied as they are at this particular instant in time, then the body's velocity will accelerate at the same rate. Let's plug in some numbers and try to make it clearer. Suppose the Mass of the object is 10. The Force being applied is (5,0,10) or, in other words, there is a force of 5 (somethings - Newtons usually) along the x-axis (pushing the object to the right), 0 upwards, and 10 along the z-axis (pushing the object away from us). So, imagine you are pushing the mug to your right, and your mate is pushing the mug (at the same time) twice as hard away from you. That's how the mug will be moving. But, we are calculating the acceleration so: Acceleration = (5, 0, 10) / 10 = (0.5, 0, 1) So, with the absence of any other forces (friction, air resistance, etc), the mug will accelerate at that rate forever (providing the forces are still applied to it). So, after 1 second it will be travelling at a velocity of (0.5, 0, 1). Then, after 2 seconds, it will be travelling at a velocity of (1, 0, 2), 3 seconds (1.5, 0, 3) and so on. 
 Now that we know what the acceleration is, we can work out the velocity of the mug. Imagine a car accelerating from a standing start. We know it will gradually get faster and faster because it is accelerating. Now, imagine taking a photo of the car at a particular moment in time. If we could see the Speedo, we would know that at that instant it was travelling at a certain speed. BUT, it was actually accelerating. So, if we know the rate of acceleration and how long it has been accelerating for (the deltaTime), we can work out the velocity at a particular time. The Velocity = Acceleration x Time. If we are accelerating at 10m/s, then after 5 seconds we are travelling at 50m/s. So, how does this knowledge help us now ? Well, we know the amount of time since the last calculations were performed. So, we assume that the acceleration was constant over this time. The same way we assumed that the forces acting we constant over the time step. So, taking the calculation for the acceleration, we can calculate the INSTANTANEOUS velocity of the object. In other words: InstVelocity = Acceleration x DeltaTime or InstVelocity = (0.5, 0, 1) x 0.01 = (0.005, 0, 0.01) 
 Now you add the instantaneous velocity to the accumulated velocity of the object because this is the amount the velocity has increased during the time step. 
 This may seem like it is travelling REALLY slow. But remember, we are only talking about a tiny amount of time. Accumulate this for a second's worth and you'll see it soon adds up. If there is no force acting on the body, then the Acceleration will be (0,0,0) and subsequently the velocity will be unchanged. Now we have the actual velocity of the body, we can work out the new position for the body. This is done by taking the velocity and multiplying it by the time step. This will tell us how far we have travelled in the time since the last call. So, once again, adding in the numbers (assuming the body was at rest at the start - i.e. Velocity = (0,0,0) and that it started at a position of (0,0,0)). Note that this is the distance we have travelled, NOT the position we are at. Velocity = (0.005, 0, 0.01) Distance = Velocity x DeltaTime = (0.005, 0, 0.01) x 0.01 = (0.00005, 0, 0.0001) So, the new position of the object is CenterOfMass += Distance = (0, 0, 0) + (0.00005, 0, 0.0001) = (0.00005, 0, 0.0001) 
 And so now we update the object and draw everything. And then we loop. We reset the forces acting on the body (set them to 0,0,0) ready for the next loop. If the forces are the same, then the next time our object will be at position (0.0001, 0, 0.0002). This may seem really small, but scale the forces and the mass for real examples, and run it with a proper calculation of the time elapsed since the last time, and it will look realistic. Try changing the forces as well. Here's an example, if you press the "a" key, then a force is applied. If you press the "b" key, then the same force is applied, but in the opposite direction. This will cause you to accelerate while holding down the "a" key. Travel at a constant speed while not pressing any key, and then decelerating (and eventually travel in the opposite direction) while the b key is pressed. Try changing the value for the Mass of the Body. This will affect the acceleration and deceleration using the same forces. As a task for the reader, implement the following pseudo code. Play around with the code and add in some graphics drawing code too. So, the loop looks like this : 
 If you want to add in gravity to the system, then there is a slight "gotcha". The value for Gravity on Earth is 9.8. This is along the y-axis downwards, so it can be represented by (0, -9.8, 0). However, this is NOT a force. The units for this value are m/s/s (metres per second per second). Or in other words it is an ACCELERATION. NOT a force. There are two ways to add in gravity. The first is to add it as an external force as you would any other force. Yes, I know I said that the value for gravity is an acceleration, not a force. That is still true. However, if you multiply the value for gravity by the mass of the body, then this will give you (remember - F=m*a) the force. You can then add that value. For example, the mass of the object is 10. The value of gravity is 9.8m/s/s. Therefore, you would add a force of (0, -98, 0) to your body and run through the loop. The second way to add in gravity is to define a gravity constant. Then, in the physics loop, were you calculate the forces on the body, and then convert this to the acceleration, you would add in the acceleration due to gravity. For example…. 
 If you do it via the first method, there are slightly more calculations to perform (although you could pre-calculate this value for each body). However, it would then be possible to add in a differing gravitational pull to different bodies depending where they were in your universe. It's up to you. 
 That's it. Still to come are rotations of the body, collision responses, and so on. But that's another time...... I hope you enjoyed this tutorial and found it useful. Please send any comments (good or bad) or questions to me! Contact information: 
 
 
 For a printable copy of this article, please click HERE. 
 This site is Copyright© 2000-2004, BlitzCoder. All rights reserved.   |