PolyPhysicsScreen.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. /*
  2. * PolyPhysicsScreen.cpp
  3. * Poly
  4. *
  5. * Created by Ivan Safrin on 5/8/08.
  6. * Copyright 2008 __MyCompanyName__. All rights reserved.
  7. *
  8. */
  9. #include "PolyPhysicsScreen.h"
  10. using namespace Polycode;
  11. void PhysicsScreen::Add(const b2ContactPoint* point) {
  12. if (numContactPoints == MAX_B2DCONTACTPOINTS) {
  13. return;
  14. }
  15. ContactPoint* cp = m_points + numContactPoints;
  16. cp->shape1 = point->shape1;
  17. cp->shape2 = point->shape2;
  18. cp->position = point->position;
  19. cp->normal = point->normal;
  20. cp->id = point->id;
  21. cp->state = e_contactAdded;
  22. ++numContactPoints;
  23. }
  24. void PhysicsScreen::Persist(const b2ContactPoint* point) {
  25. if (numContactPoints == MAX_B2DCONTACTPOINTS) {
  26. return;
  27. }
  28. ContactPoint* cp = m_points + numContactPoints;
  29. cp->shape1 = point->shape1;
  30. cp->shape2 = point->shape2;
  31. cp->position = point->position;
  32. cp->normal = point->normal;
  33. cp->id = point->id;
  34. cp->state = e_contactPersisted;
  35. ++numContactPoints;
  36. }
  37. void PhysicsScreen::Remove(const b2ContactPoint* point) {
  38. if (numContactPoints == MAX_B2DCONTACTPOINTS) {
  39. return;
  40. }
  41. ContactPoint* cp = m_points + numContactPoints;
  42. cp->shape1 = point->shape1;
  43. cp->shape2 = point->shape2;
  44. cp->position = point->position;
  45. cp->normal = point->normal;
  46. cp->id = point->id;
  47. cp->state = e_contactRemoved;
  48. ++numContactPoints;
  49. }
  50. PhysicsScreen::PhysicsScreen() : Screen() {
  51. init(Vector2(-200.0f, -100.0f),Vector2(8500.0f, 1000.0f),1.0f/60.0f,10,Vector2(0.0f, 10.0f));
  52. }
  53. PhysicsScreen::PhysicsScreen(float freq) : Screen() {
  54. init(Vector2(-200.0f, -100.0f),Vector2(8500.0f, 1000.0f),1.0f/freq,10,Vector2(0.0f, 10.0f));
  55. }
  56. PhysicsScreen::PhysicsScreen(Vector2 physicsWorldLowerBound, Vector2 physicsWorldUpperBound)
  57. {
  58. init(physicsWorldLowerBound,physicsWorldUpperBound,1.0f/60.0f,10,Vector2(0.0f, 10.0f));
  59. }
  60. void PhysicsScreen::init(Vector2 physicsWorldLowerBound, Vector2 physicsWorldUpperBound, float physicsTimeStep, int physicsIterations, Vector2 physicsGravity) {
  61. numContactPoints = 0;
  62. timeStep = physicsTimeStep;
  63. iterations = physicsIterations;
  64. b2AABB worldAABB;
  65. worldAABB.lowerBound.Set(physicsWorldLowerBound.x/10.0,physicsWorldLowerBound.y/10.0);
  66. worldAABB.upperBound.Set(physicsWorldUpperBound.x/10.0,physicsWorldUpperBound.y/10.0);
  67. b2Vec2 gravity(physicsGravity.x,physicsGravity.y);
  68. bool doSleep = true;
  69. world = new b2World(worldAABB, gravity, doSleep);
  70. world->SetContactListener(this);
  71. updateTimer = new Timer(true, 3);
  72. updateTimer->addEventListener(this, Timer::EVENT_TRIGGER);
  73. }
  74. PhysicsScreenEntity *PhysicsScreen::getPhysicsByScreenEntity(ScreenEntity *ent) {
  75. for(int i=0; i<physicsChildren.size();i++) {
  76. if(physicsChildren[i]->getScreenEntity() == ent)
  77. return physicsChildren[i];
  78. }
  79. return NULL;
  80. }
  81. b2RevoluteJoint *PhysicsScreen::createRevoluteJoint(ScreenEntity *ent1, ScreenEntity *ent2, float ax, float ay, bool enableLimit, float lowerLimit, float upperLimit, bool motorEnabled, float motorSpeed, float maxTorque) {
  82. PhysicsScreenEntity *pEnt1 = getPhysicsByScreenEntity(ent1);
  83. PhysicsScreenEntity *pEnt2 = getPhysicsByScreenEntity(ent2);
  84. if(pEnt1 == NULL || pEnt2 == NULL)
  85. return NULL;
  86. b2Vec2 anchor((ent1->getPosition()->x+ax)/10.0f, (ent1->getPosition()->y+ay)/10.0f);
  87. b2RevoluteJointDef *jointDef = new b2RevoluteJointDef();
  88. jointDef->collideConnected = false;
  89. jointDef->lowerAngle = lowerLimit * (PI/180.0f);
  90. jointDef->upperAngle = upperLimit * (PI/180.0f);
  91. jointDef->enableLimit = enableLimit;
  92. jointDef->motorSpeed = motorSpeed;
  93. jointDef->maxMotorTorque = maxTorque;
  94. jointDef->enableMotor = motorEnabled;
  95. jointDef->Initialize(pEnt1->body, pEnt2->body, anchor);
  96. b2RevoluteJoint *joint = (b2RevoluteJoint*)world->CreateJoint(jointDef);
  97. return joint;
  98. }
  99. void PhysicsScreen::createPrismaticJoint(ScreenEntity *ent1, ScreenEntity *ent2, bool collideConnected) {
  100. }
  101. void PhysicsScreen::wakeUp(ScreenEntity *ent) {
  102. PhysicsScreenEntity *pEnt = getPhysicsByScreenEntity(ent);
  103. if(pEnt == NULL)
  104. return;
  105. pEnt->body->WakeUp();
  106. }
  107. void PhysicsScreen::setVelocity(ScreenEntity *ent, float fx, float fy) {
  108. PhysicsScreenEntity *pEnt = getPhysicsByScreenEntity(ent);
  109. if(pEnt == NULL)
  110. return;
  111. pEnt->body->WakeUp();
  112. b2Vec2 f = pEnt->body->GetLinearVelocity();
  113. if(fx != 0)
  114. f.x = fx;
  115. if(fy != 0)
  116. f.y = fy;
  117. pEnt->body->SetLinearVelocity(f);
  118. }
  119. void PhysicsScreen::setVelocityX(ScreenEntity *ent, float fx) {
  120. PhysicsScreenEntity *pEnt = getPhysicsByScreenEntity(ent);
  121. if(pEnt == NULL)
  122. return;
  123. pEnt->body->WakeUp();
  124. b2Vec2 f = pEnt->body->GetLinearVelocity();
  125. f.x = fx;
  126. pEnt->body->SetLinearVelocity(f);
  127. }
  128. void PhysicsScreen::setVelocityY(ScreenEntity *ent, float fy) {
  129. PhysicsScreenEntity *pEnt = getPhysicsByScreenEntity(ent);
  130. if(pEnt == NULL)
  131. return;
  132. pEnt->body->WakeUp();
  133. b2Vec2 f = pEnt->body->GetLinearVelocity();
  134. f.y = fy;
  135. pEnt->body->SetLinearVelocity(f);
  136. }
  137. PhysicsScreenEntity *PhysicsScreen::addCollisionChild(ScreenEntity *newEntity, int entType) {
  138. PhysicsScreenEntity *ret;
  139. ret = addPhysicsChild(newEntity, entType, 0,0.1,0, true);
  140. ret->collisionOnly = true;
  141. return ret;
  142. }
  143. void PhysicsScreen::applyForce(ScreenEntity *ent, float fx, float fy) {
  144. PhysicsScreenEntity *pEnt = getPhysicsByScreenEntity(ent);
  145. if(pEnt == NULL)
  146. return;
  147. pEnt->body->WakeUp();
  148. b2Vec2 f = b2Vec2(fx,fy);
  149. b2Vec2 p = pEnt->body->GetWorldPoint(b2Vec2(0.0f, 0.0f));
  150. pEnt->body->ApplyForce(f, p);
  151. }
  152. void PhysicsScreen::applyImpulse(ScreenEntity *ent, float fx, float fy) {
  153. PhysicsScreenEntity *pEnt = getPhysicsByScreenEntity(ent);
  154. if(pEnt == NULL)
  155. return;
  156. pEnt->body->WakeUp();
  157. b2Vec2 f = b2Vec2(fx,fy);
  158. b2Vec2 p = pEnt->body->GetWorldPoint(b2Vec2(0.0f, 0.0f));
  159. pEnt->body->ApplyImpulse(f, p);
  160. }
  161. void PhysicsScreen::createDistanceJoint(ScreenEntity *ent1, ScreenEntity *ent2, bool collideConnected) {
  162. PhysicsScreenEntity *pEnt1 = getPhysicsByScreenEntity(ent1);
  163. PhysicsScreenEntity *pEnt2 = getPhysicsByScreenEntity(ent2);
  164. if(pEnt1 == NULL || pEnt2 == NULL)
  165. return;
  166. b2Vec2 a1(ent1->getPosition()->x/10.0f, ent1->getPosition()->y/10.0f);
  167. b2Vec2 a2(ent2->getPosition()->x/10.0f, ent2->getPosition()->y/10.0f);
  168. b2DistanceJointDef *jointDef = new b2DistanceJointDef();
  169. jointDef->Initialize(pEnt1->body, pEnt2->body, a1, a2);
  170. jointDef->collideConnected = collideConnected;
  171. world->CreateJoint(jointDef);
  172. }
  173. b2MouseJoint *PhysicsScreen::createMouseJoint(ScreenEntity *ent1, Vector2 *mp) {
  174. PhysicsScreenEntity *pEnt1 = getPhysicsByScreenEntity(ent1);
  175. if(pEnt1 == NULL)
  176. return NULL;
  177. b2MouseJointDef *mj = new b2MouseJointDef();
  178. mj->body1 = world->GetGroundBody();
  179. mj->body2 = pEnt1->body;
  180. b2Vec2 mpos(mp->x/10.0f, mp->y/10.0f);
  181. mj->target = mpos;
  182. #ifdef TARGET_FLOAT32_IS_FIXED
  183. mj->maxForce = (pEnt1->body->GetMass() < 16.0)? (1000.0f * pEnt1->body->GetMass()) : float32(16000.0);
  184. #else
  185. mj->maxForce = 1000.0f * pEnt1->body->GetMass();
  186. #endif
  187. b2MouseJoint *m_mouseJoint = (b2MouseJoint*)world->CreateJoint(mj);
  188. pEnt1->body->WakeUp();
  189. Logger::log("OK %d!\n", m_mouseJoint);
  190. return m_mouseJoint;
  191. }
  192. Vector2 PhysicsScreen::getEntityCollisionNormal(ScreenEntity *ent1, ScreenEntity *ent2) {
  193. PhysicsScreenEntity *pEnt1 = getPhysicsByScreenEntity(ent1);
  194. PhysicsScreenEntity *pEnt2 = getPhysicsByScreenEntity(ent2);
  195. if(pEnt1 == NULL || pEnt2 == NULL)
  196. return Vector2(0,0);
  197. PhysicsScreenEntity *rEnt1;
  198. PhysicsScreenEntity *rEnt2;
  199. for (int32 i = 0; i < numContactPoints; ++i)
  200. {
  201. ContactPoint* point = m_points + i;
  202. if (point->state == 0 || point->state == 1) {
  203. rEnt1= getPhysicsEntityByShape(point->shape1);
  204. rEnt2 = getPhysicsEntityByShape(point->shape2);
  205. if((rEnt1 == pEnt1 && rEnt2 == pEnt2) ||
  206. (rEnt1 == pEnt2 && rEnt2 == pEnt1)) {
  207. return Vector2(point->normal.x,point->normal.y);
  208. }
  209. }
  210. }
  211. return Vector2(0,0);
  212. }
  213. bool PhysicsScreen::areEntitiesColliding(ScreenEntity *ent1, ScreenEntity *ent2) {
  214. PhysicsScreenEntity *pEnt1 = getPhysicsByScreenEntity(ent1);
  215. PhysicsScreenEntity *pEnt2 = getPhysicsByScreenEntity(ent2);
  216. if(pEnt1 == NULL || pEnt2 == NULL)
  217. return false;
  218. PhysicsScreenEntity *rEnt1;
  219. PhysicsScreenEntity *rEnt2;
  220. for (int32 i = 0; i < numContactPoints; ++i)
  221. {
  222. ContactPoint* point = m_points + i;
  223. if (point->state == 0 || point->state == 1) {
  224. rEnt1= getPhysicsEntityByShape(point->shape1);
  225. rEnt2 = getPhysicsEntityByShape(point->shape2);
  226. if((rEnt1 == pEnt1 && rEnt2 == pEnt2) ||
  227. (rEnt1 == pEnt2 && rEnt2 == pEnt1)) {
  228. return true;
  229. }
  230. }
  231. }
  232. return false;
  233. }
  234. ScreenEntity *PhysicsScreen::getEntityAtPosition(float x, float y) {
  235. ScreenEntity *ret = NULL;
  236. b2Vec2 mousePosition;
  237. mousePosition.x = x/10.0f;
  238. mousePosition.y = y/10.0f;
  239. for(int i=0;i<physicsChildren.size();i++) {
  240. PhysicsScreenEntity *ent = physicsChildren[i];
  241. if(ent->shape->TestPoint(ent->body->GetXForm(), mousePosition))
  242. return ent->getScreenEntity();
  243. }
  244. return ret;
  245. }
  246. bool PhysicsScreen::testEntityAtPosition(ScreenEntity *ent, float x, float y) {
  247. PhysicsScreenEntity *pEnt = getPhysicsByScreenEntity(ent);
  248. if(pEnt == NULL)
  249. return false;
  250. b2Vec2 mousePosition;
  251. mousePosition.x = x/10.0f;
  252. mousePosition.y = y/10.0f;
  253. if(pEnt->shape->TestPoint(pEnt->body->GetXForm(), mousePosition))
  254. return true;
  255. else
  256. return false;
  257. }
  258. void PhysicsScreen::destroyMouseJoint(b2MouseJoint *mJoint) {
  259. world->DestroyJoint(mJoint);
  260. mJoint = NULL;
  261. }
  262. PhysicsScreenEntity *PhysicsScreen::addPhysicsChild(ScreenEntity *newEntity, int entType, float friction, float density, float restitution, bool isSensor) {
  263. addChild(newEntity);
  264. newEntity->setPositionMode(ScreenEntity::POSITION_CENTER);
  265. PhysicsScreenEntity *newPhysicsEntity = new PhysicsScreenEntity(newEntity, world, entType, friction, density, restitution, isSensor);
  266. physicsChildren.push_back(newPhysicsEntity);
  267. newPhysicsEntity->body->WakeUp();
  268. return newPhysicsEntity;
  269. }
  270. void PhysicsScreen::removePhysicsChild(PhysicsScreenEntity *entityToRemove) {
  271. world->DestroyBody(entityToRemove->body);
  272. removeChild(entityToRemove->getScreenEntity());
  273. for(int i=0;i<physicsChildren.size();i++) {
  274. if(physicsChildren[i] == entityToRemove) {
  275. physicsChildren.erase(physicsChildren.begin()+i);
  276. }
  277. }
  278. }
  279. void PhysicsScreen::Shutdown() {
  280. }
  281. PhysicsScreen::~PhysicsScreen() {
  282. delete world;
  283. for(int i=0; i<physicsChildren.size();i++) {
  284. delete physicsChildren[i];
  285. }
  286. }
  287. PhysicsScreenEntity *PhysicsScreen::getPhysicsEntityByShape(b2Shape *shape) {
  288. for(int i=0; i < physicsChildren.size(); i++) {
  289. if(physicsChildren[i]->shape == shape)
  290. return physicsChildren[i];
  291. }
  292. return NULL;
  293. }
  294. void PhysicsScreen::handleEvent(Event *event) {
  295. numContactPoints = 0;
  296. if(event->getDispatcher() == updateTimer) {
  297. world->Step(timeStep, iterations);
  298. }
  299. for (int32 i = 0; i < numContactPoints; ++i)
  300. {
  301. ContactPoint* point = m_points + i;
  302. if (point->state == 0) {
  303. PhysicsScreenEvent *newEvent = new PhysicsScreenEvent();
  304. newEvent->entity1 = getPhysicsEntityByShape(point->shape1);
  305. newEvent->entity2 = getPhysicsEntityByShape(point->shape2);
  306. dispatchEvent(newEvent, PhysicsScreenEvent::EVENT_NEW_SHAPE_COLLISION);
  307. } else if (point->state == 1) {
  308. // Persist
  309. // DrawPoint(point->position, 5.0f, b2Color(0.3f, 0.3f, 0.95f));
  310. } else {
  311. // Remove
  312. // DrawPoint(point->position, 10.0f, b2Color(0.95f, 0.3f, 0.3f));
  313. dispatchEvent(new PhysicsScreenEvent(), PhysicsScreenEvent::EVENT_END_SHAPE_COLLISION);
  314. }
  315. }
  316. Screen::handleEvent(event);
  317. }
  318. void PhysicsScreen::Update() {
  319. // unsigned int elapsed = updateTimer->getTicks();
  320. // if(updateTimer->hasElapsed()) {
  321. // world->Step(timeStep, iterations);
  322. for(int i=0; i<physicsChildren.size();i++) {
  323. physicsChildren[i]->Update();
  324. }
  325. // }
  326. }