/Farseer/Common/PathManager.cs

https://bitbucket.org/Grimelios/starlight · C# · 186 lines · 103 code · 26 blank · 57 comment · 6 complexity · 566e752d71fb6b422604a1472cc7e5b9 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using FarseerPhysics.Collision.Shapes;
  4. using FarseerPhysics.Common.Decomposition;
  5. using FarseerPhysics.Dynamics;
  6. using FarseerPhysics.Dynamics.Joints;
  7. using Microsoft.Xna.Framework;
  8. namespace FarseerPhysics.Common
  9. {
  10. /// <summary>
  11. /// An easy to use manager for creating paths.
  12. /// </summary>
  13. public static class PathManager
  14. {
  15. #region LinkType enum
  16. public enum LinkType
  17. {
  18. Revolute,
  19. Slider
  20. }
  21. #endregion
  22. //Contributed by Matthew Bettcher
  23. /// <summary>
  24. /// Convert a path into a set of edges and attaches them to the specified body.
  25. /// Note: use only for static edges.
  26. /// </summary>
  27. /// <param name="path">The path.</param>
  28. /// <param name="body">The body.</param>
  29. /// <param name="subdivisions">The subdivisions.</param>
  30. public static void ConvertPathToEdges(Path path, Body body, int subdivisions)
  31. {
  32. Vertices verts = path.GetVertices(subdivisions);
  33. if (path.Closed)
  34. {
  35. ChainShape chain = new ChainShape(verts, true);
  36. body.CreateFixture(chain);
  37. }
  38. else
  39. {
  40. for (int i = 1; i < verts.Count; i++)
  41. {
  42. body.CreateFixture(new EdgeShape(verts[i], verts[i - 1]));
  43. }
  44. }
  45. }
  46. /// <summary>
  47. /// Convert a closed path into a polygon.
  48. /// Convex decomposition is automatically performed.
  49. /// </summary>
  50. /// <param name="path">The path.</param>
  51. /// <param name="body">The body.</param>
  52. /// <param name="density">The density.</param>
  53. /// <param name="subdivisions">The subdivisions.</param>
  54. public static void ConvertPathToPolygon(Path path, Body body, float density, int subdivisions)
  55. {
  56. if (!path.Closed)
  57. throw new Exception("The path must be closed to convert to a polygon.");
  58. List<Vector2> verts = path.GetVertices(subdivisions);
  59. List<Vertices> decomposedVerts = Triangulate.ConvexPartition(new Vertices(verts), TriangulationAlgorithm.Bayazit);
  60. foreach (Vertices item in decomposedVerts)
  61. {
  62. body.CreateFixture(new PolygonShape(item, density));
  63. }
  64. }
  65. /// <summary>
  66. /// Duplicates the given Body along the given path for approximatly the given copies.
  67. /// </summary>
  68. /// <param name="world">The world.</param>
  69. /// <param name="path">The path.</param>
  70. /// <param name="shapes">The shapes.</param>
  71. /// <param name="type">The type.</param>
  72. /// <param name="copies">The copies.</param>
  73. /// <param name="userData"></param>
  74. /// <returns></returns>
  75. public static List<Body> EvenlyDistributeShapesAlongPath(World world, Path path, IEnumerable<Shape> shapes, BodyType type, int copies, object userData = null)
  76. {
  77. List<Vector3> centers = path.SubdivideEvenly(copies);
  78. List<Body> bodyList = new List<Body>();
  79. for (int i = 0; i < centers.Count; i++)
  80. {
  81. Body b = new Body(world);
  82. // copy the type from original body
  83. b.BodyType = type;
  84. b.Position = new Vector2(centers[i].X, centers[i].Y);
  85. b.Rotation = centers[i].Z;
  86. b.UserData = userData;
  87. foreach (Shape shape in shapes)
  88. {
  89. b.CreateFixture(shape);
  90. }
  91. bodyList.Add(b);
  92. }
  93. return bodyList;
  94. }
  95. /// <summary>
  96. /// Duplicates the given Body along the given path for approximatly the given copies.
  97. /// </summary>
  98. /// <param name="world">The world.</param>
  99. /// <param name="path">The path.</param>
  100. /// <param name="shape">The shape.</param>
  101. /// <param name="type">The type.</param>
  102. /// <param name="copies">The copies.</param>
  103. /// <param name="userData">The user data.</param>
  104. /// <returns></returns>
  105. public static List<Body> EvenlyDistributeShapesAlongPath(World world, Path path, Shape shape, BodyType type,
  106. int copies, object userData)
  107. {
  108. List<Shape> shapes = new List<Shape>(1);
  109. shapes.Add(shape);
  110. return EvenlyDistributeShapesAlongPath(world, path, shapes, type, copies, userData);
  111. }
  112. public static List<Body> EvenlyDistributeShapesAlongPath(World world, Path path, Shape shape, BodyType type, int copies)
  113. {
  114. return EvenlyDistributeShapesAlongPath(world, path, shape, type, copies, null);
  115. }
  116. /// <summary>
  117. /// Moves the given body along the defined path.
  118. /// </summary>
  119. /// <param name="path">The path.</param>
  120. /// <param name="body">The body.</param>
  121. /// <param name="time">The time.</param>
  122. /// <param name="strength">The strength.</param>
  123. /// <param name="timeStep">The time step.</param>
  124. public static void MoveBodyOnPath(Path path, Body body, float time, float strength, float timeStep)
  125. {
  126. Vector2 destination = path.GetPosition(time);
  127. Vector2 positionDelta = body.Position - destination;
  128. Vector2 velocity = (positionDelta / timeStep) * strength;
  129. body.LinearVelocity = -velocity;
  130. }
  131. /// <summary>
  132. /// Attaches the bodies with revolute joints.
  133. /// </summary>
  134. /// <param name="world">The world.</param>
  135. /// <param name="bodies">The bodies.</param>
  136. /// <param name="localAnchorA">The local anchor A.</param>
  137. /// <param name="localAnchorB">The local anchor B.</param>
  138. /// <param name="connectFirstAndLast">if set to <c>true</c> [connect first and last].</param>
  139. /// <param name="collideConnected">if set to <c>true</c> [collide connected].</param>
  140. public static List<RevoluteJoint> AttachBodiesWithRevoluteJoint(World world, List<Body> bodies, Vector2 localAnchorA, Vector2 localAnchorB, bool connectFirstAndLast, bool collideConnected)
  141. {
  142. List<RevoluteJoint> joints = new List<RevoluteJoint>(bodies.Count + 1);
  143. for (int i = 1; i < bodies.Count; i++)
  144. {
  145. RevoluteJoint joint = new RevoluteJoint(bodies[i], bodies[i - 1], localAnchorA, localAnchorB);
  146. joint.CollideConnected = collideConnected;
  147. world.AddJoint(joint);
  148. joints.Add(joint);
  149. }
  150. if (connectFirstAndLast)
  151. {
  152. RevoluteJoint lastjoint = new RevoluteJoint(bodies[0], bodies[bodies.Count - 1], localAnchorA, localAnchorB);
  153. lastjoint.CollideConnected = collideConnected;
  154. world.AddJoint(lastjoint);
  155. joints.Add(lastjoint);
  156. }
  157. return joints;
  158. }
  159. }
  160. }