PageRenderTime 26ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/AAEngine.Box2D/Box2DSpatialComponent.cs

http://aaengine.codeplex.com
C# | 399 lines | 339 code | 47 blank | 13 comment | 57 complexity | 478bcae7c17712c68ccae037a96f178c MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. /*******************************************************************************
  2. * AAEngine
  3. * Copyright (c) 2010 Mike Jarosch
  4. *
  5. * Original source PushButton Engine:
  6. * Copyright (C) 2009 PushButton Labs, LLC
  7. * For more information see http://www.pushbuttonengine.com
  8. *
  9. * This file is licensed under the terms of the MIT license, which is included
  10. * in the "MIT License.txt" file at the root directory of this SDK.
  11. ******************************************************************************/
  12. using System;
  13. using Microsoft.Xna.Framework;
  14. using Box2D.XNA;
  15. using AAEngine.Engine;
  16. using AAEngine.Engine.Core;
  17. using AAEngine.Engine.Debug;
  18. using AAEngine.Engine.Entities;
  19. using AAEngine.Rendering2D;
  20. namespace AAEngine.Box2D
  21. {
  22. public class Box2DSpatialComponent : EntityComponent, IMobileSpatialObject2D
  23. {
  24. public Action<Box2DSpatialComponent> OnAddedCallback { get; set; }
  25. private Box2DManagerComponent _manager;
  26. private ObjectType _collidesWithTypes;
  27. private ObjectType _collisionType;
  28. private Vector2 _size = new Vector2(10, 10);
  29. private bool _canMove = true;
  30. private bool _canRotate = true;
  31. private Vector2 _linearVelocity = Vector2.Zero;
  32. private float _angularVelocity = 0;
  33. private bool _canSleep = true;
  34. private CollisionShape[] _collisionShapes;
  35. private Body _body;
  36. private BodyDef _bodyDef = new BodyDef();
  37. public Box2DManagerComponent SpatialManager
  38. {
  39. get { return _manager; }
  40. set
  41. {
  42. if (_body != null)
  43. {
  44. Logger.Warn(this, "set_SpatialManager", "The manager can only be set before the component is registered.");
  45. return;
  46. }
  47. _manager = value;
  48. }
  49. }
  50. public Body Body { get { return _body; } }
  51. public ObjectType ObjectMask { get { return _collidesWithTypes; } }
  52. public Box WorldExtents
  53. {
  54. get
  55. {
  56. Vector2 halfSize = _size * 0.5f;
  57. Vector2 min = new Vector2(Position.X - halfSize.X, Position.Y - halfSize.Y);
  58. Vector2 max = new Vector2(Position.X + halfSize.X, Position.Y + halfSize.Y);
  59. return new Box(min, max);
  60. }
  61. }
  62. public bool CastRay(Vector2 start, Vector2 end, ObjectType mask, ref RayHitInfo result)
  63. {
  64. throw new NotImplementedException();
  65. }
  66. public bool PointOccupied(Vector2 position, ObjectType mask, IScene2D scene)
  67. {
  68. ContainmentType contains = WorldExtents.Contains(position);
  69. return contains == ContainmentType.Contains || contains == ContainmentType.Intersects;
  70. }
  71. public ObjectType CollisionType
  72. {
  73. get { return _collisionType; }
  74. set
  75. {
  76. _collisionType = value;
  77. if (_body != null)
  78. {
  79. BuildCollisionShapes();
  80. }
  81. }
  82. }
  83. public ObjectType CollidesWithTypes
  84. {
  85. get { return _collidesWithTypes; }
  86. set
  87. {
  88. _collidesWithTypes = value;
  89. if (_body != null)
  90. {
  91. BuildCollisionShapes();
  92. }
  93. }
  94. }
  95. public Vector2 Position
  96. {
  97. get
  98. {
  99. if (_body != null)
  100. {
  101. Vector2 pos = _body.GetPosition();
  102. return new Vector2(pos.X * _manager.Scale, pos.Y * _manager.Scale);
  103. }
  104. return _bodyDef.position;
  105. }
  106. set
  107. {
  108. _bodyDef.position = value;
  109. if (_body != null)
  110. {
  111. value *= _manager.InverseScale;
  112. _body.SetTransform(value, _body.GetAngle());
  113. }
  114. }
  115. }
  116. public float Rotation
  117. {
  118. get
  119. {
  120. float rotation = _bodyDef.angle;
  121. if (_body != null)
  122. {
  123. rotation = _body.GetAngle();
  124. }
  125. return MathHelper.ToDegrees(rotation);
  126. }
  127. set
  128. {
  129. float rotation = MathHelper.ToRadians(value);
  130. _bodyDef.angle = rotation;
  131. if (_body != null)
  132. {
  133. _body.SetTransform(_body.GetPosition(), rotation);
  134. }
  135. }
  136. }
  137. public Vector2 Size
  138. {
  139. get { return _size; }
  140. set
  141. {
  142. _size = value;
  143. if (_body != null)
  144. {
  145. BuildCollisionShapes();
  146. }
  147. }
  148. }
  149. public Vector2 LinearVelocity
  150. {
  151. get
  152. {
  153. if (_body != null)
  154. {
  155. _linearVelocity = _body.GetLinearVelocity() * _manager.Scale;
  156. }
  157. return _linearVelocity;
  158. }
  159. set
  160. {
  161. _linearVelocity = value;
  162. if (_body != null)
  163. {
  164. Vector2 velocity = _linearVelocity * _manager.InverseScale;
  165. _body.SetLinearVelocity(velocity);
  166. }
  167. }
  168. }
  169. public float AngularVelocity
  170. {
  171. get
  172. {
  173. if (_body != null)
  174. {
  175. _angularVelocity = MathHelper.ToDegrees(_body.GetAngularVelocity());
  176. }
  177. return _angularVelocity;
  178. }
  179. set
  180. {
  181. _angularVelocity = value;
  182. if (_body != null)
  183. {
  184. _body.SetAngularVelocity(MathHelper.ToRadians(value));
  185. }
  186. }
  187. }
  188. public bool CanMove
  189. {
  190. get { return _canMove; }
  191. set
  192. {
  193. _canMove = value;
  194. //_bodyDef.type = _canMove ? BodyType.Dynamic : BodyType.Static;
  195. if (_body != null)
  196. {
  197. UpdateMass();
  198. //_body.SetType(_canMove ? BodyType.Dynamic : BodyType.Static);
  199. }
  200. }
  201. }
  202. public bool CanRotate
  203. {
  204. get { return _canRotate; }
  205. set
  206. {
  207. _canRotate = value;
  208. if (_body != null)
  209. {
  210. UpdateMass();
  211. }
  212. }
  213. }
  214. public bool CanSleep
  215. {
  216. get { return _canSleep; }
  217. set
  218. {
  219. _canSleep = value;
  220. _bodyDef.allowSleep = value;
  221. if (_body != null)
  222. {
  223. _body.AllowSleeping(value);
  224. }
  225. }
  226. }
  227. public bool CollidesContinuously
  228. {
  229. get
  230. {
  231. if (_body != null)
  232. {
  233. return _body.IsBullet;
  234. }
  235. return _bodyDef.bullet;
  236. }
  237. set
  238. {
  239. _bodyDef.bullet = value;
  240. if (_body != null)
  241. {
  242. _body.SetBullet(value);
  243. }
  244. }
  245. }
  246. public BodyType BodyType
  247. {
  248. get
  249. {
  250. if (_body != null)
  251. {
  252. return _body.GetType();
  253. }
  254. return _bodyDef.type;
  255. }
  256. set
  257. {
  258. _bodyDef.type = value;
  259. if (_body != null)
  260. {
  261. _body.SetType(value);
  262. }
  263. }
  264. }
  265. public CollisionShape[] CollisionShapes
  266. {
  267. get { return _collisionShapes; }
  268. set
  269. {
  270. _collisionShapes = value;
  271. if (_body != null)
  272. {
  273. BuildCollisionShapes();
  274. }
  275. }
  276. }
  277. public void BuildCollisionShapes()
  278. {
  279. if (_body == null)
  280. {
  281. Logger.Warn(this, "BuildCollisionShapes", "Cannot build collision shapes prior to registration.");
  282. return;
  283. }
  284. Fixture fixture = _body.GetFixtureList();
  285. while (fixture != null)
  286. {
  287. Fixture nextFixture = fixture.GetNext();
  288. _body.DestroyFixture(fixture);
  289. fixture = nextFixture;
  290. }
  291. if (_collisionShapes != null)
  292. {
  293. foreach (CollisionShape shape in _collisionShapes)
  294. {
  295. _body.CreateFixture(shape.CreateFixture(this));
  296. }
  297. }
  298. UpdateMass();
  299. }
  300. public void UpdateMass()
  301. {
  302. _body.ResetMassData();
  303. if (!_canMove || !_canRotate)
  304. {
  305. MassData mass = new MassData();
  306. mass.center = _body.GetLocalCenter();
  307. if (_canMove)
  308. {
  309. mass.mass = _body.GetMass();
  310. }
  311. else
  312. {
  313. mass.mass = 0;
  314. }
  315. if (_canRotate)
  316. {
  317. mass.I = _body.GetInertia();
  318. }
  319. else
  320. {
  321. mass.I = 0;
  322. }
  323. _body.SetMassData(ref mass);
  324. }
  325. }
  326. public override void OnAdd()
  327. {
  328. if (_manager == null)
  329. {
  330. Logger.Warn(this, "OnAdd", "A Box2DSpatialComponent cannot be registered without a manager.");
  331. return;
  332. }
  333. _bodyDef.position *= _manager.InverseScale;
  334. _bodyDef.userData = this;
  335. _manager.Add(_bodyDef, (Body body) =>
  336. {
  337. _body = body;
  338. _bodyDef.position *= _manager.Scale;
  339. BuildCollisionShapes();
  340. if (OnAddedCallback != null)
  341. {
  342. OnAddedCallback(this);
  343. }
  344. });
  345. }
  346. public override void OnRemove()
  347. {
  348. _manager.Remove(_body);
  349. _body = null;
  350. }
  351. }
  352. }