Newtons Laws of Motion


Newton’s Laws of Motion

Let’s take a quick look at the important laws of motion by our friend Isaac Newton. Check out Figure 13-2 to see these physics laws in action:

  • First Law - Objects stay in motion unless some external force interacts with them. This is really easy because all objects that can move usually have a movement vector or some velocity value anyway. Just don’t change that value unless you apply some force on it to slow it down, accelerate it, or change the direction. That’s it.

  • Second Law - When you do apply an external force, it means you can accelerate or decelerate an object, or if you have more than one dimension (well, you have three for 3D games) you can also change the direction the object is moving. In that case you just work with vectors instead of scalar values and all vector components (x, y, and z) will be changed instead of just one simple value. Because masses for your objects will always be constant (at least in most games I know of) you can use the simplified F = m * a formula, where “a” is the acceleration defined by the change of velocity divided by the change of time: a = dv/dt.

  • Third Law - Each action has an equal and opposite reaction. This means if you have a force like the gravity of the earth acting on an object, there is a reacting force of the object applying the same force on the earth in opposite direction. Because the earth has a much greater mass than some small object like a stone or apple it will not matter much to the earth if it is acting on it. But if you take a much bigger object like the sun, the gravity of the earth is even much smaller than the one from the sun. Good thing our earth is always in motion rotating around the sun keeping it in orbit, the same way the moon is orbiting around the earth.

image from book
Figure 13-2

One of the things Newton thought about when he wrote his “Principia Mathematica” showing these laws of motion for the first time was his law of universal gravitation, which explains the planetary movement and why the moon orbits the earth and the earth orbits the sun. Pretty exciting stuff back then, but today every school kid can calculate this, at least if they pay attention in physics class. Computers are more powerful than just giving them one planet moving around another one. In Rocket Commander you already saw thousands of asteroids interacting with each other. They don’t apply gravity on each other and they just collide and bounce off each other, but adding more reality to the unit tests there by adding gravity would not be a big challenge.

Keep It Simple

Because physics is a big topic and can require your full attention when you implement physics into your game, you should try to keep things simple. Often you don’t even have to know which formula is the correct one - just find something that works. For example, you don’t have to code anything to follow the first law of motion, and the third law can be ignored too most of the time because you are only interested in forces that change motion for your objects.

Before you dive deeper into the world of physics and take a quick look at the available physics engines, you should make sure you know exactly what you need for your Racing Game. There is no need to implement a highly complex physics engine allowing you to stack boxes and throw them over, if all you need is to be able to just drive around with your car and stay on the road. I really wish I would have had more time for implementing physics into the Racing Game, but the game had to be completed and I had quite a lot of other projects I was working on at the time. For that reason the Racing Game only uses a simple approach to physics and the collisions are handled in a very simplified way. But it works, and even though it stills requires a lot of fine-tuning and special care as you can see in the next chapter, you can get your car on the road and drive around.

Figure 13-3 shows the basic physics requirement for the Racing Game. Because you do not interact with any other object in the world and no landscape object has physics, you can fully turn your attention to the car and don’t have to worry about anything else.

image from book
Figure 13-3

These rules are implemented in a few lines of code, but it gets harder to tweak all the values and let the car interact correctly with the road:

  // [From CarPhysics.cs] // Handle car engine force float newAccelerationForce = 0.0f; if (Input.KeyboardUpPressed ||   Input.Keyboard.IsKeyDown(Keys.W) ||   Input.MouseLeftButtonPressed ||   Input.GamePadAPressed)   newAccelerationForce +=     MaxAccelerationPerSec; // [etc.] // Add acceleration force to total car force, but use the current // car direction! carForce +=   carDir * newAccelerationForce * (moveFactor * 85);// 70);//75); // Change speed with standard formula, use acceleration as our // force, gravity is handled below in the ApplyGravity method. float oldSpeed = speed; Vector3 speedChangeVector = carForce / CarMass; // Only use the amount important for our current direction // (slower rotation) if (speedChangeVector.Length() > 0) {   float speedApplyFactor =     Vector3.Dot(Vector3.Normalize(speedChangeVector), carDir);   if (speedApplyFactor > 1)     speedApplyFactor = 1;   speed += speedChangeVector.Length() * speedApplyFactor; } // if (speedChangeVector.Length) 

The code is maybe a little bit more complicated than it was when I implemented the solution the first time with the help of the unit test of the CarPhysics class, but it still basically increases the speed of the car when you accelerate through the keyboard up keys or the equivalent input keys and buttons. To allow letting the car drift into a different direction than you are actually heading I split up the car direction and the movement vector. Speed was used to update the length of the movement vector, but I ran into many problems and to simplify the problem I just use a scalar value for the speed now. This way it is also very easy to just drive backwards a little bit with the help of negative speed vectors while the car is still pointing forward.

