TheoJansen.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  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.Graphics;
  9. namespace FarseerPhysics.SamplesFramework
  10. {
  11. public class TheoJansenWalker
  12. {
  13. private Sprite _body;
  14. private Body _chassis;
  15. private Sprite _engine;
  16. private Sprite _leftLeg;
  17. private Body[] _leftLegs;
  18. private Sprite _leftShoulder;
  19. private Body[] _leftShoulders;
  20. private RevoluteJoint _motorJoint;
  21. private bool _motorOn;
  22. private float _motorSpeed;
  23. private Vector2 _position;
  24. private Sprite _rightLeg;
  25. private Body[] _rightLegs;
  26. private Sprite _rightShoulder;
  27. private Body[] _rightShoulders;
  28. private PhysicsGameScreen _screen;
  29. private List<DistanceJoint> _walkerJoints;
  30. private Body _wheel;
  31. public TheoJansenWalker(World world, PhysicsGameScreen screen, Vector2 position)
  32. {
  33. _position = position;
  34. _motorSpeed = 2.0f;
  35. _motorOn = true;
  36. _screen = screen;
  37. _walkerJoints = new List<DistanceJoint>();
  38. _leftShoulders = new Body[3];
  39. _rightShoulders = new Body[3];
  40. _leftLegs = new Body[3];
  41. _rightLegs = new Body[3];
  42. Vector2 pivot = new Vector2(0f, -0.8f);
  43. // Chassis
  44. {
  45. PolygonShape shape = new PolygonShape(1f);
  46. shape.SetAsBox(2.5f, 1.0f);
  47. _body =
  48. new Sprite(_screen.ScreenManager.Assets.TextureFromShape(shape, MaterialType.Blank,
  49. Color.Beige, 1f));
  50. _chassis = BodyFactory.CreateBody(world);
  51. _chassis.BodyType = BodyType.Dynamic;
  52. _chassis.Position = pivot + _position;
  53. Fixture fixture = _chassis.CreateFixture(shape);
  54. fixture.CollisionGroup = -1;
  55. }
  56. {
  57. CircleShape shape = new CircleShape(1.6f, 1f);
  58. _engine =
  59. new Sprite(_screen.ScreenManager.Assets.TextureFromShape(shape, MaterialType.Waves,
  60. Color.Beige * 0.8f, 1f));
  61. _wheel = BodyFactory.CreateBody(world);
  62. _wheel.BodyType = BodyType.Dynamic;
  63. _wheel.Position = pivot + _position;
  64. Fixture fixture = _wheel.CreateFixture(shape);
  65. fixture.CollisionGroup = -1;
  66. }
  67. {
  68. _motorJoint = new RevoluteJoint(_wheel, _chassis, _wheel.GetLocalPoint(_chassis.Position), Vector2.Zero);
  69. _motorJoint.CollideConnected = false;
  70. _motorJoint.MotorSpeed = _motorSpeed;
  71. _motorJoint.MaxMotorTorque = 400f;
  72. _motorJoint.MotorEnabled = _motorOn;
  73. world.AddJoint(_motorJoint);
  74. }
  75. Vector2 wheelAnchor = pivot + new Vector2(0f, 0.8f);
  76. CreateLegTextures();
  77. CreateLeg(world, -1f, wheelAnchor, 0);
  78. CreateLeg(world, 1f, wheelAnchor, 0);
  79. _leftLeg.Origin = AssetCreator.CalculateOrigin(_leftLegs[0]);
  80. _leftShoulder.Origin = AssetCreator.CalculateOrigin(_leftShoulders[0]);
  81. _rightLeg.Origin = AssetCreator.CalculateOrigin(_rightLegs[0]);
  82. _rightShoulder.Origin = AssetCreator.CalculateOrigin(_rightShoulders[0]);
  83. _wheel.SetTransform(_wheel.Position, 120f * Settings.Pi / 180f);
  84. CreateLeg(world, -1f, wheelAnchor, 1);
  85. CreateLeg(world, 1f, wheelAnchor, 1);
  86. _wheel.SetTransform(_wheel.Position, -120f * Settings.Pi / 180f);
  87. CreateLeg(world, -1f, wheelAnchor, 2);
  88. CreateLeg(world, 1f, wheelAnchor, 2);
  89. }
  90. public void Reverse()
  91. {
  92. _motorSpeed *= -1f;
  93. _motorJoint.MotorSpeed = _motorSpeed;
  94. }
  95. private void CreateLeg(World world, float s, Vector2 wheelAnchor, int index)
  96. {
  97. Vector2 p1 = new Vector2(5.4f * s, 6.1f);
  98. Vector2 p2 = new Vector2(7.2f * s, 1.2f);
  99. Vector2 p3 = new Vector2(4.3f * s, 1.9f);
  100. Vector2 p4 = new Vector2(3.1f * s, -0.8f);
  101. Vector2 p5 = new Vector2(6.0f * s, -1.5f);
  102. Vector2 p6 = new Vector2(2.5f * s, -3.7f);
  103. PolygonShape poly1 = new PolygonShape(1f);
  104. PolygonShape poly2 = new PolygonShape(2f);
  105. Vertices vertices = new Vertices(3);
  106. if (s < 0f)
  107. {
  108. vertices.Add(p1);
  109. vertices.Add(p2);
  110. vertices.Add(p3);
  111. poly1.Set(vertices);
  112. vertices[0] = Vector2.Zero;
  113. vertices[1] = p5 - p4;
  114. vertices[2] = p6 - p4;
  115. poly2.Set(vertices);
  116. }
  117. else
  118. {
  119. vertices.Add(p1);
  120. vertices.Add(p3);
  121. vertices.Add(p2);
  122. poly1.Set(vertices);
  123. vertices[0] = Vector2.Zero;
  124. vertices[1] = p6 - p4;
  125. vertices[2] = p5 - p4;
  126. poly2.Set(vertices);
  127. }
  128. Body body1 = BodyFactory.CreateBody(world);
  129. body1.BodyType = BodyType.Dynamic;
  130. body1.Position = _position;
  131. body1.AngularDamping = 10f;
  132. if (s < 0f)
  133. {
  134. _leftLegs[index] = body1;
  135. }
  136. else
  137. {
  138. _rightLegs[index] = body1;
  139. }
  140. Body body2 = BodyFactory.CreateBody(world);
  141. body2.BodyType = BodyType.Dynamic;
  142. body2.Position = p4 + _position;
  143. body2.AngularDamping = 10f;
  144. if (s < 0f)
  145. {
  146. _leftShoulders[index] = body2;
  147. }
  148. else
  149. {
  150. _rightShoulders[index] = body2;
  151. }
  152. Fixture f1 = body1.CreateFixture(poly1);
  153. f1.CollisionGroup = -1;
  154. Fixture f2 = body2.CreateFixture(poly2);
  155. f2.CollisionGroup = -1;
  156. // Using a soft distanceraint can reduce some jitter.
  157. // It also makes the structure seem a bit more fluid by
  158. // acting like a suspension system.
  159. DistanceJoint djd = new DistanceJoint(body1, body2, body1.GetLocalPoint(p2 + _position),
  160. body2.GetLocalPoint(p5 + _position));
  161. djd.DampingRatio = 0.5f;
  162. djd.Frequency = 10f;
  163. world.AddJoint(djd);
  164. _walkerJoints.Add(djd);
  165. DistanceJoint djd2 = new DistanceJoint(body1, body2, body1.GetLocalPoint(p3 + _position),
  166. body2.GetLocalPoint(p4 + _position));
  167. djd2.DampingRatio = 0.5f;
  168. djd2.Frequency = 10f;
  169. world.AddJoint(djd2);
  170. _walkerJoints.Add(djd2);
  171. DistanceJoint djd3 = new DistanceJoint(body1, _wheel, body1.GetLocalPoint(p3 + _position),
  172. _wheel.GetLocalPoint(wheelAnchor + _position));
  173. djd3.DampingRatio = 0.5f;
  174. djd3.Frequency = 10f;
  175. world.AddJoint(djd3);
  176. _walkerJoints.Add(djd3);
  177. DistanceJoint djd4 = new DistanceJoint(body2, _wheel, body2.GetLocalPoint(p6 + _position),
  178. _wheel.GetLocalPoint(wheelAnchor + _position));
  179. djd4.DampingRatio = 0.5f;
  180. djd4.Frequency = 10f;
  181. world.AddJoint(djd4);
  182. _walkerJoints.Add(djd4);
  183. Vector2 anchor = p4 - new Vector2(0f, -0.8f);
  184. RevoluteJoint rjd = new RevoluteJoint(body2, _chassis, body2.GetLocalPoint(_chassis.GetWorldPoint(anchor)),
  185. anchor);
  186. world.AddJoint(rjd);
  187. }
  188. private void CreateLegTextures()
  189. {
  190. Vector2 p1 = new Vector2(-5.4f, 6.1f);
  191. Vector2 p2 = new Vector2(-7.2f, 1.2f);
  192. Vector2 p3 = new Vector2(-4.3f, 1.9f);
  193. Vector2 p4 = new Vector2(-2.9f, -0.7f);
  194. Vector2 p5 = new Vector2(0.6f, -2.9f);
  195. Vertices vertices = new Vertices(3);
  196. vertices.Add(p1);
  197. vertices.Add(p2);
  198. vertices.Add(p3);
  199. _leftLeg =
  200. new Sprite(_screen.ScreenManager.Assets.TextureFromVertices(vertices, MaterialType.Blank,
  201. Color.IndianRed * 0.8f, 1f));
  202. vertices[0] = Vector2.Zero;
  203. vertices[1] = p4;
  204. vertices[2] = p5;
  205. _leftShoulder =
  206. new Sprite(_screen.ScreenManager.Assets.TextureFromVertices(vertices, MaterialType.Blank,
  207. Color.Beige * 0.8f, 1f));
  208. p1.X *= -1f;
  209. p2.X *= -1f;
  210. p3.X *= -1f;
  211. p4.X *= -1f;
  212. p5.X *= -1f;
  213. vertices[0] = p1;
  214. vertices[1] = p3;
  215. vertices[2] = p2;
  216. _rightLeg =
  217. new Sprite(_screen.ScreenManager.Assets.TextureFromVertices(vertices, MaterialType.Blank,
  218. Color.IndianRed * 0.8f, 1f));
  219. vertices[0] = Vector2.Zero;
  220. vertices[1] = p5;
  221. vertices[2] = p4;
  222. _rightShoulder =
  223. new Sprite(_screen.ScreenManager.Assets.TextureFromVertices(vertices, MaterialType.Blank,
  224. Color.Beige * 0.8f, 1f));
  225. }
  226. public void Draw()
  227. {
  228. LineBatch _batch = _screen.ScreenManager.LineBatch;
  229. SpriteBatch _spriteBatch = _screen.ScreenManager.SpriteBatch;
  230. _spriteBatch.Begin(0, null, null, null, null, null, _screen.Camera.View);
  231. _spriteBatch.Draw(_body.Texture, ConvertUnits.ToDisplayUnits(_chassis.Position), null,
  232. Color.White, _chassis.Rotation, _body.Origin, 1f, SpriteEffects.None, 0f);
  233. _spriteBatch.End();
  234. _batch.Begin(_screen.Camera.SimProjection, _screen.Camera.SimView);
  235. for (int i = 0; i < _walkerJoints.Count; ++i)
  236. {
  237. _batch.DrawLine(_walkerJoints[i].WorldAnchorA, _walkerJoints[i].WorldAnchorB, Color.DarkRed);
  238. }
  239. _batch.End();
  240. _spriteBatch.Begin(0, null, null, null, null, null, _screen.Camera.View);
  241. for (int i = 0; i < 3; ++i)
  242. {
  243. _spriteBatch.Draw(_leftLeg.Texture, ConvertUnits.ToDisplayUnits(_leftLegs[i].Position), null,
  244. Color.White, _leftLegs[i].Rotation, _leftLeg.Origin, 1f, SpriteEffects.None, 0f);
  245. _spriteBatch.Draw(_leftShoulder.Texture, ConvertUnits.ToDisplayUnits(_leftShoulders[i].Position), null,
  246. Color.White, _leftShoulders[i].Rotation, _leftShoulder.Origin, 1f, SpriteEffects.None,
  247. 0f);
  248. _spriteBatch.Draw(_rightLeg.Texture, ConvertUnits.ToDisplayUnits(_rightLegs[i].Position), null,
  249. Color.White, _rightLegs[i].Rotation, _rightLeg.Origin, 1f, SpriteEffects.None, 0f);
  250. _spriteBatch.Draw(_rightShoulder.Texture, ConvertUnits.ToDisplayUnits(_rightShoulders[i].Position), null,
  251. Color.White, _rightShoulders[i].Rotation, _rightShoulder.Origin, 1f,
  252. SpriteEffects.None, 0f);
  253. }
  254. _spriteBatch.Draw(_engine.Texture, ConvertUnits.ToDisplayUnits(_wheel.Position), null,
  255. Color.White, _wheel.Rotation, _engine.Origin, 1f, SpriteEffects.None, 0f);
  256. _spriteBatch.End();
  257. }
  258. }
  259. }