Jypeli  5
The simple game programming library
FrictionLogic.cs
Siirry tämän tiedoston dokumentaatioon.
1 #region MIT License
2 /*
3  * Copyright (c) 2009 University of Jyväskylä, Department of Mathematical
4  * Information Technology.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #endregion
25 
26 /*
27  * Authors: Tero Jäntti, Tomi Karppinen, Janne Nikkanen.
28  */
29 
30 using System;
31 using AdvanceMath;
32 using AdvanceMath.Geometry2D;
33 using Physics2DDotNet;
34 using Physics2DDotNet.PhysicsLogics;
35 
36 namespace Jypeli
37 {
41 #if !XBOX && !WINDOWS_PHONE
42  [Serializable]
43 #endif
44  internal sealed class FrictionLogic : PhysicsLogic
45  {
46  private TopDownPhysicsGame parent;
47 
48  public FrictionLogic( TopDownPhysicsGame parent, Lifespan lifetime )
49  : base( lifetime )
50  {
51  this.parent = parent;
52  }
53 
54  private bool Overlap( Body b, Body surface )
55  {
56  if ( !b.Shape.CanGetIntersection || !surface.Shape.CanGetIntersection )
57  return false;
58 
59  Vector2D offset = b.State.Position.Linear - surface.State.Position.Linear;
60  IntersectionInfo ii;
61  var rect = surface.Rectangle;
62  double surfaceWidth = Math.Abs( rect.Max.X - rect.Min.X );
63  double surfaceHeight = Math.Abs( rect.Max.Y - rect.Min.Y );
64  double targetRadius = Math.Sqrt( Math.Pow( surfaceWidth, 2 ) + Math.Pow( surfaceHeight, 2 ) );
65 
66  for ( int i = 0; i < b.Shape.Vertexes.Length; i++ )
67  {
68  Vector2D vec = b.Shape.Vertexes[i] + offset + Vector2D.FromLengthAndAngle( 10, b.Shape.Vertexes[i].Angle );
69 
70  if ( surface.Shape.TryGetIntersection( vec, out ii ) )
71  return true;
72  }
73 
74  return false;
75  }
76 
81  protected internal override void RunLogic( TimeStep step )
82  {
83  double surfaceFriction = parent.KineticFriction;
84  double gravityNormal = parent.Gravity;
85 
86  foreach ( Body e in Bodies )
87  {
88  if ( e.IgnoresPhysicsLogics ) continue;
89  if ( !( e.Tag is PhysicsObject ) ) continue;
90 
91  double frictionCoefficient = 0;
92  if ( Game.Instance is TopDownPhysicsGame )
93  frictionCoefficient = ( (TopDownPhysicsGame)Game.Instance ).KineticFriction;
94 
95  foreach ( var surface in parent.Surfaces )
96  {
97  if ( surface.Body == e )
98  continue;
99 
100  if ( Overlap( e, surface.Body ) )
101  {
102  // Use the object's friction
103  frictionCoefficient = Math.Sqrt( surface.KineticFriction * e.Coefficients.DynamicFriction );
104 
105  // TODO: Instead of stopping on the first surface found, look for
106  // the surface with highest Z value.
107  break;
108  }
109  else
110  {
111  // Use the global friction
112  frictionCoefficient = Math.Sqrt( surfaceFriction * e.Coefficients.DynamicFriction );
113  }
114  }
115 
116  float friction = (float)( frictionCoefficient * gravityNormal * e.Mass.MassInv * step.Dt );
117  if ( e.State.Velocity.Linear.Magnitude <= friction )
118  e.State.Velocity.Linear = Vector2D.Zero;
119  else
120  e.State.Velocity.Linear.Magnitude -= friction;
121  }
122  }
123  }
124 }