Spiderweb.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. using System.Collections.Generic;
  2. using FarseerPhysics.Collision.Shapes;
  3. using FarseerPhysics.Common;
  4. using FarseerPhysics.Dynamics;
  5. using FarseerPhysics.Dynamics.Joints;
  6. using FarseerPhysics.Factories;
  7. using Microsoft.Xna.Framework;
  8. using Microsoft.Xna.Framework.Content;
  9. using Microsoft.Xna.Framework.Graphics;
  10. namespace FarseerPhysics.SamplesFramework
  11. {
  12. public class Spiderweb
  13. {
  14. private Sprite _goo;
  15. private Sprite _link;
  16. private float _radius;
  17. private float _spriteScale;
  18. private World _world;
  19. public Spiderweb(World world, Vector2 position, float radius, int rings, int sides)
  20. {
  21. const float breakpoint = 100f;
  22. _world = world;
  23. _radius = radius;
  24. List<List<Body>> ringBodys = new List<List<Body>>(rings);
  25. for (int i = 1; i < rings; ++i)
  26. {
  27. Vertices vertices = PolygonTools.CreateCircle(i * 2.9f, sides);
  28. List<Body> bodies = new List<Body>(sides);
  29. //Create the first goo
  30. Body prev = BodyFactory.CreateCircle(world, radius, 0.2f, vertices[0]);
  31. prev.FixedRotation = true;
  32. prev.Position += position;
  33. prev.BodyType = BodyType.Dynamic;
  34. bodies.Add(prev);
  35. //Connect the first goo to the next
  36. for (int j = 1; j < vertices.Count; ++j)
  37. {
  38. Body bod = BodyFactory.CreateCircle(world, radius, 0.2f, vertices[j]);
  39. bod.FixedRotation = true;
  40. bod.BodyType = BodyType.Dynamic;
  41. bod.Position += position;
  42. DistanceJoint dj = JointFactory.CreateDistanceJoint(world, prev, bod, Vector2.Zero, Vector2.Zero);
  43. dj.Frequency = 4.0f;
  44. dj.DampingRatio = 0.5f;
  45. dj.Breakpoint = breakpoint;
  46. prev = bod;
  47. bodies.Add(bod);
  48. }
  49. //Connect the first and the last box
  50. DistanceJoint djEnd = JointFactory.CreateDistanceJoint(world, bodies[0], bodies[bodies.Count - 1],
  51. Vector2.Zero, Vector2.Zero);
  52. djEnd.Frequency = 4.0f;
  53. djEnd.DampingRatio = 0.5f;
  54. djEnd.Breakpoint = breakpoint;
  55. ringBodys.Add(bodies);
  56. }
  57. //Create an outer ring
  58. Vertices lastRing = PolygonTools.CreateCircle(rings * 2.9f, sides);
  59. lastRing.Translate(ref position);
  60. List<Body> lastRingFixtures = ringBodys[ringBodys.Count - 1];
  61. //Fix each of the fixtures of the outer ring
  62. for (int j = 0; j < lastRingFixtures.Count; ++j)
  63. {
  64. FixedDistanceJoint fdj = JointFactory.CreateFixedDistanceJoint(world, lastRingFixtures[j], Vector2.Zero,
  65. lastRing[j]);
  66. fdj.Frequency = 4.0f;
  67. fdj.DampingRatio = 0.5f;
  68. fdj.Breakpoint = breakpoint;
  69. }
  70. //Interconnect the rings
  71. for (int i = 1; i < ringBodys.Count; i++)
  72. {
  73. List<Body> prev = ringBodys[i - 1];
  74. List<Body> current = ringBodys[i];
  75. for (int j = 0; j < prev.Count; j++)
  76. {
  77. Body prevFixture = prev[j];
  78. Body currentFixture = current[j];
  79. DistanceJoint dj = JointFactory.CreateDistanceJoint(world, prevFixture, currentFixture, Vector2.Zero,
  80. Vector2.Zero);
  81. dj.Frequency = 4.0f;
  82. dj.DampingRatio = 0.5f;
  83. }
  84. }
  85. }
  86. public void LoadContent(ContentManager content)
  87. {
  88. _link = new Sprite(content.Load<Texture2D>("Samples/link"));
  89. _goo = new Sprite(content.Load<Texture2D>("Samples/goo"));
  90. _spriteScale = 2f * ConvertUnits.ToDisplayUnits(_radius) / _goo.Texture.Width;
  91. }
  92. public void Draw(SpriteBatch batch)
  93. {
  94. foreach (Joint j in _world.JointList)
  95. {
  96. if (j.Enabled && j.JointType != JointType.FixedMouse)
  97. {
  98. Vector2 pos = ConvertUnits.ToDisplayUnits((j.WorldAnchorA + j.WorldAnchorB) / 2f);
  99. Vector2 AtoB = j.WorldAnchorB - j.WorldAnchorA;
  100. float distance = ConvertUnits.ToDisplayUnits(AtoB.Length()) + 8f * _spriteScale;
  101. Vector2 scale = new Vector2(distance / _link.Texture.Width, _spriteScale);
  102. Vector2 unitx = Vector2.UnitX;
  103. float angle = (float)MathUtils.VectorAngle(ref unitx, ref AtoB);
  104. batch.Draw(_link.Texture, pos, null, Color.White, angle, _link.Origin, scale, SpriteEffects.None, 0f);
  105. }
  106. }
  107. foreach (Body b in _world.BodyList)
  108. {
  109. if (b.Enabled && b.FixtureList[0].ShapeType == ShapeType.Circle)
  110. {
  111. batch.Draw(_goo.Texture, ConvertUnits.ToDisplayUnits(b.Position), null,
  112. Color.White, 0f, _goo.Origin, _spriteScale, SpriteEffects.None, 0f);
  113. }
  114. }
  115. }
  116. }
  117. }