PolyPhysicsScreen.cpp 13 KB

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