Because your track is not just going straight ahead you need to rotate your car with the help of the left and right keyboard cursors or the gamepad, or even by using the mouse. Figure 13-4 shows the basic rules for the rotation of your car, which is very simple and implemented in just a few lines of code. To make rotations more smooth the last rotation value is still used, but reduced a bit.

image from book
Figure 13-4

  // First handle rotations (reduce last value) rotationChange *= 0.825f;// 75f; // Left/right changes rotation if (Input.KeyboardLeftPressed ||   Input.Keyboard.IsKeyDown(Keys.A))   rotationChange += MaxRotationPerSec * moveFactor / 2.5f; else if (Input.KeyboardRightPressed ||   Input.Keyboard.IsKeyDown(Keys.D) ||   Input.Keyboard.IsKeyDown(Keys.E))   rotationChange -= MaxRotationPerSec * moveFactor / 2.5f; else   rotationChange = 0; if (Input.MouseXMovement != 0)   rotationChange -=     (Input.MouseXMovement / 15.0f) *     MaxRotationPerSec * moveFactor; // Rotate dir around up vector // Interpolate rotatation amount. virtualRotationAmount += rotationChange; // Smooth over 200ms float interpolatedRotationChange =   (rotationChange + virtualRotationAmount) *   moveFactor / 0.225f;// / 0.200f; virtualRotationAmount -= interpolatedRotationChange; // We can't rotate our car ourself if it is currently not on the ground if (isCarOnGround)   carDir = Vector3.TransformNormal(carDir,     Matrix.CreateFromAxisAngle(carUp, interpolatedRotationChange)); 

A more complex way to handle the car physics makes sense if you have more than a few weeks’ time to develop your game, and if you really want more realistic calculations you could use more constants and forces to get the car behavior more realistic than I did. But my solution works too and it did not take much time to implement it.

If you want to check it out please use the TestCarPhysicsOnPlaneWithGuardRails unit test in the CarPhysics class. The unit test started out very simple with just the car and a plane rendered on the ground, which is rendered with the help of the new PlaneRenderer class. Later the guard rails and collision checking and response were added, which are discussed later in this chapter. This is an earlier version of the unit test before it was renamed to TestCarPhysicsOnPlaneWithGuardRails just showing you my test environment for handling the basic car physics. Figure 13-5 shows the result. Testing is done with the normal keys and input devices the game uses for controlling the car (up, down, left, right, and so on).

