BodyFactory.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. using System;
  2. using System.Collections.Generic;
  3. using FarseerPhysics.Collision.Shapes;
  4. using FarseerPhysics.Common;
  5. using FarseerPhysics.Common.Decomposition;
  6. using FarseerPhysics.Dynamics;
  7. using Microsoft.Xna.Framework;
  8. namespace FarseerPhysics.Factories
  9. {
  10. public static class BodyFactory
  11. {
  12. public static Body CreateBody(World world)
  13. {
  14. return CreateBody(world, null);
  15. }
  16. public static Body CreateBody(World world, object userData)
  17. {
  18. Body body = new Body(world, userData);
  19. return body;
  20. }
  21. public static Body CreateBody(World world, Vector2 position)
  22. {
  23. return CreateBody(world, position, null);
  24. }
  25. public static Body CreateBody(World world, Vector2 position, object userData)
  26. {
  27. Body body = CreateBody(world, userData);
  28. body.Position = position;
  29. return body;
  30. }
  31. public static Body CreateEdge(World world, Vector2 start, Vector2 end)
  32. {
  33. return CreateEdge(world, start, end, null);
  34. }
  35. public static Body CreateEdge(World world, Vector2 start, Vector2 end, object userData)
  36. {
  37. Body body = CreateBody(world);
  38. FixtureFactory.AttachEdge(start, end, body, userData);
  39. return body;
  40. }
  41. public static Body CreateLoopShape(World world, Vertices vertices)
  42. {
  43. return CreateLoopShape(world, vertices, null);
  44. }
  45. public static Body CreateLoopShape(World world, Vertices vertices, object userData)
  46. {
  47. return CreateLoopShape(world, vertices, Vector2.Zero, userData);
  48. }
  49. public static Body CreateLoopShape(World world, Vertices vertices, Vector2 position)
  50. {
  51. return CreateLoopShape(world, vertices, position, null);
  52. }
  53. public static Body CreateLoopShape(World world, Vertices vertices, Vector2 position,
  54. object userData)
  55. {
  56. Body body = CreateBody(world, position);
  57. FixtureFactory.AttachLoopShape(vertices, body, userData);
  58. return body;
  59. }
  60. public static Body CreateRectangle(World world, float width, float height, float density)
  61. {
  62. return CreateRectangle(world, width, height, density, null);
  63. }
  64. public static Body CreateRectangle(World world, float width, float height, float density, object userData)
  65. {
  66. return CreateRectangle(world, width, height, density, Vector2.Zero, userData);
  67. }
  68. public static Body CreateRectangle(World world, float width, float height, float density, Vector2 position)
  69. {
  70. return CreateRectangle(world, width, height, density, position, null);
  71. }
  72. public static Body CreateRectangle(World world, float width, float height, float density, Vector2 position,
  73. object userData)
  74. {
  75. if (width <= 0)
  76. throw new ArgumentOutOfRangeException("width", "Width must be more than 0 meters");
  77. if (height <= 0)
  78. throw new ArgumentOutOfRangeException("height", "Height must be more than 0 meters");
  79. Body newBody = CreateBody(world, position);
  80. Vertices rectangleVertices = PolygonTools.CreateRectangle(width / 2, height / 2);
  81. PolygonShape rectangleShape = new PolygonShape(rectangleVertices, density);
  82. newBody.CreateFixture(rectangleShape, userData);
  83. return newBody;
  84. }
  85. public static Body CreateCircle(World world, float radius, float density)
  86. {
  87. return CreateCircle(world, radius, density, null);
  88. }
  89. public static Body CreateCircle(World world, float radius, float density, object userData)
  90. {
  91. return CreateCircle(world, radius, density, Vector2.Zero, userData);
  92. }
  93. public static Body CreateCircle(World world, float radius, float density, Vector2 position)
  94. {
  95. return CreateCircle(world, radius, density, position, null);
  96. }
  97. public static Body CreateCircle(World world, float radius, float density, Vector2 position, object userData)
  98. {
  99. Body body = CreateBody(world, position);
  100. FixtureFactory.AttachCircle(radius, density, body, userData);
  101. return body;
  102. }
  103. public static Body CreateEllipse(World world, float xRadius, float yRadius, int edges, float density)
  104. {
  105. return CreateEllipse(world, xRadius, yRadius, edges, density, null);
  106. }
  107. public static Body CreateEllipse(World world, float xRadius, float yRadius, int edges, float density,
  108. object userData)
  109. {
  110. return CreateEllipse(world, xRadius, yRadius, edges, density, Vector2.Zero, userData);
  111. }
  112. public static Body CreateEllipse(World world, float xRadius, float yRadius, int edges, float density,
  113. Vector2 position)
  114. {
  115. return CreateEllipse(world, xRadius, yRadius, edges, density, position, null);
  116. }
  117. public static Body CreateEllipse(World world, float xRadius, float yRadius, int edges, float density,
  118. Vector2 position, object userData)
  119. {
  120. Body body = CreateBody(world, position);
  121. FixtureFactory.AttachEllipse(xRadius, yRadius, edges, density, body, userData);
  122. return body;
  123. }
  124. public static Body CreatePolygon(World world, Vertices vertices, float density)
  125. {
  126. return CreatePolygon(world, vertices, density, null);
  127. }
  128. public static Body CreatePolygon(World world, Vertices vertices, float density, object userData)
  129. {
  130. return CreatePolygon(world, vertices, density, Vector2.Zero, userData);
  131. }
  132. public static Body CreatePolygon(World world, Vertices vertices, float density, Vector2 position)
  133. {
  134. return CreatePolygon(world, vertices, density, position, null);
  135. }
  136. public static Body CreatePolygon(World world, Vertices vertices, float density, Vector2 position,
  137. object userData)
  138. {
  139. Body body = CreateBody(world, position);
  140. FixtureFactory.AttachPolygon(vertices, density, body, userData);
  141. return body;
  142. }
  143. public static Body CreateCompoundPolygon(World world, List<Vertices> list, float density)
  144. {
  145. return CreateCompoundPolygon(world, list, density, BodyType.Static);
  146. }
  147. public static Body CreateCompoundPolygon(World world, List<Vertices> list, float density,
  148. object userData)
  149. {
  150. return CreateCompoundPolygon(world, list, density, Vector2.Zero, userData);
  151. }
  152. public static Body CreateCompoundPolygon(World world, List<Vertices> list, float density,
  153. Vector2 position)
  154. {
  155. return CreateCompoundPolygon(world, list, density, position, null);
  156. }
  157. public static Body CreateCompoundPolygon(World world, List<Vertices> list, float density,
  158. Vector2 position, object userData)
  159. {
  160. //We create a single body
  161. Body polygonBody = CreateBody(world, position);
  162. FixtureFactory.AttachCompoundPolygon(list, density, polygonBody, userData);
  163. return polygonBody;
  164. }
  165. public static Body CreateGear(World world, float radius, int numberOfTeeth, float tipPercentage,
  166. float toothHeight, float density)
  167. {
  168. return CreateGear(world, radius, numberOfTeeth, tipPercentage, toothHeight, density, null);
  169. }
  170. public static Body CreateGear(World world, float radius, int numberOfTeeth, float tipPercentage,
  171. float toothHeight, float density, object userData)
  172. {
  173. Vertices gearPolygon = PolygonTools.CreateGear(radius, numberOfTeeth, tipPercentage, toothHeight);
  174. //Gears can in some cases be convex
  175. if (!gearPolygon.IsConvex())
  176. {
  177. //Decompose the gear:
  178. List<Vertices> list = EarclipDecomposer.ConvexPartition(gearPolygon);
  179. return CreateCompoundPolygon(world, list, density, userData);
  180. }
  181. return CreatePolygon(world, gearPolygon, density, userData);
  182. }
  183. /// <summary>
  184. /// Creates a capsule.
  185. /// Note: Automatically decomposes the capsule if it contains too many vertices (controlled by Settings.MaxPolygonVertices)
  186. /// </summary>
  187. /// <param name="world">The world.</param>
  188. /// <param name="height">The height.</param>
  189. /// <param name="topRadius">The top radius.</param>
  190. /// <param name="topEdges">The top edges.</param>
  191. /// <param name="bottomRadius">The bottom radius.</param>
  192. /// <param name="bottomEdges">The bottom edges.</param>
  193. /// <param name="density">The density.</param>
  194. /// <param name="position">The position.</param>
  195. /// <returns></returns>
  196. public static Body CreateCapsule(World world, float height, float topRadius, int topEdges,
  197. float bottomRadius,
  198. int bottomEdges, float density, Vector2 position, object userData)
  199. {
  200. Vertices verts = PolygonTools.CreateCapsule(height, topRadius, topEdges, bottomRadius, bottomEdges);
  201. Body body;
  202. //There are too many vertices in the capsule. We decompose it.
  203. if (verts.Count >= Settings.MaxPolygonVertices)
  204. {
  205. List<Vertices> vertList = EarclipDecomposer.ConvexPartition(verts);
  206. body = CreateCompoundPolygon(world, vertList, density, userData);
  207. body.Position = position;
  208. return body;
  209. }
  210. body = CreatePolygon(world, verts, density, userData);
  211. body.Position = position;
  212. return body;
  213. }
  214. public static Body CreateCapsule(World world, float height, float topRadius, int topEdges,
  215. float bottomRadius,
  216. int bottomEdges, float density, Vector2 position)
  217. {
  218. return CreateCapsule(world, height, topRadius, topEdges, bottomRadius, bottomEdges, density, position, null);
  219. }
  220. public static Body CreateCapsule(World world, float height, float endRadius, float density)
  221. {
  222. return CreateCapsule(world, height, endRadius, density, null);
  223. }
  224. public static Body CreateCapsule(World world, float height, float endRadius, float density,
  225. object userData)
  226. {
  227. //Create the middle rectangle
  228. Vertices rectangle = PolygonTools.CreateRectangle(endRadius, height / 2);
  229. List<Vertices> list = new List<Vertices>();
  230. list.Add(rectangle);
  231. Body body = CreateCompoundPolygon(world, list, density, userData);
  232. //Create the two circles
  233. CircleShape topCircle = new CircleShape(endRadius, density);
  234. topCircle.Position = new Vector2(0, height / 2);
  235. body.CreateFixture(topCircle, userData);
  236. CircleShape bottomCircle = new CircleShape(endRadius, density);
  237. bottomCircle.Position = new Vector2(0, -(height / 2));
  238. body.CreateFixture(bottomCircle, userData);
  239. return body;
  240. }
  241. /// <summary>
  242. /// Creates a rounded rectangle.
  243. /// Note: Automatically decomposes the capsule if it contains too many vertices (controlled by Settings.MaxPolygonVertices)
  244. /// </summary>
  245. /// <param name="world">The world.</param>
  246. /// <param name="width">The width.</param>
  247. /// <param name="height">The height.</param>
  248. /// <param name="xRadius">The x radius.</param>
  249. /// <param name="yRadius">The y radius.</param>
  250. /// <param name="segments">The segments.</param>
  251. /// <param name="density">The density.</param>
  252. /// <param name="position">The position.</param>
  253. /// <returns></returns>
  254. public static Body CreateRoundedRectangle(World world, float width, float height, float xRadius,
  255. float yRadius,
  256. int segments, float density, Vector2 position,
  257. object userData)
  258. {
  259. Vertices verts = PolygonTools.CreateRoundedRectangle(width, height, xRadius, yRadius, segments);
  260. //There are too many vertices in the capsule. We decompose it.
  261. if (verts.Count >= Settings.MaxPolygonVertices)
  262. {
  263. List<Vertices> vertList = EarclipDecomposer.ConvexPartition(verts);
  264. Body body = CreateCompoundPolygon(world, vertList, density, userData);
  265. body.Position = position;
  266. return body;
  267. }
  268. return CreatePolygon(world, verts, density);
  269. }
  270. public static Body CreateRoundedRectangle(World world, float width, float height, float xRadius,
  271. float yRadius,
  272. int segments, float density, Vector2 position)
  273. {
  274. return CreateRoundedRectangle(world, width, height, xRadius, yRadius, segments, density, position, null);
  275. }
  276. public static Body CreateRoundedRectangle(World world, float width, float height, float xRadius,
  277. float yRadius,
  278. int segments, float density)
  279. {
  280. return CreateRoundedRectangle(world, width, height, xRadius, yRadius, segments, density, null);
  281. }
  282. public static Body CreateRoundedRectangle(World world, float width, float height, float xRadius,
  283. float yRadius,
  284. int segments, float density, object userData)
  285. {
  286. return CreateRoundedRectangle(world, width, height, xRadius, yRadius, segments, density, Vector2.Zero,
  287. userData);
  288. }
  289. public static BreakableBody CreateBreakableBody(World world, Vertices vertices, float density)
  290. {
  291. return CreateBreakableBody(world, vertices, density, null);
  292. }
  293. public static BreakableBody CreateBreakableBody(World world, Vertices vertices, float density, object userData)
  294. {
  295. return CreateBreakableBody(world, vertices, density, Vector2.Zero, userData);
  296. }
  297. /// <summary>
  298. /// Creates a breakable body. You would want to remove collinear points before using this.
  299. /// </summary>
  300. /// <param name="world">The world.</param>
  301. /// <param name="vertices">The vertices.</param>
  302. /// <param name="density">The density.</param>
  303. /// <param name="position">The position.</param>
  304. /// <returns></returns>
  305. public static BreakableBody CreateBreakableBody(World world, Vertices vertices, float density, Vector2 position,
  306. object userData)
  307. {
  308. List<Vertices> triangles = EarclipDecomposer.ConvexPartition(vertices);
  309. BreakableBody breakableBody = new BreakableBody(triangles, world, density, userData);
  310. breakableBody.MainBody.Position = position;
  311. world.AddBreakableBody(breakableBody);
  312. return breakableBody;
  313. }
  314. public static BreakableBody CreateBreakableBody(World world, Vertices vertices, float density, Vector2 position)
  315. {
  316. return CreateBreakableBody(world, vertices, density, position, null);
  317. }
  318. public static Body CreateLineArc(World world, float radians, int sides, float radius, Vector2 position,
  319. float angle, bool closed)
  320. {
  321. Body body = CreateBody(world);
  322. FixtureFactory.AttachLineArc(radians, sides, radius, position, angle, closed, body);
  323. return body;
  324. }
  325. public static Body CreateSolidArc(World world, float density, float radians, int sides, float radius,
  326. Vector2 position, float angle)
  327. {
  328. Body body = CreateBody(world);
  329. FixtureFactory.AttachSolidArc(density, radians, sides, radius, position, angle, body);
  330. return body;
  331. }
  332. }
  333. }