image from book
Figure 13-5

  static public void TestCarPhysicsOnPlane() {   PlaneRenderer plane = null;   TestGame.Start("TestCarPhysicsOnPlane",    delegate    {      plane = new PlaneRenderer(Vector3.Zero,        new Plane(new Vector3(0, 0, 1), 0),        new Material("CityGround", "CityGroundNormal"), 500.0f);      // Put car on the ground and use standard direction and up vectors   RacingGame.Player.SetCarPosition(         new Vector3(0, 0, 0),         new Vector3(0, 1, 0),         new Vector3(0, 0, 1));     },     delegate     {       // Test slow computers by slowing down the framerate with Ctrl       if (Input.Keyboard.IsKeyDown(Keys.LeftControl))         Thread.Sleep(75);       Matrix carMatrix = RacingGame.Player.UpdateCarMatrixAndCamera();       // Generate shadows, just the car does shadows       ShaderEffect.shadowMapping.GenerateShadows(         delegate         {           RacingGame.CarModel.GenerateShadow(carMatrix);         });       // Render shadows (on both the plane and the car)       ShaderEffect.shadowMapping.RenderShadows(         delegate         {           RacingGame.CarModel.UseShadow(carMatrix);           plane.UseShadow();         });       BaseGame.UI.RenderGameBackground();       // Show car and ground plane       RacingGame.CarModel.RenderCar(0, Color.White, carMatrix);       plane.Render();       // Just add brake tracks (we don't render the landscape here)       RacingGame.Landscape.RenderBrakeTracks();       // Render all 3d objects       BaseGame.MeshRenderManager.Render();       // Add shadows       ShaderEffect.shadowMapping.ShowShadows();       RacingGame.Player.DisplayPhysicsValuesAndHelp();     }); } // TestCarPhysicsOnPlane() 

Gravitation

Just driving around on a plane surface is easy to do, but not really fun, especially since the Racing Game allows you to drive crazy tracks with loopings, tunnels, hard curves, and so on. The collision detection and response techniques are discussed later in this chapter, but you can add gravity relatively quickly to your current TestCarPhysicsOnPlane unit test and fine-tune it a little bit more later.

You are just going to make a very simple change to the TestCarPhysicsOnPlane unit test by simply putting the car 10 meters above the ground in the initialization code. It should fall down now, but because you have not implemented any real physics yet (only the car controlling, accelerating, and steering was done until now) it just stays in the air (see Figure 13-6).

image from book
Figure 13-6

  // Put car 10m above the ground to test gravity and ground plane! RacingGame.Player.SetCarPosition(   new Vector3(0, 0, 10),   new Vector3(0, 1, 0),   new Vector3(0, 0, 1)); 

The Player class is derived from the ChaseCamera class, which is again derived from the CarPhysics class. This way all the car controlling, physics, player logic, and so on can be handled and accessed from one single place: the Player class. The ChaseCamera has two modes, similar to the modes of the SpaceCamera class from Rocket Commander:

  • The Free Camera Mode is usually used for all unit tests. Sometimes you have to change it for unit tests like the one you are currently working on to allow the same controller features as in the game.

  • Default Chase Car Game Camera is used for the game. Either used for the menu or replays to chase the camera behind the car and of course in the game to show and control the car.

Use the following lines in the initialization code to make sure the game camera is used and you don’t use any zoom-in time like in the game, so you can see the car falling down at the beginning:

  // Make sure we are not in free camera mode and can control the car RacingGame.Player.FreeCamera = false; RacingGame.Player.ZoomInTime = 0;   RacingGame.Player.SetCameraPosition(new Vector3(0, -5, 8)); 

The rest of the unit test can stay the same; the actual gravity computation happens in the Update method of the CarPhysics class, which calls the ApplyGravity method:

  /// <summary> /// Apply gravity /// </summary> private void ApplyGravity() {   // Fix car on ground   float distFromGround = Vector3Helper.SignedDistanceToPlane(     carPos, groundPlanePos, groundPlaneNormal);   isCarOnGround = distFromGround > -0.1f;   // Use very hard and instant gravity to fix if car is below ground!   float moveFactor = BaseGame.MoveFactorPerSecond;   float maxGravity = Gravity * moveFactor;   // Use more smooth gravity for jumping   float minGravity = -Gravity * moveFactor;      if (distFromGround > maxGravity)   {     distFromGround = maxGravity;     gravitySpeed = 0;   } // if (distFromGround)   if (distFromGround < minGravity)   {     distFromGround = minGravity;     gravitySpeed -= distFromGround;   } // if (distFromGround)   carPos.Z += distFromGround; } // ApplyGravity() 

This code basically just reduces the z position value of the car position until you reach the ground. Because the car might be lower than the road when you drive uphill or because of some precision error, the z position value is also corrected to reset the car back to the road level.

For tweaking the many constants are used, which are all defined at the very beginning of the CarPhysics class. These are the first three constants; changing the CarMass, for example, gives you control if the car is very heavy and almost glued to the ground or if it is as light as a feather and can fly a long time until gravity kicks in again:

  #region Constants /// <summary> /// Car is 1000 kg /// </summary> const float CarMass = 1000;//1000.0f; /// <summary> /// Gravity on earth is 9.81 m/s^2 /// </summary> const float Gravity = 9.81f; /// <summary> /// Max speed of our car is 275 mph. /// While we use mph for the display, we calculate internally with /// meters per sec since meter is the unit we use for everthing in the /// game. And it is a much nicer unit than miles or feet. /// </summary> public const float MaxSpeed =   275.0f * MphToMeterPerSec; /// <summary> /// Convert our meter per sec to mph for display. /// 1 mile = 1.609344 kilometers /// Each hour has 3600 seconds (60 min * 60 sec). /// 1 kilometer = 1000 meter. /// </summary> public const float MeterPerSecToMph =   1.609344f * ((60.0f*60.0f)/1000.0f),   MphToMeterPerSec = 1.0f / MeterPerSecToMph; // [etc.] 

You probably saw a couple of times now that I use meters instead of feet, inches, yards, miles, or whatever crazy formats there are in the U.S. Sorry, the rest of the world uses meters and it is an easier unit system for measuring and setting constants. I don’t even know constants like gravity in other unit systems and you can see that whenever I have other formats like Mph (Miles per hour) I use helper constants to convert from one format to the next. You can also use Google to convert from one format to another. Just type in “1500 meters as miles” and you will get the value in miles.

The new TestCarPhysicsOnPlane unit test allows you to control the car and it handles gravity correctly (see Figure 13-7). It also handles displaying the brake tracks on the ground after you suddenly try to stop the car.

image from book
Figure 13-7




Professional XNA Game Programming
Professional XNA Programming: Building Games for Xbox 360 and Windows with XNA Game Studio 2.0
ISBN: 0470261285
EAN: 2147483647
Year: 2007
Pages: 138

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net